Как внутреннее отключение системы ядра Linux?

28

У меня есть какое-то приблизительное представление о том, как пользовательское пространство и init-система (будь то классическая init sysV / upstart / systemd) работают при выключении системы. (По сути, есть последовательность заказов: «Стоп!», «Пожалуйста, остановите сейчас действительно», «Процесс, который мне нужен, чтобы убить вас, чтобы остановить» и ожидание ... что-то происходит).

В любом случае, я не очень понимаю, как происходит отключение системы в ядре (где, конечно же, есть много чего сделать)?

Я попытался заглянуть в документацию ядра https://www.kernel.org/doc/htmldocs/ и даже использовал инструмент поиска АНБ, чтобы дать мне понять, как он работает.

Также я искал на SE U + L и ничего не нашел (я это пропустил?)

В любом случае, этот вопрос, хотя и может быть немного сложным, заслуживает ответа в этой сети вопросов и ответов, так как я предполагаю, что все больше людей заинтересованы в получении эскиза того, что происходит в ядре Linux при завершении работы.

Потенциально есть также изменение, чтобы ссылаться на некоторые более подробные объяснения.

Возможно, ответ будет включать какие системные вызовы и какие сигналы ядра используются?

https://github.com/torvalds/linux/blob/b3a3a9c441e2c8f6b6760de9331023a7906a4ac6/arch/x86/kernel/reboot.c, похоже, используется x86-файл, связанный с перезагрузкой (уже близко к завершению работы, а?)

может быть, фрагмент, найденный здесь http://lxr.free-electrons.com/source/kernel/reboot.c#L176, можно использовать для объяснения

176 void kernel_power_off (void)
177 {
178 kernel_shutdown_prepare (SYSTEM_POWER_OFF);
179 if (pm_power_off_prepare)
180 pm_power_off_prepare ();
181 migrate_to_reboot_cpu ();
182 syscore_shutdown ();
183 pr_emerg («Выключить \ n»);
184 kmsg_dump (KMSG_DUMP_POWEROFF);
185 machine_power_off ();
186}
187 EXPORT_SYMBOL_GPL (kernel_power_off);
humanityANDpeace
источник
8
да
пребудет
1
@Kiwy спасибо за предложение. Я приму через некоторое время потенциальные лучшие ответы. Но, по крайней мере, какой-то ответ сейчас есть.
человечествоANDpeace
Не благодари меня, спасибо Единорог!
Kiwy
Имейте в виду, что есть / была выпрыгнутая опция окна,shutdown(8) то есть устаревшая, -n которую я думаю в старой документации Unix, используемой для чтения « выключите систему самостоятельно - основной блок включен на пожаре! », Фактически запутанный переключатель блокировки системы, который оставил бы / мог бы разбросать биты по полу (или, по крайней мере, файловые системы в поврежденном состоянии) - можно представить, что это будет использоваться для системы типа основной рамы, где кто-то только что схватил их за руку в охлаждающий вентилятор. Ly
SlySven

Ответы:

26

Основные ресурсы, чтобы понять, как работает ядро ​​Linux:

  1. Документации .
  2. Linux Weekly News статьи .
  3. Источник. Это сложный зверь, которого немного легче понять с помощью LXR , перекрестной ссылки Linux. Вариант LXR, работающий на lxr.linux.no , лучше других, но часто не работает.

В этом случае я не могу найти что-либо центрально релевантное в документации или на LWN, так что LXR это так.

Последнее, что делает код пользователя, - это вызывает rebootсистемный вызов . Требуется 4 аргумента, поэтому ищите SYSCALL_DEFINE4(rebootна LXR, что приводит к kernel/reboot.c. После проверки привилегий вызывающего абонента и аргументов, точка входа системного вызова вызывает один из нескольких функций: kernel_restartдля перезагрузки, kernel_haltчтобы остановить на тугую петле, kernel_poweroffчтобы отключить питание системы, kernel_kexecчтобы заменить ядро на новом (если скомпилированы в), или hibernateсохранить память на диск перед выключением.

kernel_restart, kernel_haltИ kernel_power_offдовольно похожи:

  1. Пройдите reboot_notifier_list, это список хуков, которые компоненты ядра могут зарегистрировать для выполнения кода при отключении питания. На этом этапе для выполнения кода требуется всего несколько драйверов, в основном это сторожевые таймеры.
  2. Установите system_stateпеременную.
  3. Отключите usermode-helper , чтобы гарантировать, что пользовательский код больше не будет запускаться. (На этом этапе все еще могут быть существующие процессы.)
  4. Позвоните, device_shutdownчтобы отключить или отключить все устройства в системе. Многие водители подключаются к этой стадии.
    Обратите внимание, что любые файловые системы, которые все еще смонтированы в этой точке, эффективно размонтированы принудительно. Вызывающий системный вызов несет ответственность за любую чистую размонтировку.
  5. Только для выключения питания, если настроен ACPI, возможно, выполните код, чтобы подготовиться к переходу в состояние ACPI S5 (плавное выключение).
  6. В многопроцессорной машине код может выполняться на любом процессоре, который бы ни вызывал системный вызов. migrate_to_reboot_cpuзаботится о переключении на один конкретный процессор и не позволяет планировщику отправлять код на другие процессоры. После этого запускается только один процессор.
  7. syscore_shutdownвызывает shutdownметод зарегистрированных операций syscore . Я думаю, что это в основном отключение прерываний; У нескольких крючков есть shutdownметод.
  8. Записать информационное сообщение - лебединую песню.
  9. Наконец ехать на отдых в какой - то машинно-зависимым способом путем вызова machine_restart, machine_haltили machine_power_off.

Гибернации код проходит через следующие этапы:

  1. Итерируйте через хуки управления питанием .
  2. Синхронизация файловых систем.
  3. Заморозить весь код пользователя .
  4. Предотвратить горячее подключение устройства .
  5. Дамп состояния системы в пространство подкачки.
  6. Если все прошло успешно, переведите оборудование в спящий режим . Это может включать вызов kernel_restart, kernel_haltили kernel_power_off, или какой-либо специфичный для платформы метод гибернации.

Другой способ выключить систему machine_emergency_restart. Это вызывается волшебным ключом SysRqB . OКлюч работает по- другому: он вызываетkernel_power_off .

Система также может отключиться от паники , то есть неисправимой ошибки. Паника пытается зарегистрировать сообщение, а затем перезагрузить систему (через аппаратный сторожевой таймер или аварийный перезапуск).

Жиль "ТАК - перестань быть злым"
источник
+1 спасибо! @Gilles, если вы хотите реализовать какой-то код, который будет стирать / санировать ОЗУ машины как последний шаг, вы зарегистрируете для нее операцию syscore syscore_shutdown(то есть это решит мой другой вопрос unix.stackexchange.com/q/122540/24394 ) , Оба шага (1) и шаг (7) позволяют зарегистрировать материал, который будет выполняться при выключении, не стесняясь, что + У меня сложилось впечатление, что на порядок выполнения этих обратных вызовов в (1) и (7) нельзя повлиять! Я буду документы, которые вы упомянули, но если вы знаете! Благодарность!
человечествоANDpeace
Я удивлен этим вопросом, и ответа больше нет.
2

Это только частичный ответ, и я наверняка предлагаю другой ответ, который может быть более исчерпывающим и ясным.

Содержание этого ответа взято из kernel/reboot.cфайла ядра Linux 3.13 (что может быть не первым предположением, поскольку имя не shutdown.c, а reboot.c)

В любом случае, у нас есть три основные функции, которые определяют процесс выключения системы.

  • void kernel_halt(void) // который заканчивается системой в состоянии остановки
  • void kernel_power_off(void) // который заканчивается отключением системы
  • void kernel_restart(char *cmd) // который завершает систему, чтобы перезапустить ее

Эти функции очень кратки и поэтому могут быть вставлены здесь полностью. Их код лучше всего показывает, какие шаги предпринимаются на пути к выключению в ядре. (комментарии сделаны мной и не могут быть на 100% идеальными и правильными, проверьте себя на предмет уверенности. Это просто попытка.

void kernel_halt(void)

void kernel_halt (void)
{
    // 1-й шаг делает:
    // а) вызов функций / обратный вызов зарегистрирован для запуска при перезагрузке / выключении
    // b) установить system_sate в SYSTEM_HALT
    // c) остановить взаимодействие с userpacetool
    // d) вызвать функцию device_shutdown ()
    kernel_shutdown_prepare (SYSTEM_HALT);

    // 2-й шаг: я думаю, что это в основном необходимо для систем с несколькими процессорами
    migrate_to_reboot_cpu ();

    // 3-й шаг:
    // syscore_shutdown - выполнение всех зарегистрированных обратных вызовов выключения ядра системы 
    syscore_shutdown ();

    // 4-е сообщения
    pr_emerg ("Система остановлена ​​\ n");
    kmsg_dump (KMSG_DUMP_HALT);

    // специфичный для 5-й арки вызова cpu-halt-code
    machine_halt ();
}

все это инициируется sys_rebootсистемным вызовом, который, учитывая, что он не только перезагружается, но и завершает работу, не является прямой связью с процессом завершения работы в любом случае.

humanityANDpeace
источник