Спасибо за комментарии выше. После некоторых исследований я готов дать себе более полный ответ, ниже:
По крайней мере, для архитектуры x86 лучше всего использовать reboot(LINUX_REBOOT_CMD_HALT)
. Это, в свою очередь, вызывает системный вызов reboot()
(см.: http://lxr.linux.no/linux+v3.6.6/kernel/sys.c#L433). Затем для флага LINUX_REBOOT_CMD_HALT
(см.: http://lxr.linux.no/linux+v3.6.6/kernel/sys.c#L480), системный вызов вызывает kernel_halt()
(определено здесь: http://lxr.linux.no/linux+v3.6.6/kernel/sys.c#L394). Эта функция вызывает syscore_shutdown() для выполнения всех зарегистрированных обратных вызовов завершения работы ядра системы, отображает сообщение «Система остановлена», затем сбрасывает дамп ядра И, наконец, вызывает machine_halt()
, который является оболочкой для native_machine_halt()
(см.: http://lxr.linux.no/linux+v3.6.6/arch/x86/kernel/reboot.c#L680). Именно эта функция останавливает другие ЦП (через machine_shutdown()
), затем вызывает stop_this_cpu()
для отключения последнего оставшегося работающего процессора. Первое, что делает эта функция, — отключает прерывания на текущем процессоре, то есть планировщик больше не может взять на себя управление.
Я не уверен, почему системный вызов reboot()
все еще вызывает do_exit(0)
после вызова kernel_halt()
. Я интерпретирую это так: теперь, когда все процессоры помечены как отключенные, системный вызов reboot()
вызывает do_exit(0)
и завершается. Даже если планировщик пробужден, больше нет включенных процессоров, на которых он мог бы запланировать какое-либо задание или прерывание: система остановлена. Я не уверен в этом объяснении, так как stop_this_cpu()
, похоже, не возвращается (он входит в бесконечный цикл). Может быть, это просто защита, на тот случай, когда stop_this_cpu()
выйдет из строя (и вернется): в этом случае do_exit()
завершит текущую задачу начисто, затем будет вызвана функция panic()
.
Что касается кода panic()
(определенного здесь: http://lxr.linux.no/linux+v3.6.6/kernel/panic.c#L69), функция сначала отключает локальные прерывания, затем отключает все остальные процессоры, кроме текущего, вызывая smp_send_stop()
. Наконец, как единственная задача, выполняемая на текущем процессоре (который является единственным живым процессором), со всеми отключенными локальными прерываниями (то есть у вытесняемого планировщика — в конце концов, прерывания по таймеру — нет шансов...) , то функция panic()
какое-то время зацикливается или вызывает emergency_restart()
, которая должна перезапустить процессор.
Если у вас есть лучшее понимание, пожалуйста, внесите свой вклад.
person
user1284631
schedule
16.11.2012
panic()
чем-то похожа на UNIX, я думаю, что это на самом деле зависит от машины и от того, как запланирован упреждающий планировщик. Принимая во внимание, что Linux очень хорошо спроектирован и безопасность обычно имеет первостепенное значение, я почти уверен, чтоpanic()
останавливает планировщик. - person Linuxios   schedule 12.11.2012