Якщо нитки мають однаковий PID, як їх можна ідентифікувати?


98

У мене є запит, пов'язаний з реалізацією потоків в Linux.

Linux не має явної підтримки потоків. У просторі користувачів ми можемо використовувати бібліотеку потоків (як NPTL) для створення потоків. Тепер, якщо ми використовуємо NPTL, він підтримує відображення 1: 1.

Ядро буде використовувати clone()функцію для реалізації потоків.

Припустимо, я створив 4 теми. Тоді це означало б, що:

  • Буде 4 task_struct.
  • Всередині task_structбуде передбачено розподіл ресурсів відповідно до аргументів для клонування (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND).

Тепер у мене є такий запит:

  1. Чи будуть 4 потоки мати однаковий PID? Якщо хтось може розробити, як поділяються PID.
  2. Як ідентифікуються різні нитки; чи є якась концепція TID (ID потоку)?

Відповіді:


274

Чотири потоки матимуть той самий PID, але лише при огляді зверху. Те, що ви (як користувач) називаєте PID - це не те, що ядро ​​(дивлячись знизу) називає PID.

У ядрі кожен потік має власний ідентифікатор, який називається PID (хоча, можливо, було б більш розумно називати це TID або ідентифікатор потоку), і вони також мають TGID (ідентифікатор групи потоків), який є PID потоку що розпочало весь процес.

Спрощено, коли створюється новий процес , він відображається у вигляді потоку, де і PID, і TGID є однаковим (новим) номером.

Коли потік запускає інший потік, цей запущений потік отримує свій власний PID (тому планувальник може планувати його самостійно), але він успадковує TGID від вихідного потоку.

Таким чином, ядро ​​може із задоволенням планувати потоки, незалежно від того, до якого процесу вони належать, тоді як вам повідомляються процеси (ідентифікатори груп потоків).

Наступна ієрархія потоків може допомогти (a) :

                      USER VIEW
 <-- PID 43 --> <----------------- PID 42 ----------------->
                     +---------+
                     | process |
                    _| pid=42  |_
                  _/ | tgid=42 | \_ (new thread) _
       _ (fork) _/   +---------+                  \
      /                                        +---------+
+---------+                                    | process |
| process |                                    | pid=44  |
| pid=43  |                                    | tgid=42 |
| tgid=43 |                                    +---------+
+---------+
 <-- PID 43 --> <--------- PID 42 --------> <--- PID 44 --->
                     KERNEL VIEW

Ви можете бачити, що запуск нового процесу (зліва) дає вам новий PID та новий TGID (обидва встановлені на одне значення), а запуск нового потоку (справа) дає вам новий PID, зберігаючи той самий TGID як нитка, яка його запустила.


(а) тремтіти в захваті від моїх вражаючих графічних навичок :-)


20
FYI, getpid()повертає tgid:, asmlinkage long sys_getpid(void) { return current->tgid;}як показано на www.makelinux.com/
Герцог

6
@Duke - нічого собі, тому я не міг знайти gettgid(2)функцію. І getpid()не повертає TID ("PID" потоку), і там де gettid(2)входить. Таким чином я можу сказати, якщо ми в основному потоці чи ні.
Томаш Гандор,

2
Це призводить до іншого цікавого моменту: Отже, якщо потоки та процеси обробляються однаково всередині ядра (крім tgid), багатопотоковий процес отримає на закінчення більше часу процесора, ніж однопотоковий, за умови, що обидва мають однакові пріоритет, і жоден з потоків не зупиняється з будь-якої причини (наприклад, очікування мутекса).
Аконкагуа

1
@Aconcagua, CFS (повністю справедливий планувальник у Linux), як правило, працює таким чином, але також дозволяє використовувати розширення групового планувальника, щоб чесність працювала в певних групах завдань, а не в окремих завданнях. Я ніколи насправді не дивився на це, окрім побіжного погляду.
paxdiablo

'' getpgrp '', щоб отримати ідентифікатор групи
Pengcheng

2

Потоки ідентифікуються за допомогою PID і TGID (ідентифікатор групи потоків). Вони також знають, який потік є батьківським, хто так по суті процес ділиться своїм PID з будь-якими потоками, які він починає. Ідентифікаторами ниток зазвичай керує сама бібліотека потоків (наприклад, pthread тощо). Якщо запущено 4 потоки, вони повинні мати однаковий PID. Ядро саме буде обробляти планування потоків і тому подібне, але бібліотека - це та, яка буде керувати потоками (незалежно від того, чи можуть вони працювати, чи ні, залежно від використання методів приєднання та очікування потоку).

Примітка. Це з мого спогаду ядра 2.6.36. Моя робота в поточних версіях ядра знаходиться в шарі вводу / виводу, тому я не знаю, чи змінилося це відтоді.


-6

Linux забезпечує fork()системний виклик традиційною функціональністю дублювання процесу. Linux також надає можливість створювати потоки за допомогою clone()системного виклику. Однак Linux не розрізняє процеси та потоки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.