OpenWrt开发:17---软件启动机制(init进程、/etc/inittab、/etc/rc.d、/etc/init.d、rc.common)

一、init进程介绍

  • init进程是所有系统进程的父进程,它被内核调用起来并负责调用所有其他的进程。 如果任何进程的父进程退出,init进程将成为它的父进程。但是init进程是如何将其他进程调用起来的呢?接下来介绍

二、OpenWrt软件启动机制

第一步:

  • 内核启动完成后读取/etc/inittab文件,然后执行inittab中的sysinit所指的脚本(/etc/init.d/rcS)
  • OpenWrt的inittab文件内容如下:

OpenWrt开发:17---软件启动机制(init进程、/etc/inittab、/etc/rc.d、/etc/init.d、rc.common)_第1张图片

第二步:

  • 如果按照通常的简单做法:我们会将每一个待启动的程序启动命令按行放入rcS文件中,并顺序执行。这种实现方法在软件启动进程列表不变时工作得非常好,如果需要动态修改,则不容易以程序来控制(在OpenWrt下,使用ls命令查看不到/etc/init.d/rcS这个文件)。OpenWrt引入了一个便于控制的启动机制,这种机制是在/etc/rc.d目录下创建每个软件的软链接方式,由rcS脚本在该目录读取启动命令的软链接, 然后启动软链接所指向的程序,由于每一个软链接均包含一个数字,这样就可以按照数字顺序读取并进行启动了
  • 具体执行流程:执行/etc/init.d/rcS脚本时,给脚本传递两个参数(分别为S何boot),接着rcS脚本通过run_scripts函数来启动软件,将每一个以/etc/rc.d/S开头的脚本按照数字传递boot参数并调用
    • S:表示软件启动模块,是和 K(软件关闭)相对应的
    • boot:表示首次启动

OpenWrt开发:17---软件启动机制(init进程、/etc/inittab、/etc/rc.d、/etc/init.d、rc.common)_第2张图片

  • 例如从/etc/rc.d目录下的脚本可以看出,就是先执行../init.d/sysfixtime,再执行../init.d/boot,以此类推......。几个比较重要的程序如下:
    • S10boot:调用uci_apply_defaults执行第1此开机时的UCI配置初始化,该函数执行/etc/uci-defaults/下的所有脚本,执行成功后就删除,因此该目录下的脚本只有第一次开机才会执行
    • S10system:根据UCI配置文件/etc/config/system配置系统,具体可参考该配置文件
    • S11sysctl:根据/etc/sysctl.conf配置系统([-f  /etc/sysctl.conf]  && sysctl -p -e >&-)
    • S19filewall:启动防火墙fw3,该工具来自openwrt软件包package/network/config/firewal
    • S20network:根据UCI配置文件/etc/config/network,使用守护进程/sbin/netifd来配置网络

OpenWrt开发:17---软件启动机制(init进程、/etc/inittab、/etc/rc.d、/etc/init.d、rc.common)_第3张图片

三、“/etc/init.d/*”脚本分析

  • 上面那些最终调用的软件启动shell脚本,包含变量定义和函数定义(start、stop和restart等函数)
  • 备注:因为/etc/rc.d/下面文件是/etc/int.d/下脚本的软链接,根据软链接的特性,我们查看软链接文件也就可以访问到/etc/int.d/下面的脚本文件
  • 另外使用 opkg 命令安装软件时一般均有执行权限,如果是自己手动新增脚本,不要忘记确认脚本是否有执行权限(通过运行 chmod +x /etc/init.d/hello命令来增加执行权限)

脚本分析

OpenWrt开发:17---软件启动机制(init进程、/etc/inittab、/etc/rc.d、/etc/init.d、rc.common)_第4张图片

  • /etc/rc.common:这个脚本没有解析自己的命令行参数,这是通过“/etc/rc.common”脚本回调来完成的。第一行是特殊的注释行,表示使用“/etc/rc.common”来提供一些基本函数,包含主函数及默认功能以及检查脚本执行等
  • START、STOP变量:脚本的执行顺序通过START和 STOP变量来定义
    • 如果这两个变量被更改了,再次运行/etc/init.d/hello enable才会再次生效,并且这将删除以前创建的启动链接,然后再根据新的变量定义创建链接(创建的启动链接保存在“/etc/rc.d”目录下)
    • 如果多个初始化脚本有相同的启动优先值,则调用顺序取决于启动脚本名称的字母顺序(在上上张图中S10boot与S10system文件中的START变量值相同,但是他们按照脚本名称的字母排序启动)
  • start()、stop()函数:脚本中最重要的函数是 start 和 stop,这两个函数决定如何启动和停止服务

rc.common函数含义

  • 备注:其中的start()、stop()函数实现为空,供应用软件重新实现,相当于C++语言中的虚函数
  • enable、disable 和 enabled函数提供自启动状态的设置和查询
  • help函数提供命令帮助信息,如果你不带参数运行软件命令,将会自动调用help函数输出帮助信息
  • boot函数与start函数的关系:命令在启动时取代 start 函数而执行 boot 函数,如果 boot 函数没 有被重新定义,将执行 rc.common 中预定义的 boot 函数,boot 函数再次调用 start 函数
  • 详情见下表:
函 数 含 义
start 启动服务。相当于 C++语言中的虚函数,通常情况下每一个服务均需重写该函数
stop 关闭服务。相当于 C++语言中的虚函数,通常情况下每一个服务均需重写该函数
restart 重启服务。调用 stop 函数退出进程,然后再调用 start 函数启动进程
reload 重新读取配置,如果读取配置失败则调用 restart 函数重启进程
enable 打开服务自启动,即将启动脚本软链接文件放在/etc/rc.d 目录下
disable 关闭服务自启动,删除在/etc/rc.d 的软链接文件
enabled 提供服务自启动的状态查询
boot 调用 start 函数
shutdown 调用 stop 函数
help 输出帮助信息

软链接特性

  • ①当我们使用enable设置一个软件为开机自启动时,将自动在/etc/rc.d/目录下创建一个软链接指向/etc/init.d/目录下的软件
  • ②当我们使用disable关闭一个软件开机自启动时,软件在/etc/rc.d/目录下的软链接将删除

四、自定义软件的启动脚本设计案例

  • 见文章:
    • https://blog.csdn.net/qq_41453285/article/details/102545618
    • https://blog.csdn.net/qq_41453285/article/details/102622557

你可能感兴趣的:(OpenWrt开发)