Вопрос или проблема
Когда ядро загружается в initramfs, запускается процесс init, который делает некоторые приготовления для настоящей rootfs. Когда настоящая rootfs готова, процесс init в initramfs должен передать управление другому init из настоящей rootfs.
Мой вопрос:
когда init(старый) уже имеет идентификатор процесса 1, как новый процесс init может также иметь идентификатор процесса 1?
Кто-то говорит, что передача управления осуществляется с помощью команды switch_root
, я прочитал код и выяснил, что switch_root только монтирует /dev
, /proc
и т.д., меняет root на новую fs и затем выполняет execv(/sbin/init)
.
switch_root
должен выполняться как дочерний процесс init(старого) и иметь идентификатор процесса 2, 3 или любой другой, но не 1. верно?
Ответ или решение
В контексте работы с операционными системами Linux, процесс инициализации системы является критическим этапом, который требует особого внимания и тщательного понимания. При запуске ядра в initramfs, первое (и единственное на тот момент) пространство выполнения создаёт процесс init, который начинает выполнение с идентификатором процесса (PID) равным 1. Основная задача этого процесса — подготовить "настоящее" корневое файловое пространство (root filesystem) перед передачей управления следующему init. Этот процесс передачи управления осуществляется с использованием команды switch_root
. Давайте подробно разберем, каким образом выполняется передача и как происходит приобретение новым init PID, равного 1.
Теория
Процесс с PID 1 является особенным в UNIX-подобных системах. Этот процесс всегда является начальной инициализацией системы и, по сути, "родителем" всех других процессов в системе. При перезагрузке системы или после её включения, PID 1 выполняет функцию активатора для всех других процессов, начиная с инициализации оборудования и заканчивая запуском пользовательских приложений. Таким образом, init (или systemd, как в некоторых современных дистрибутивах) обеспечивает контроль за жизненным циклом всех процессов.
Ключевая проблема, как упомянуто в вопросе, заключается в следующем: если процесс init из initramfs уже имеет PID 1, как может новый init также иметь PID 1 после смены корневой файловой системы? В этом контексте switch_root
является утилитой, которая играет важную роль в смене "фокуса" операционной системы с временной корневой файловой системы (initramfs) на настоящую корневую файловую систему.
Пример
Итак, как же switch_root
справляется с этой задачей? Когда ядро загружается поначалу в initramfs, init в этой среде создает временную файловую систему, подготавливая условия для основной файловой системы. Затем, когда все необходимые ресурсы и зависимости инициализированы, switch_root
используется для смены корневой файловой системы и последующего выполнения нового процесса init с новым PID.
switch_root
работает следующим образом:
-
Монтирование необходимых файловых систем:
switch_root
заботится о том, чтобы смонтировать такие виртуальные файловые системы, как/dev
,/proc
, и другие, необходимые для функционирования системы. -
Перемещение корневой файловой системы: С помощью системного вызова
pivot_root
(или аналогичного механизма в реализацииswitch_root
), временная файловая система (initramfs) перемещается, а реальная файловая система становится новой корневой. -
Передача управления: Наиболее важный момент заключается в том, что
switch_root
, выполнив вышеописанные действия, завершает текущий процесс сexecv
, сменяя тем самым процесс выполнения на новый init в новой корневой системе. Благодаря вызовуexec
, процесс не создается как новый (с новым PID), а продолжается в новом контексте с тем же PID, что позволяет новому init унаследовать PID 1.
Применение
Как было упомянуто, в результате вызова execv
в switch_root
, процесс init никак не происходит как новый экземпляр процесса с новым PID. Способность прямой передачи управления функций в UNIX системах через exec
позволяет передать управление новым процессом, не изменив при этом идентификатор текущего процесса. Именно поэтому switch_root
не создает новый дочерний процесс с другим PID, а продолжает текущий процесс в новом контексте файловой системы.
Заключение
Применение switch_root
в процессе смены корневой файловой системы иллюстрирует важную функциональность UNIX-подобных систем по управлению процессами. Используя execv
, и сохраняя идентификатор процесса на уровне PID 1, система может плавно передать управление новому init, не нарушая функциональности системы и не создавая дубликатов процессов. Это гарантирует стабильность и предсказуемость работы системы в процессе инициализации.
Данный механизм имеет широкий спектр применения и жизненно важен в контексте обслуживания и управления операционными системами. Владение этими базовыми принципами критично для инженеров, работающих с низкоуровневыми процессами и системной архитектурой в Linux, что обеспечивает высокую устойчивость и надежность работы систем в самых разнообразных условиях.