目录
1. 第一次运行procd
第一次运行procd,形式为procd -h /etc/hotplug-preinit.json
,这是主要是对对uevent的处理。
分析代码完成序列图:
贴上/etc/hotplug-preinit.json
[
[ "case", "ACTION", {
"add": [
[ "if",
[ "has", "FIRMWARE" ],
[
[ "exec", "/sbin/hotplug-call", "%SUBSYSTEM%" ],
[ "load-firmware", "/lib/firmware" ],
[ "return" ]
]
],
],
}, ],
[ "if",
[ "and",
[ "eq", "SUBSYSTEM", "button" ],
],
[ "exec", "/etc/rc.button/failsafe" ]
],
]
可见在preint阶段需要处理安全模式和固件升级两个hotplug.
uevent事件的ACTION为add类型时,如果事件中的包含$FIRMWARE变量则做两件事:
- 执行
/sbin/hotplug-call
,识别uevent中的SUBSYSTEM
变量运行/etc/hotplug.d/
下对应目录中的脚本。 - 加载
/lib/firmware
下的对应固件完成模块的固件升级。
- 执行
判断uevent事件,如果
SUBSYSTEM
为button
则通过运行/etc/rc.button/failsafe
脚本。该脚本决定是否创建/tmp/failsafe_button
判断是否进入安全模式,/tmp/failsafe_button
这个文件在lib/preinit/30_failsafe_wait
中用到。
附上/etc/rc.button/failsafe
如下:
#!/bin/sh
[ "${TYPE}" = "switch" ] || echo ${BUTTON} > /tmp/failsafe_button
注:FAQ一章中贴上来带注释的/etc/hotplug.json。介绍了hotplug的json描述。
2. 第二次运行procd
第二次运行procd,替换了init进程成为1号进程,完成开机的初始化,各种用户态服务的启动。
procd中有几个状态:
- STATE_EARLY,
- STATE_UBUS,
- STATE_INIT,
- STATE_RUNNING,
- STATE_SHUTDOWN,
- STATE_HALT,
开机初始化走到STATE_RUNNING就算是结束了,之后procd进程会通过uloop_run驻留系统。
3. 开机系统服务的启动
从上面序列图上可以看到,开机做了几件事情:
STATE_EARLY
阶段
hotplug根据/etc/hotplug.json
监听内核的uevent事件
coldplug mount /dev到tmpfs, 运行udevtrigger主动触发设备uevent,创建设备节点。STATE_UBUS
阶段- marvell平台运行mrvl_fast_boot,这是定制的,非标准流程。运行脚本/etc/telinit,主要是modem、rild、usb的一些配置启动。
- 与ubus建立socket连接,开始时ubus不存在,procd_connect_ubus中定义定时间,定时重连,直到连接上ubus后,向ubus添加对象
main_object
、system_object
,然后以服务进程启动ubusd,以提供进程间通信的基础。
STATE_INIT
阶段procd_inittab()
函数解析配置文件/etc/inittab
创建了sysinit
、shutdown
和askconsole
三个init_action的list。procd_inittab_run
依次运行respawn
、askconsole
、askfirst
和sysinit
几个action的callback:
static struct init_handler handlers[] = {
{
.name = "sysinit",
.cb = runrc,
}, {
.name = "shutdown",
.cb = runrc,
}, {
.name = "askfirst",
.cb = askfirst,
.multi = 1,
}, {
.name = "askconsole",
.cb = askconsole,
.multi = 1,
}, {
.name = "respawn",
.cb = rcrespawn,
.multi = 1,
}
};
下面重点看sysinit
对应的runrc
该项目运行下面脚本:
S00sysfixtime
S10boot #/etc/init.d/mrvl_init,/sbin/kmodloader,/etc/uci-defaults,/sbin/reload_config
S19dnsmasq #空boot,hotplug过程中完成
S19firewall #空boot,hotplug过程中完成
S40fstab #/sbin/block mount
S95done #/etc/rc.local,/etc/diag.sh
后续就是看具体的启动脚本,模块化调试了。