openwrt reboot流程

2023-11-12

openwrt 系统中,当执行了 reboot 命令,系统将会发生什么事情呢?如何进行重启的呢?下面来一起看一下。

reboot 应用层操作

首先,reboot 是由busybox(它是一个集成了常用Linux命令和工具的软件)提供的一个Linux命令。reboot 命令存在在系统的 /sbin 目录下,到该目录查看可以发现它是一个软链接,指向 /bin 目录下的 busybox 可执行程序。

当执行 reboot 命令,将会调用到busybox中的init/halt.c文件,实际上,关机、重启都是由该文件实现的。

reboot 其他参数

  • -w:仅保存系统用户使用信息,不会进行重启等操作;
  • -n:执行reboot命令前不会执行sync()函数;
  • -f:是否通过init进程关机,如果没有-f参数,则通过init进程关机;

no -f 关机

如果执行 reboot 命令时没有带 -f 参数,将会按照下面流程进行。

  1. 如果配置了 ENABLE_LINUXRC,将会kill linuxrc 程序(默认ENABLE_LINUXRC为0);
  2. 如果 ENABLE_FEATURE_CALL_TELINIT 配置为0,则给1号进程进行发送信号,signals[] = { SIGUSR1, SIGUSR2, SIGTERM }。(默认ENABLE_FEATURE_CALL_TELINIT 为0);
  3. 如果 ENABLE_FEATURE_CALL_TELINIT 配置为1,则通过execlp()函数进行reboot等操作;

下面进行分析第2步,看看给1号进程发送信号之后会发生什么。

1号进程是/sbin/procd,通过查看 procd 的代码可以看到在procd_signal()函数中有各个信号的处理。最终的在procd中,如果是SIGINT、SIGTERM信号,将会执行重启;如果是SIGUSR1、SIGUSR2信号,将执行关机,相应的操作都是通过procd_shutdown()函数完成的,只是传递的参数不一样而已。

procd_shutdown()

在该函数中,将init进程的state置为STATE_SHUTDOWN,再state_enter()中执行STATE_SHUTDOWN操作。通过 set_console() 函数重定向输出到终端,而后执行procd_inittab_run("shutdown")操作,实际上该操作就是执行 /etc/inittab 中的shutdown操作,而在openwrt平台,该操作就是执行 /etc/rc.d 中的shutdown操作(自启动脚本的shutdown操作),最后再执行sync()操作。

在这里回头看,从我们执行reboot命令,到busybox中的处理reboot参数,而后给1号进程发信号,1号进程执行 procd_shutdown() 函数的STATE_SHUTDOWN操作,但是似乎都没有最终的调用到 reboot 操作,那么,具体的reboot操作又是那里实现的呢?

奥秘就在procd_inittab_run("shutdown")

干活的procd_inittab_run(“shutdown”)

要知道procd_inittab_run()函数进行了什么操作,得先分析一下procd_inittab()函数(开机过程会调用该函数)。

procd_inittab()函数将会打开/etc/inittab文件,将里面的操作添加到系统的操作链表中,待procd_inittab_run()函数调用。

/etc/inittab文件是init守护进程在系统运行过程中会读取信息来启动或退出进程的配置文件。inittab文件的每一项具有以下字段:

id:runlevels:action:process

id:它是每个登记项的标识符,用于唯一标识每个登记项,不能重复;

runlevels:系统的运行级别,表示process的action要在哪个级别下运行,该段中可以定义多个运行级别,各级别之间直接写不用分隔符;如果为空,表示在所有的运行级别运行;

action:表示对应登记项的process在一定条件下所要执行的动作;

具体动作有:

  • respawn:当process终止后马上启动一个新的

  • wait:当进入指定的runlevels后process才会启动一次,并且到离开这个runlevels终止

  • initdefault:设定默认的运行级别,即我们开机之后默认进入的运行级别,不能是0,6,你懂的

  • sysinit:系统初始化,只有系统开机或重新启动的时候,这个process才会被执行一次

  • powerwait:当init接收到电源失败信号的时候执行相应的process,并且如果init有进程在运行,会等待这个进程完成之后,再执行相应的process

  • powerfail:当init接收到电源失败信号的时候执行相应的process,并且如果init有进程在运行,不会等待这个进程完成,它会直接执行相应的process

  • powerokwait:电源已经故障,但是在等待执行对应操作的时候突然来电了就执行对应的process

  • powerfailnow:当电源故障并且init被通知UPS电源已经快耗尽执行相对应的process

  • ctrlaltdel:当用户按下ctrl+alt+del这个组合键的时候执行对应的process

  • boot:只有在引导过程中,才执行该进程,但不等待该进程的结束;当该进程死亡时,也不重新启动该进程

  • bootwait:只有在引导过程中,才执行该进程,并等待进程的结束;当该进程死亡时,也不重新启动该进程

  • off:如果process正在运行,那么就发出一个警告信号,等待20秒后,再通过杀死信号强行终止该process。如果process并不存在那么就忽略该登记项

  • once:启动相应的进程,但不等待该进程结束便继续处理/etc/inittab文件中的下一个登记项;当该进程死亡时,init也不重新启动该进程

  • shutdown:当系统重启、重启时将会执行的程序

process:表示启动哪个程序或脚本或执行哪个命令等;

简单了解上面信息之后,我们来看看procd_inittab_run("shutdown")的操作,而在openwrt系统,/etc/inittab文件中标识shutdown的信息如下:

::shutdown:/etc/init.d/rcS K shutdown

所以通过上面可以得到,将会执行 /etc/init.d/rcS 程序,但是在系统中并没有看到该文件,同时再回到procd_inittab_run()函数的实现将会看到,调用的将会是相应handler的cb()函数,shutdown操作的将会是调用runrc()函数。而在runrc()中,实际上就是执行rcS(K, shutdown, rcdone),再查看rcS()的实现,就发现是执行/etc/rc.d目录下的K*脚本中的shutdown操作。将K*脚本中的shutdown操作添加到任务队列中,然后再运行,任务逐个运行,到最后一个任务的时候,将会设置最后一个任务是运行工作队列中的empty_cb(),实际上,empty_cb() 就是工作队列中的任务都运行完时调用的。而上面在调用rcS()函数的时候,将empty_cb()函数设置为rcdone(),下面来看看rcdone()的操作。

rcdone()的操作比较简单,只是将init进程的state变量加1,再调用state_enter()。上面在procd_shutdown()中已经将state置为STATE_SHUTDOWN了,当前再加1,那state就是STATE_HALT。

state_enter() 的STATE_HALT

在HALT操作中,先signal(SIGCHLD, SIG_IGN)通知内核,init进程忽略子进程结束,子进程结束后由内核回收。而后通过kill(-1, SIGTERM)、kill(-1, SIGKILL)操作,发信号给除1号进程外的所有进程,使它们退出。最后,将创建子进程调用reboot(reboot_event),至此,reboot应用层操作转到内核。

reboot内核流程

在应用层调用reboot()函数之后,将会到内核的kernel/reboot.c中的SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd, void __user *, arg)函数。

在内核中,先检查当前是否具有root权限,因为reboot只能由root权限才可以执行,而后重启的话将会执行kernel_restart(),关机则执行kernel_power_off()。

kernel_restart()

在该函数中,主要进行下面的操作:

  1. kernel_restart_prepare():调用device_shutdown()函数,逐个调用device的shutdown()函数;
  2. migrate_to_reboot_cpu():将当前运行程序切换到CPU0;
  3. syscore_shutdown():调用通过register_syscore_ops()注册的shutdown的回调函数,比如irq、cpufreq、clock等核心模块的shutdown函数;
  4. machine_restart():调用到平台的restart()函数;

machine_restart() 的实现依赖不同的平台,如ARM64将会调用到arch/arm64/kernel/process.c中的machine_restart()。在ARM64平台中,将会先关闭中断使能,再关闭除CPU0外的其他CPU核,最后将会通过 arm_pm_restart() 函数指针调用到各自平台实现。

总结

通过上面的简单介绍,总结一下reboot流程。

  1. 接着将会发信号到1号进程procd,而procd将会执行shutdown操作,实际上就是调用/etc/rc.d目录下的K*的shutdown操作;
  2. 上面的K*都操作完之后,将会更新init进程的state为STATE_HALT;
  3. 在STATE_HALT中,将会退出除一号进程外的其他进程,接着执行reboot函数进入内核;
  4. 在内核中,调用device、irq、clock等的shutdown操作,关中断,关核,调用相应平台的重启接口;
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

openwrt reboot流程 的相关文章

随机推荐

  • Vijava (更改虚拟机配置信息(内存、CPU和添加新磁盘)终极版本)

    package com vmware server import java util List import java util Map import org apache log4j FileAppender import org apa
  • 解决idea不显示Services工具栏的问题

    Idea的Services窗口可以展示项目的入口引导类及端口 可以方便的启动及停止相关服务 假如自己的idea里边不显示 可以通过一下方式解决 1 找到自己 idea工作空间的workspace xml文件 2 文件内搜索 RunDashb
  • vue项目中封装手动上传多个图片并支持修改和移除

    现有的组件库无法满足手动上传文件到服务器 并支持通过按钮修改和移除文件的操作 所以我利用原生input进行封装 如有需要请拿走 1 页面部分 div class container div class upload picture div
  • centos7 查看服务器配置信息

    1 linux查看版本当前操作系统发行信息 cat etc centos release cat etc centos release 2 查看内核版本uname a或者cat proc version 3 查看CPU参数 1 查看 CPU
  • uniapp 本地缓存剩余时间

    封装代码 在项目根目录项新建 utils 文件夹 再新建一个 idea js 文件 import store from store js module exports 计算剩余时间 timeRemaining val time return
  • 二叉搜索树-AVL树的实现

    首先 AVL树是一棵加了额外平衡条件的搜索树 这是因为普通的搜索树如果插入的key接近有序的话 二叉树将会退化成一个单链表 导致查找的时间复杂度为O N 而AVL树中用一个平衡因子来制约树的左右子树的高度 保证任何节点的左右子树高度之差最多
  • Android开发人员应该选择哪种语言?

    自 Google 于 2017 年宣布 Kotlin 成为 Google IO 的 Android 开发官方语言以来 想要成为Android开发人员的程序员正陷入两难境地 在讨论这个问题前 我首先要明确一点 不要陷入编程语言战争 不要进行语
  • 【亲测解决】AttributeError: module ‘tensorflow‘ has no attribute ‘__version__‘

    今天在安装使用bert as service时报错 报错信息如下 AttributeError module tensorflow has no attribute version 一看 懵逼了 啥 tensorflow么有 version
  • centos 内核升级

    首先查看centos版本 cat etc centos release 或者 rpm q centos release 查看内核版本 uname sr 查看官方内核 https www kernel org 接下来升级内核 大多数现代发行版
  • 太牛叉了!解决“卡脖子”的国产自主 IDE [狗头.jpg]

    推荐关注 综合整理 程序员的那些事 ID iProgrammer 解决 卡脖子 的自主创新 IDE 最近有一个的国产自主创新的 CEC IDE 震动了程序员圈子 在 CEC IDE 官网简介中的 安全可控 条目自称 国企品牌 自主研发 注意
  • k8s运维 pod、node、namespace、pv处于terminating的原因及处理方法

    1 概述 node pod ns pv由于一些原因在生产中处于terminating的状态 常规方法无法删除 一下总结了一些原因以及删除方法 2 node处于Terminating状态原因及处理方法 node节点不可达的情况下 kubect
  • MATLAB嵌套循环求解1到1000的素数和

    熬夜打卡 代码都跑过一遍的 没有任何问题啦 方法一 matlab的嵌套循环 重在理解 clc clear s 0 for i 2 1000 for j 2 32 if mod i j break end end if j gt i j s
  • 【华为OD机试】阿里巴巴找黄金宝箱(IV)(C++ Python Java)2023 B卷

    时间限制 C C 1秒 其他语言 2秒 空间限制 C C 262144K 其他语言524288K 64bit IO Format lld 题目描述 一贫如洗的樵夫阿里巴巴在去砍柴的路上 无意中发现了强盗集团的藏宝地 藏宝地有编号从0 N的箱
  • 常用的BOM属性 - Kaiqisan

    终于出狱了 今天重新恢复博客的更新 大致谈谈我复习面试上面的查漏补缺的内容 首先讲讲什么是BOM BOM简单来说就是浏览器对象 只有js在浏览器环境运行时才会被赋予的对象 location对象 该对象内所有的属性都与URL有关 常常用于提取
  • 攻防世界————fileclude(内含php伪协议菜鸟讲解)

    先进去发现为一坨php代码 新手勉勉强强看得懂 接下来我们分析代码 WRONG WAY
  • Angular2-使用Augury来调试Angular2程序

    原文链接 http www jianshu com p efecaea287f2 推荐 Augury Angular专用的chrome 调试插件 如题 就在前几天的2016 12 8谷歌开发者大会上 angular2的leader来给我们演
  • idea字体主题集合

    http color themes com view index
  • 意念控制四旋翼 学习笔记

    第一部分 模块原始数据 拿到模块 在网上查了一圈 发现基本没什么有用的资料 很多都是一些相关但是没有实际价值的东西 许多论文都是再谈怎么去做 而没有实实在在的去完成这么一个过程 废话不多说 直接步入正题 昨天在网上才发现这个软件 据评论说是
  • 最近大火的「元宇宙」是什么?

    公众号后台回复 图书 了解更多号主新书内容 作者 腾讯技术工程特约撰稿人 李佳华 本文将介绍元宇宙的由来和底层技术 探讨海内外资本在这条赛道上的布局 元宇宙将会对哪些行业产生变革的影响 这些影响背后凸显了元宇宙的哪些价值 以及元宇宙逐步实现
  • openwrt reboot流程

    openwrt 系统中 当执行了 reboot 命令 系统将会发生什么事情呢 如何进行重启的呢 下面来一起看一下 reboot 应用层操作 首先 reboot 是由busybox 它是一个集成了常用Linux命令和工具的软件 提供的一个Li