简单理解Busybox下halt/poweroff/reboot实现及区别
關(guān)鍵詞:halt/poweroff/reboot、reboot()、SIGUSR1/SIGTERM/SIGUSR2等。
1. busybox下的halt/poweroff/reboot實(shí)現(xiàn)
通過(guò)applets.h下的halt/poweroff/reboot可知,實(shí)現(xiàn)都在halt_main()中。
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表示延遲多久執(zhí)行操作;-n表示在執(zhí)行操作之前是否執(zhí)行sync();-f表示強(qiáng)制整個(gè)系統(tǒng)直接系統(tǒng)調(diào)用reboot重啟操作,不定義的情況下通過(guò)init。
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;---------------------------------------------------------------根據(jù)applet_name[]來(lái)確定which的值,小技巧實(shí)現(xiàn)了下面kill()和reboot參數(shù)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);------------------------------------------------延時(shí)多久執(zhí)行操作。
...
if (!(flags & 2)) /* no -n */
sync();--------------------------------------------------sync()同步操作。
/* Perform action. */
rc = 1;
if (!(flags & 4)) { /* no -f */------------------------------重要區(qū)別是-f是否定義,對(duì)reboot命令影響較大。
...
if (rc) {
/* talk to init */
if (!ENABLE_FEATURE_CALL_TELINIT) {
/* bbox init assumed */
rc = kill(1, signals[which]);--------------------對(duì)init進(jìn)程發(fā)送信號(hào),信號(hào)值是由which決定的。
} else {
...
}
}
} else {
rc = reboot(magic[which]);------------------------------在定義-f的情況下,執(zhí)行真正的內(nèi)核reboot命令。具體的哪種reboot,也是通過(guò)which決定的。
}
if (rc)
bb_perror_nomsg_and_die();
return rc;
}
1.1 reboot -f和reboot的區(qū)別
在沒(méi)有-f選項(xiàng)情況下,直接調(diào)用reboot系統(tǒng)調(diào)用;反之,則向init進(jìn)程發(fā)送SIGUSR1/SIGTERM/SIGUSR2信號(hào),經(jīng)由init處理這幾個(gè)信號(hào)來(lái)實(shí)現(xiàn)halt/poweroff/reboot。
check_delayed_sigs()接收SIGUSR[12]/SIGTERM信號(hào),調(diào)用halt_reboot_pwoff()進(jìn)行處理。
halt_reboot_pwoff()執(zhí)行inittab中SHUTDOWN操作,kill所有非init進(jìn)程之后,調(diào)用reboot系統(tǒng)調(diào)用。
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();---------------執(zhí)行inittab中的SHUTDOWN action。
m = "halt";
rb = RB_HALT_SYSTEM;-----------------------------默認(rèn)是halt magic。
if (sig == SIGTERM) {----------------------------對(duì)應(yīng)reboot magic。
m = "reboot";
rb = RB_AUTOBOOT;
} else if (sig == SIGUSR2) {---------------------對(duì)應(yīng)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);-------------------------------在子進(jìn)程中執(zhí)行reboot()系統(tǒng)調(diào)用。
_exit(EXIT_SUCCESS);
}
while (1)
sleep(1);------------------------------------init進(jìn)程本身進(jìn)入了while(1)。
}
2. reboot系統(tǒng)調(diào)用
halt/poweroff/reboot三個(gè)busybox命令,分別對(duì)應(yīng)RB_HALT_SYSTEM(0xcdef0123)/RB_POWER_OFF(0x4321fedc)/RB_AUTOBOOT(0x01234567)。
這三個(gè)命令的區(qū),詳細(xì)可以參考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:-----------------------對(duì)應(yīng)busybox中的reboot命令。
kernel_restart(NULL);
break;
...
case LINUX_REBOOT_CMD_HALT:--------------------------對(duì)應(yīng)busybox中的halt命令。
kernel_halt();
do_exit(0);
panic("cannot halt");
case LINUX_REBOOT_CMD_POWER_OFF:---------------------對(duì)應(yīng)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] = '';
kernel_restart(buffer);
break;
...
default:
ret = -EINVAL;
break;
}
mutex_unlock(&reboot_mutex);
return ret;
}
3. 小結(jié)
halt/poweroff/reboot三個(gè)命令最終都通過(guò)內(nèi)核reboot()系統(tǒng)調(diào)用實(shí)現(xiàn),但是-f選項(xiàng)多了一些操作。
reboot相對(duì)于reboot -f區(qū)別是,可以通過(guò)init對(duì)halt/poweroff/reboot附加一些操作,比如做一些備份操作、同步操作。
不同reboot() magic區(qū)別是,調(diào)用不同kernel_restart()/kernel_halt()/kernel_power_off()。
總結(jié)
以上是生活随笔為你收集整理的简单理解Busybox下halt/poweroff/reboot实现及区别的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: jdbcmysql
- 下一篇: ethereal抓包工具