关键词:halt/poweroff/reboot、reboot()、SIGUSR1/SIGTERM/SIGUSR2等。app
经过applets.h下的halt/poweroff/reboot可知,实现都在halt_main()中。this
IF_HALT(APPLET(halt, BB_DIR_SBIN, BB_SUID_DROP))
IF_POWEROFF(APPLET_ODDNAME(poweroff, halt, BB_DIR_SBIN, BB_SUID_DROP, poweroff))
IF_REBOOT( APPLET_ODDNAME(reboot, halt, BB_DIR_SBIN, BB_SUID_DROP, reboot))
下面就看看halt_main(),-d表示延迟多久执行操做;-n表示在执行操做以前是否执行sync();-f表示强制整个系统直接系统调用reboot重启操做,不定义的状况下经过init。spa
int halt_main(int argc UNUSED_PARAM, char **argv) { static const int magic[] = { RB_HALT_SYSTEM, RB_POWER_OFF, RB_AUTOBOOT }; static const smallint signals[] = { SIGUSR1, SIGUSR2, SIGTERM };------------SIGUSR1表示halt操做;SIGUSR2表示poweroff操做;SIGTERM表示reboot操做。 int delay = 0; int which, flags, rc; /* Figure out which applet we're running */ if (ENABLE_HALT && !ENABLE_POWEROFF && !ENABLE_REBOOT) which = 0; else if (!ENABLE_HALT && ENABLE_POWEROFF && !ENABLE_REBOOT) which = 1; else if (!ENABLE_HALT && !ENABLE_POWEROFF && ENABLE_REBOOT) which = 2; else for (which = 0; "hpr"[which] != applet_name[0]; which++) continue;---------------------------------------------------------------根据applet_name[]来肯定which的值,小技巧实现了下面kill()和reboot参数which。 /* Parse and handle arguments */ /* We support -w even if !ENABLE_FEATURE_WTMP, * in order to not break scripts. * -i (shut down network interfaces) is ignored. */ flags = getopt32(argv, "d:+nfwi", &delay); sleep(delay);------------------------------------------------延时多久执行操做。 ... if (!(flags & 2)) /* no -n */ sync();--------------------------------------------------sync()同步操做。 /* Perform action. */ rc = 1; if (!(flags & 4)) { /* no -f */------------------------------重要区别是-f是否认义,对reboot命令影响较大。 ... if (rc) { /* talk to init */ if (!ENABLE_FEATURE_CALL_TELINIT) { /* bbox init assumed */ rc = kill(1, signals[which]);--------------------对init进程发送信号,信号值是由which决定的。 } else { ... } } } else { rc = reboot(magic[which]);------------------------------在定义-f的状况下,执行真正的内核reboot命令。具体的哪一种reboot,也是经过which决定的。 } if (rc) bb_perror_nomsg_and_die(); return rc; }
在没有-f选项状况下,直接调用reboot系统调用;反之,则向init进程发送SIGUSR1/SIGTERM/SIGUSR2信号,经由init处理这几个信号来实现halt/poweroff/reboot。rest
check_delayed_sigs()接收SIGUSR[12]/SIGTERM信号,调用halt_reboot_pwoff()进行处理。code
halt_reboot_pwoff()执行inittab中SHUTDOWN操做,kill全部非init进程以后,调用reboot系统调用。orm
static int check_delayed_sigs(void) { int sigs_seen = 0; while (1) { ... if ((1 << sig) & (0 #ifdef SIGPWR + (1 << SIGPWR) #endif + (1 << SIGUSR1) + (1 << SIGUSR2) + (1 << SIGTERM) )) { halt_reboot_pwoff(sig); } } }
static void halt_reboot_pwoff(int sig) { const char *m; unsigned rb; reset_sighandlers_and_unblock_sigs(); run_shutdown_and_kill_processes();---------------执行inittab中的SHUTDOWN action。 m = "halt"; rb = RB_HALT_SYSTEM;-----------------------------默认是halt magic。 if (sig == SIGTERM) {----------------------------对应reboot magic。 m = "reboot"; rb = RB_AUTOBOOT; } else if (sig == SIGUSR2) {---------------------对应poweroff magic。 m = "poweroff"; rb = RB_POWER_OFF; } message(L_CONSOLE, "Requesting system %s", m); pause_and_low_level_reboot(rb); /* not reached */ }
static void pause_and_low_level_reboot(unsigned magic) { pid_t pid; sleep(1); pid = vfork(); if (pid == 0) { /* child */ reboot(magic);-------------------------------在子进程中执行reboot()系统调用。 _exit(EXIT_SUCCESS); } while (1) sleep(1);------------------------------------init进程自己进入了while(1)。 }
halt/poweroff/reboot三个busybox命令,分别对应RB_HALT_SYSTEM(0xcdef0123)/RB_POWER_OFF(0x4321fedc)/RB_AUTOBOOT(0x01234567)。blog
这三个命令的区,详细能够参考kernel_halt()、kernel_power_off()、kernel_restart()。进程
/* * Reboot system call: for obvious reasons only root may call it, * and even root needs to set up some magic numbers in the registers * so that some mistake won't make this reboot the whole machine. * You can also set the meaning of the ctrl-alt-del-key here. * * reboot doesn't sync: do that yourself before calling this. */ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg) { ... if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off) cmd = LINUX_REBOOT_CMD_HALT; mutex_lock(&reboot_mutex); switch (cmd) { case LINUX_REBOOT_CMD_RESTART:-----------------------对应busybox中的reboot命令。 kernel_restart(NULL); break; ... case LINUX_REBOOT_CMD_HALT:--------------------------对应busybox中的halt命令。 kernel_halt(); do_exit(0); panic("cannot halt"); case LINUX_REBOOT_CMD_POWER_OFF:---------------------对应busybox中的poweroff命令。 kernel_power_off(); do_exit(0); break; case LINUX_REBOOT_CMD_RESTART2: ret = strncpy_from_user(&buffer[0], arg, sizeof(buffer) - 1); if (ret < 0) { ret = -EFAULT; break; } buffer[sizeof(buffer) - 1] = '\0'; kernel_restart(buffer); break; ... default: ret = -EINVAL; break; } mutex_unlock(&reboot_mutex); return ret; }
halt/poweroff/reboot三个命令最终都经过内核reboot()系统调用实现,可是-f选项多了一些操做。ip
reboot相对于reboot -f区别是,能够经过init对halt/poweroff/reboot附加一些操做,好比作一些备份操做、同步操做。get
不一样reboot() magic区别是,调用不一样kernel_restart()/kernel_halt()/kernel_power_off()。