Я пытаюсь понять больше о process 0
, например, есть ли у него дескриптор памяти (поле, отличное от NULL
task_struct->mm
) или нет, и как он связан с процессом подкачки или бездействия. Мне кажется, что на загрузочном процессоре создается один «процесс 0», а затем для каждого другого процессора создается поток бездействия с помощью idle_threads_init
, но я не нашел, где был создан первый (я предполагаю, что это process 0
).
Обновить
В свете живой книги, на которую ссылается Tychen, вот мое самое последнее понимание относительно process 0
(для x86_64), может ли кто-нибудь подтвердить/опровергнуть пункты ниже?
init_task
с типомtask_struct
определяется статически, со стеком ядра задачиinit_task.stack = init_stack
, дескрипторами памятиinit_task.mm=NULL
иinit_task.active_mm=&init_mm
, где область стекаinit_stack
иmm_struct
init_mm
определены статически.- Тот факт, что только
active_mm
не равен NULL, означает, чтоprocess 0
является процессом ядра. Кроме того,init_task.flags=PF_KTHREAD
. - Вскоре после начала выполнения несжатого образа ядра загрузите процессор начинает использовать
init_stack
в качестве стека ядра. Это делает макросcurrent
осмысленным (впервые с момента загрузки машины), что делает возможнымfork()
. После этого ядро буквально работает в контекстеprocess 0
. start_kernel
->arch_call_rest_init
->rest_init
, и внутри этой функцииprocess 1&2
разветвляются. В функцииkernel_init
, запланированной дляprocess 1
, новый поток (сCLONE_VM
) создается и подключается к очереди выполнения ЦПrq->idle
для каждого другого логического ЦП.- Интересно, что все бездействующие потоки используют один и тот же
tid 0
(а не толькоtgid
). Обычно потоки разделяютtgid
, но имеют разныеtid
, которые на самом деле являютсяprocess id
в Linux. Я думаю, это ничего не ломает, потому что простаивающие потоки привязаны к своим собственным процессорам. kernel_init
загружает исполняемый файлinit
(обычно/sbin/init
), переключаетcurrent
->mm
иactive_mm
на ненулевойmm_struct
и сбрасывает флагPF_KTHREAD
, что делаетprocess 1
законным процессом пользовательского пространства. Хотяprocess 2
не настраиваетmm
, то есть он остается процессом ядра, таким же, какprocess 0
.- В конце
rest_init
берет на себяdo_idle
, что означает, что все процессоры имеют простаивающий процесс. - Раньше меня что-то смущало, но теперь становится ясно:
init_task
/init_mm
/init_stack
все объекты/метки, такие какinit_task
/init_mm
/init_stack
, используютсяprocess 0
, а неinit process
, который являетсяprocess 1
.