Если потоки используют один и тот же 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 потока)?
SPSN
источник

Ответы:

275

У четырех потоков будет один и тот же PID, но только если смотреть сверху. То, что вы (как пользователь) называете PID, не является тем, что ядро ​​(если смотреть снизу) называет PID.

В ядре каждый поток имеет свой собственный идентификатор, называемый PID (хотя, возможно, было бы разумнее называть его TID или идентификатором потока), и у них также есть TGID (идентификатор группы потоков), который является PID потока. с этого начался весь процесс.

Проще говоря, когда создается новый процесс , он отображается как поток, в котором PID и TGID имеют одинаковый (новый) номер.

Когда поток запускает другой поток, этот запущенный поток получает свой собственный PID (поэтому планировщик может планировать его независимо), но наследует TGID от исходного потока.

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

Следующая иерархия потоков может помочь (а) :

                      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 как поток, который его запустил.


(а) Трепет перед моими впечатляющими графическими навыками :-)

Paxdiablo
источник
20
К вашему сведению, getpid()возвращает tgid:, asmlinkage long sys_getpid(void) { return current->tgid;}как показано на www.makelinux.com/
Duke
6
@ Duke - вау, вот почему я не смог найти gettgid(2)функцию. И getpid()он не вернет TID («PID» потока), и вот gettid(2)что нужно сделать. Таким образом я могу сказать, находимся мы в основном потоке или нет.
Tomasz Gandor
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 не делает различий между процессами и потоками.

САУНДАРЬЯ КУМАР ГУПТА
источник