Ну, это зависит от операционной системы, о которой вы говорите, но для многих создание процесса включает в себя создание одного потока для этого процесса.
Затем этот поток может свободно создавать и создавать другие потоки, принадлежащие процессу.
Нет смысла говорить о процессе без потоков, поскольку это означает, что для этого процесса не выполняется код, поэтому он не может ничего сделать полезного.
Например, в ядре Linux создание процесса мало отличается от создания нового потока. Это потому, что ядро планирует потоки, а не процессы.
Процессы теперь считаются группами потоков с одинаковым идентификатором группы потоков (TGID), причем TGID является идентификатором потока (TID) первого потока, созданного для этого процесса.
Когда вы fork
или vfork
или clone
(без CLONE_THREAD
), вы получаете новый поток с новым TID, и TGID устанавливается на этот TID - это новый процесс.
Когда вы clone
с CLONE_THREAD
, вы получаете новый поток с новым TID, но TGID остается таким же, как ваш клонер. Это другой поток в том же процессе.
Вот так Linux (в качестве примера) различает процессы и потоки, не делая планировщик слишком сложным. Планировщик может по своему усмотрению полностью игнорировать группы потоков. Это на самом деле невероятно умно.
Для кодирования вне планировщика, группа потоков с одинаковым TGID считается процессом.
Это включает в себя как код пользовательского пространства , так и другие биты ядра, поскольку, например, то, как потоки сгруппированы в процессы, влияет на такие вещи, как доставка сигналов и коды выхода.