LINUX_REBOOT_CMD_RESTART2
(0xa1b2c3d4;自 Linux 2.1.30 起)。打印消息“Restarting system with command '%s'”,并立即执行重新启动(使用 arg 中给出的命令字符串)。如果前面没有同步(2),数据将会丢失。
在关机过程中,arg 中给出的命令字符串到底是如何以及何时执行的?
https://unix.stackexchange.com/a/489651/674说关于LINUX_REBOOT_CMD_RESTART2
这里的一个额外的混乱是由于
reboot()
系统调用似乎能够运行一个进程来进行重新启动(但是这是有效的)
arg 中给出的命令字符串是在内核关闭之前运行的,那么该命令可以在内核关闭之前进行一些清理吗?
谢谢。
答案1
该命令是不是在关闭过程中执行。它不是 shell 命令或类似命令;它是一个字符串,应该作为回调数据(通过machine_restart()
=> )传递给由某些驱动程序(看门狗等)do_kernel_restart()
注册的重新启动处理程序。register_restart_handler()
但 x86 上并未使用该机制;那里的“命令”被完全忽略。从arch/x86/kernel/reboot.c
:
void machine_restart(char *cmd) { machine_ops.restart(cmd); struct machine_ops machine_ops __ro_after_init = { ... .restart = native_machine_restart, static void native_machine_restart(char *__unused) {
该字符串也将传递给注册的处理程序register_reboot_notifier()
。唯一(滥用)使用的驱动程序似乎是EFI 引导加载程序控制这是设置非挥发性LoaderEntryOneShot
来自它的 EFI 变量,导致一些引导加载程序确定接下来应该引导哪个操作系统。我认为该驱动程序从未在 Android 之外使用过——但无论如何它看起来都很笨重,因为它在旧的 lkml 中也有详细介绍讨论关于同一件事的先前版本。
答案2
它没有被执行。该命令具有相应的数值,该数值被传递到重新启动模式驱动程序以写入重新启动原因寄存器。重新启动后,引导加载程序从寄存器中读取原因值,并根据所选命令决定启动,例如快速启动、恢复等。
例如,基于 Qualcomm MSM8916 SOC 的手机具有 Power On 设备,其中包含这样的重启原因寄存器。命令(以 形式mode-<command>
)和相应的原因值在其中描述设备树:
pon@800 {
compatible = "qcom,pm8916-pon";
reg = <0x800>;
mode-bootloader = <0x2>;
mode-recovery = <0x1>;
因此,当reboot(2)
使用bootloader
命令字符串调用时,司机对于开机设备写入0x2
重新启动原因寄存器。
下次启动时,引导加载程序(例如 lk2nd)会检查原因寄存器并启动到适当的模式(从aboot_init()
inaboot.c):
#if USE_PON_REBOOT_REG
reboot_mode = check_hard_reboot_mode();
#else
reboot_mode = check_reboot_mode();
#endif
if (reboot_mode == RECOVERY_MODE)
{
boot_into_recovery = 1;
}
else if(reboot_mode == FASTBOOT_MODE)
{
boot_into_fastboot = true;
}
RECOVERY_MODE
并FASTBOOT_MODE
在 lk2nd 中定义重新启动.h并具有与上面设备树中相同的值(除了“fastboot”被称为“bootloader”):
#define RECOVERY_MODE 0x01
#define FASTBOOT_MODE 0x02
我不知道可以使用命令重新启动来测试此行为的实用程序,但您可以使用 ctypes 在 python 中执行此操作:
python -c "import ctypes; ctypes.CDLL('libc.so').syscall(142, 0xfee1dead, 0x20112000, 0xa1b2c3d4, b'bootloader')"
142
上面是reboot(2)
arm64上的系统调用号。十六进制魔法数字来自man 2 reboot
.