Продолжаем разговор о конкурентности. В прошлом посте были базовые определения связанные с потоками. Сегодня погружаемся во внутренности на примере ядра Linux.
Несколько предварительных фактов о ядре Linux:
Ядро Linux оперирует задачами (tasks). Задача - "что-то", что можно запустить и заменеджить. До появления многопоточности процесс и задача в Linux были синонимами.
- Каждый процесс в системе имеет два идентификатора - Process ID (
PID ) и Thread Group ID ( TGID )- В "обычном" последовательном процессе
PID == TGID.- В "многопоточном" процессе
TGID общий на группу процессов.- Процессы с общим
TGID имеют общие ресурсы.- Если «многопоточный» процесс имеет
PID == TGID, то мы имеем дело с «основным потоком» процессаЕсли погружаться в системные вызовы то:
- Вызов
getpid() из любого процесса вернет его TGID (= PID "главного потока")- Вызов
gettid() из любого процесса вернет его PID- Любой тип процесса (раздельные ресурсы, общие) может быть создан с помощью
clone(2) системного вызова- Что будет совместно использоваться процессами, решается путем передачи определенных флагов в вызов функции
clone(2)Директория `/proc`:
- имена папок в директории
/proc - это Thread Group ID идентификаторы.- имена папок в директории
/proc/{SOME_TGID}/task - это PIDы потоков.Вывод
С точки зрения ядра существуют только процессы, каждый из которых имеет свой собственный уникальный PID, а так называемый поток — это просто другой вид процесса (разделяющий, по крайней мере, одно и то же пространство памяти и обработчики сигналов с одним или несколькими другими).
Примечание:
getpid() возвращает `TGID` вместо `PID` не просто так. Это сделано для совместимости c POSIX стандартом (потоки должны шарить между собой общий `PID`).