openwrt procd启动流程和脚本分析

本文详细分析了OpenWRT系统中procd的启动流程,从kernel_init开始,到procd的main函数、uloop_init、preinit的执行,以及如何处理hotplug事件和内核uevent。procd通过fork子进程执行/etc/preinit脚本,调用hook函数,并进入状态机处理,如STATE_EARLY、STATE_UBUS和STATE_INIT等。在STATE_INIT阶段,procd执行inittab中的回调函数,处理rcS.c和/etc/rc.d下的脚本。

Linux内核执行start_kernel函数时会调用kernel_init来启动init进程,流程如下图:

graph LR A[start_kernel] -->B(rest_init) B --> C(kernel_init) C --> D[try_to_run_init_process]

kernel_init部分代码如下:

 994     if (execute_command) {
 995         ret = run_init_process(execute_command);
 996         if (!ret)
 997             return 0;
 998         panic("Requested init %s failed (error %d).",
 999               execute_command, ret);
1000     }
1001     if (!try_to_run_init_process("/sbin/init") ||
1002         !try_to_run_init_process("/etc/init") ||
1003         !try_to_run_init_process("/bin/init") ||
1004         !try_to_run_init_process("/bin/sh"))
1005         return 0;
1006
1007     panic("No working init found.  Try passing init= option to kernel. "
1008           "See Linux Documentation/init.txt for guidance.");

接着分析openwrtpackage/system/procd/Makefile,这里将procd源码编译生成的可执行文件安装到文件系统的*/sbin*目录中。

define Package/procd/install
    $(INSTALL_DIR) $(1)/sbin $(1)/etc $(1)/lib/functions

    $(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/sbin/{init,procd,askfirst,udevtrigger} $(1)/sbin/
    $(INSTALL_DATA) $(PKG_INSTALL_DIR)/usr/lib/libsetlbf.so $(1)/lib
    $(INSTALL_BIN) ./files/reload_config $(1)/sbin/
    $(INSTALL_DATA) ./files/hotplug*.json $(1)/etc/
    $(INSTALL_DATA) ./files/procd.sh $(1)/lib/functions/
endef

查看procd源码目录的CMakeList.txt,以init为例,对应源码编译文件如下

 56 IF(DISABLE_INIT)
 57 ADD_DEFINITIONS(-DDISABLE_INIT)
 58 ELSE()
 59 ADD_EXECUTABLE(init initd/init.c initd/early.c initd/preinit.c initd/mkdev.c watchdog.c
 60     utils/utils.c ${SOURCES_ZRAM})
 61 TARGET_LINK_LIBRARIES(init ${LIBS})
 62 INSTALL(TARGETS init
 63     RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
 64 )
 65
 66 ADD_EXECUTABLE(udevtrigger plug/udevtrigger.c)
 67 INSTALL(TARGETS udevtrigger
 68     RUNTIME DESTINATION ${CMAKE_INSTALL_SBINDIR}
 69 )
 70 ENDIF()

main函数入口位于initd/init.c

int
main(int argc, char **argv)
{
    pid_t pid;

    ulog_open(ULOG_KMSG, LOG_DAEMON, "init");

    sigaction(SIGTERM, &sa_shutdown, NULL);
    sigaction(S
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值