OpenWRT 启动流程
内核启动过程:【/init/mian.c】
Uboot --> start_kernel() --> rest_init() --> kernel_thread(kernel_init) --> kernel_init_freeable()
初始化过程:
Linux Kernel(kernel_init) --> /etc/preinit --> /sbin/init --> /etc/preinit, /sbin/procd --> /sbin/procd。
/etc/preinit脚本是系统其它脚本的入口,在/etc/preinit脚本中,第一条命令为:
[ -z “$PREINIT” ] && exec /sbin/init
由于一开始PREINIT没有被设置,所以为空,执行/sbin/init
其中/sbin/init 由procd/init.c编译产生的(它先执行一些ulog_open、early、cmdline等函数。最后执行preinit()函数。)
init.c部分代码如下:
当procd退出后会调用execvp函数执行/sbin/procd,替换当前的init进程,这就是系统启动完成后,进程号为1最终为/sbin/procd的由来,中间改变了几次。
preinit函数配置了环境变量PREINIT,然后再去fork进程来执行/etc/preinit,执行完毕后,再调用回调函数spawn_procd,在回调函数spawn_procd中调用了execvp函数来启动/sbin/procd,/procd最后执行/etc/init.d/目录下的文件,从而启动系统各个服务。
第二次开始执行 /etc/preinit的过程
当PREINIT被设置好了,preinit就会执行上面的代码。
可以看到三个脚本被启动:
. /lib/functions.sh
. /lib/functions/preinit.sh
. /lib/functions/system.sh
这几个脚本主要定义了shell函数,在preinit.sh中,定义了一些函数挂到hook上,当运行时,这些hook会按函数加入的顺序来启动函数。如boot_hook_init()等函数,之后使用boot_hook_init定义了五个hook节点:
boot_hook_init preinit_essential
boot_hook_init preinit_main
boot_hook_init failsafe
boot_hook_init initramfs
boot_hook_init preinit_mount_root
后面就是当前shell下依次在执行/lib/preinit/目录下的脚本:
定义那些要添加到hook结点的函数,然后通过boot_hook_add将该函数添加到对应的hook结点。
最后,/etc/preinit就会执行boot_run_hook函数执行对应hook结点上的函数。在当前环境下只执行了preinit_essential和preinit_main结点上的函数,如下:
boot_run_hook preinit_essential
boot_run_hook preinit_main
到此,/etc/preinit执行完毕并退出。
当/etc/preinit执行完毕并退出,进程消失了,但此时已经调用了回调函数spawn_procd(),而回调函数spawn_procd()里面execvp(“procd”),所以最终procd会重新被执行,从而启动系统其它各个配置!
lib/preinit/
在/etc/preinit脚本中有如下代码:
. /lib/functions.sh
. /lib/functions/preinit.sh
. /lib/functions/system.sh
查看. /lib/functions/preinit.sh脚本