前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >【openwrt】Openwrt系统的reboot流程

【openwrt】Openwrt系统的reboot流程

作者头像
知否知否应是绿肥红瘦
发布2025-02-19 21:40:46
发布2025-02-19 21:40:46
7100
代码可运行
举报
文章被收录于专栏:Openwrt知识Openwrt知识
运行总次数:0
代码可运行
reboot流程

  • 应用层reboot流程
  • 内核reboot流程
  • 参考

当我们在openwrt系统的终端中敲下 reboot指令后,系统需要进行一系列动作后,才会真正的进行硬件重启。而这一系列的动作可以分为——应用程序的停止和内核的停止。在Openwrt系统中,应用程序的停止是1号进程(也就是 procd)完成的,应用程序全部停止后才会进入内核的重启流程。下面我们将分别来介绍应用程序和内核停止的流程。

首先,我们注意到reboot指令是busybox提供的,而且reboot指令支持传入不同的参数来执行不同的重启模式。

代码语言:javascript
代码运行次数:0
复制
# ls /sbin/reboot -alh
lrwxrwxrwx    1 root     root          14 Apr 17 13:15 /sbin/reboot -> ../bin/busybox

/# reboot --help
BusyBox v1.36.1 (2024-05-10 17:21:49 UTC) multi-call binary.
Usage: reboot [-d DELAY] [-nf]
Reboot the system
        -d SEC  Delay interval  
        -n      Do not sync  
        -f      Force (don't go through init) 

下面是reboot指令的参数解释。

参数

说明

-d SEC Delay interval

延时几秒之后重启

-n

不执行sync

-f

强制重启,跳过应用层直接走内核重启流程

关于reboot指令的具体实现可以参考busybox源码:halt.c

代码语言:javascript
代码运行次数:0
复制
int halt_main(int argc UNUSED_PARAM, char **argv)

if (!(flags & 4)) { /* 不带 -f 参数 */
//TODO: I tend to think that signalling linuxrc is wrong
// pity original author didn't comment on it...
		if (rc) {
			/* talk to init */
			if (!ENABLE_FEATURE_CALL_TELINIT) {
				/* bbox init assumed */
				rc = kill(1, signals[which]);// 发送信号给1号进程
				if (init_was_not_there())
					rc = kill(1, signals[which]);
			} 
		}
	} else {
		rc = reboot(magic[which]); // reboot -f 
	}

应用层reboot流程

根据前面reboot的源码,如果执行的是不带 -f选项的reboot,那么busybox就会发送信号给1号进程,由1号进程来执行重启流程。在openwrt系统中,1号进程就是procd.

代码语言:javascript
代码运行次数:0
复制
# ps
  PID USER       VSZ STAT COMMAND
    1 root      1868 S    /sbin/procd  

下面就是procd执行reboot的流程图:

  • procd_signal()是在procd启动时执行的,里面对SIGTERM,SIGINT,SIGUSR1 这些信号都注册了同一个回调函数——sa_shutdownsa_shutdown 其实是一个指向 struct sigaction 的指针,该结构体定义了如何处理上述信号.
  • procd收到如上信号后,sa_shutdown里面的回调函数会被调用,也就是signal_shutdown()
  • signal_shutdown 里面会根据不同的信号类型设置不同的event,然后将event传入procd_shutdown()
  • procd_shutdown()里面设置state = STATE_SHUTDOWN,随后调用state_enter()进入STATE_SHUTDOWN对应的状态处理流程
  • procd_inittab_run()会遍历整个handlers[],找到name=shutdown的handler,然后执行其cb函数,也就是runrc()
  • runrc()->rcS()->_rc(),_rc()会依次执行/etc/rc.d/ 下面所有K开头的脚本,也是所有应用程序的停止脚本,这一步完成后,rcdone()会被调用。
  • rcdone() 会继续将STATE_SHUTDOWN 状态推进到 STATE_HALT状态,进入STATE_HALT状态后,会执行reboot系统调用进行内核阶段的重启,并且会带上前面的event参数,event参数也会被传递到内核,我们将在后续内核重启流程中继续介绍这个参数的具体作用。
  • 至此,所有的应用程序都已经停止(但1号进程未停止)

内核reboot流程

书接上回,前面提到应用层重启流程的最后一步是执行reboot()函数,其中reboot函数携带的参数可能是RB_AUTOBOOT或者RB_POWER_OFF,在musl libc中(openwrt系统默认使用musl libc而不是glibc)reboot函数的实现以及RB_AUTOBOOTRB_POWER_OFF的定义如下:

代码语言:javascript
代码运行次数:0
复制
//openwrt/build_dir/toolchain-aarch64_cortex-a53_gcc-12.3.0_musl/musl-1.2.4/include/sys/reboot.h
#define RB_AUTOBOOT     0x01234567
#define RB_HALT_SYSTEM  0xcdef0123
#define RB_ENABLE_CAD   0x89abcdef
#define RB_DISABLE_CAD  0
#define RB_POWER_OFF    0x4321fedc
#define RB_SW_SUSPEND   0xd000fce2
#define RB_KEXEC        0x45584543

//openwrt/build_dir/toolchain-aarch64_cortex-a53_gcc-12.3.0_musl/musl-1.2.4/src/linux/reboot.c
#include <sys/reboot.h>
#include "syscall.h"

int reboot(int type)
{
	//type=RB_AUTOBOOT or RB_POWER_OFF
	return syscall(SYS_reboot, 0xfee1dead, 672274793, type);
}

我们暂时只关注重启流程,所以type=RB_AUTOBOOT ,上面的reboot函数并没有过多操作,直接就执行了reboot系统调用,root系统调用的整体流程如下:

  • 进入内核reboot系统调用的处理函数中,用户层传入的参数 RB_AUTOBOOT 对应内核层的参数LINUX_REBOOT_CMD_RESTART,所以后续会调用kernel_restart()函数进行系统重启之前准备工作以及最后的重启动作(其他参数会对应其他动作,请自行参考源码)
  • kernel_restart_prepare()调用device_shutdown()关闭所有注册的device
  • 接下来console应该可以看到reboot: Restarting system的打印信息
  • machine_restart()在不同的平台实现可能不一样,在ARM64平台是调用do_kernel_restart()通知具体的驱动进行重启,通常是通知看门狗驱动来进行最终的物理重启。

参考

openwrt reboot流程 记一个openwrt reboot异步信号处理死锁问题 linux reboot/panic子系统

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=w9uuvqz1x4

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-02-19,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • reboot流程
  • 应用层reboot流程
  • 内核reboot流程
  • 参考
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档