当前位置:网站首页>busybox之reboot命令流程分析
busybox之reboot命令流程分析
2022-07-31 11:52:00 【szembed】
busybox初始化注册reboot处理信号
busybox启动的时候,会注册reboot的处理信号
init_main
bb_signals(0
+ (1 << SIGUSR1) /* halt */
+ (1 << SIGTERM) /* reboot */
+ (1 << SIGUSR2) /* poweroff */
, halt_reboot_pwoff);
signal(SIGQUIT, restart_handler); /* re-exec another init */
- 1
- 2
- 3
- 4
- 5
- 6
- 7
busybox 的命令对应入口查找流程
运行busybox对应的命令的时候,处理流程如下:
busybox对外提供了一个命令列表,支持非常多的命令
这个列表在代码里面的 include/applet_names.h
applet_names 定义了字符串和函数钩子的对应列表applet_main,顺序是一一对应的
入这里 reboot —> halt_main
其他命令的处理入口函数根据这个顺序去查找
lbb_main
run_applet_and_exit
int applet = find_applet_by_name(name);
if (applet >= 0)
run_applet_no_and_exit(applet, argv);
if (!strncmp(name, "busybox", 7))
exit(busybox_main(argv));
- 1
- 2
- 3
- 4
- 5
- 6
- 7
从这段代码可以看出来,运行busybox命令的时候,会根据name查找到
命令在 applet_main 的下表索引 applet_no ,最后直接调用
applet_main[applet_no](argc, argv)命令执行对应命令的处理函数
reboot命令处理函数 halt_main
该函数的主要处理流程如下:
if (!(flags & 4)) { /* no -f */
//TODO: I tend to think that signalling linuxrc is wrong
// pity original author didn't comment on it...
if (ENABLE_FEATURE_INITRD) {
/* talk to linuxrc */
/* bbox init/linuxrc assumed */
pid_t *pidlist = find_pid_by_name("linuxrc");
if (pidlist[0] > 0)
rc = kill(pidlist[0], signals[which]);
if (ENABLE_FEATURE_CLEAN_UP)
free(pidlist);
}
if (rc) {
/* talk to init */
if (!ENABLE_FEATURE_CALL_TELINIT) {
/* bbox init assumed */
rc = kill(1, signals[which]);
} else {
/* SysV style init assumed */
/* runlevels:
* 0 == shutdown
* 6 == reboot */
rc = execlp(CONFIG_TELINIT_PATH,
CONFIG_TELINIT_PATH,
which == 2 ? "6" : "0",
(char *)NULL
);
}
}
} else {
rc = reboot(magic[which]);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
这里可以看出来,分为两个流程:
- 当reboot命令没有加 -f的时候,直接使用kill发送信号到busybox执行halt_reboot_pwoff函数
- 直接使用-f的话,直接使用reboot系统调用接口,通知内核,让内核执行重启操作,简单粗暴
halt_reboot_pwoff函数处理流程
我们大部分的重启命令都是直接使用reboot命令,最后走halt_reboot_pwoff流程,
当我们执行reboot的时候,一般都会有以下的打印:
The system is going down NOW!
Sent SIGTERM to all processes
Sent SIGKILL to all processes
Requesting system reboot
- 1
- 2
- 3
- 4
从上面可以看出来,分为三步:
- 发送SIGTERM给所有进程,让进程正常退出
- 发送SIGKILL给所有进程,将其杀掉
- 让系统重启
以上三步都是在halt_reboot_pwoff里面实现的
static void halt_reboot_pwoff(int sig) { const char *m; unsigned rb;
/* We may call run() and it unmasks signals, * including the one masked inside this signal handler. * Testcase which would start multiple reboot scripts: * while true; do reboot; done * Preventing it: */ reset_sighandlers_and_unblock_sigs(); run_shutdown_and_kill_processes(); m = "halt"; rb = RB_HALT_SYSTEM; if (sig == SIGTERM) { m = "reboot"; rb = RB_AUTOBOOT; } else if (sig == SIGUSR2) { m = "poweroff"; rb = RB_POWER_OFF; } message(L_CONSOLE, "Requesting system %s", m); pause_and_low_level_reboot(rb); /* not reached */
}
static void run_shutdown_and_kill_processes(void)
{
/* Run everything to be run at “shutdown”. This is done prior
* to killing everything, in case people wish to use scripts to
* shut things down gracefully… */
run_actions(SHUTDOWN);
message(L_CONSOLE | L_LOG, "The system is going down NOW!");
/* Send signals to every process _except_ pid 1 */
kill(-1, SIGTERM);
message(L_CONSOLE | L_LOG, "Sent SIG%s to all processes", "TERM");
sync();
sleep(1);
kill(-1, SIGKILL);
message(L_CONSOLE, "Sent SIG%s to all processes", "KILL");
sync();
/*sleep(1); - callers take care about making a pause */
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
上面的源码可以看出来,halt_reboot_pwoff直接调用run_shutdown_and_kill_processes去
完成第一第二步,中间sleep 一秒钟
第三步是直接使用vfork子进程出来下发系统调用reboot(magic)命令给内核,让内核完成重启,
这一步和我们直接用reboot -f基本一致,也就是说reboot和reboot -f之间相差了第一第二步而已。
内核处理reboot系统调用流程
SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg)
kernel_restart(NULL);
kernel_restart_prepare(cmd);
migrate_to_reboot_cpu();
syscore_shutdown();
if (!cmd)
pr_emerg("Restarting system\n");
else
pr_emerg("Restarting system with command '%s'\n", cmd);
kmsg_dump(KMSG_DUMP_RESTART);
machine_restart(cmd);
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
用户态运行reboot命令,除了用户态先kill所有用户态进程之外,还需要通过系统调用reboot接口
通知内核,让内核执行正常的cpu重启,这里涉及到不同架构cpu板子的重启,所以这里是分架构
来调用对应架构的重启cpu操作的.
边栏推荐
- Mysql环境变量的配置(详细图解)
- The most complete phpmyadmin vulnerability summary
- Candence学习篇(11) allegro中设置规则,布局,走线,铺铜
- 下课看着文档走回实验室,我重新拾起了遗忘的SQL运算符
- Data Lake (19): SQL API reads Kafka data and writes it to Iceberg table in real time
- After class, watching the documentation and walking back to the lab, I picked up the forgotten SQL operators again
- 生命不息,刷题不止,简单题学习知识点
- Summary of several defragmentation schemes for MySQL (to solve the problem of not releasing space after deleting a large amount of data)
- CameraToolUnity中两种摄像机的两种观察控制方式
- 关于==和equals的区别和联系,面试这么回答就可以
猜你喜欢
最全phpmyadmin漏洞汇总
In PLC communication error or timeout or download the prompt solution of the model
2022/7/28
透过开发抽奖小程序,体会创新与迭代
Is the working process of the belt you know the story - actionreducerstore
5 open source Rust web development frameworks, which one do you choose?
Candence学习篇(11) allegro中设置规则,布局,走线,铺铜
After class, watching the documentation and walking back to the lab, I picked up the forgotten SQL operators again
Docker实践经验:Docker 上部署 mysql8 主从复制
MySQL百万数据优化总结 一
随机推荐
2022/7/28
关于==和equals的区别和联系,面试这么回答就可以
Docker搭建Mysql主从复制
文件包含漏洞
Different lower_case_table_names settings for server ('1') and data dictionary ('0') solution
502 bad gateway causes and solutions
【虚拟化生态平台】平台架构图&思路和实现细节
线程池 ThreadPoolExecutor 详解
[Virtualization Ecological Platform] Platform Architecture Diagram & Ideas and Implementation Details
Yarn安装配置(vsftpd安装配置)
连续变量离散化教程
Detailed tutorial on distributed transaction Seata
In Excel using ODBC consumer SAP ABAP CDS view
一周精彩内容分享(第14期)
Acwing第 62 场周赛【未完结】
便利贴--46{基于移动端长页中分页加载逻辑封装}
Initial JDBC programming
多线程学习笔记-2.final关键字和不变性
Read through the interface to call the artifact RestTemplate
无法将“node.exe”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。