目录
第一次运行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描述。
第二次运行procd,替换了init进程成为1号进程,完成开机的初始化,各种用户态服务的启动。
procd中有几个状态:
开机初始化走到STATE_RUNNING就算是结束了,之后procd进程会通过uloop_run驻留系统。
从上面序列图上可以看到,开机做了几件事情:
STATE_EARLY
阶段
hotplug根据/etc/hotplug.json
监听内核的uevent事件
coldplug mount /dev到tmpfs, 运行udevtrigger主动触发设备uevent,创建设备节点。
STATE_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
后续就是看具体的启动脚本,模块化调试了。