Как команда switch_root делает /sbin/init в новой файловой системе процессом с PID 1?

Вопрос или проблема

Когда ядро загружается в 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 работает следующим образом:

  1. Монтирование необходимых файловых систем: switch_root заботится о том, чтобы смонтировать такие виртуальные файловые системы, как /dev, /proc, и другие, необходимые для функционирования системы.

  2. Перемещение корневой файловой системы: С помощью системного вызова pivot_root (или аналогичного механизма в реализации switch_root), временная файловая система (initramfs) перемещается, а реальная файловая система становится новой корневой.

  3. Передача управления: Наиболее важный момент заключается в том, что 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, что обеспечивает высокую устойчивость и надежность работы систем в самых разнообразных условиях.

Оцените материал
Добавить комментарий

Капча загружается...