先来介绍一下什么是Busybox:它是将众多的UNIX命令集合进一个很小的可执行程序中。
在制作根文件系统之内核如何启动init进程中遗留了一个问题是/linuxrc是内核启动的第一个应用程序,那么它是什么?我们看到移植好的根文件系统环境,输入ls -al /linuxrc。可以看到:
lrwxrwxrwx 1 1000 1000 11 Jul 26 2018 linuxrc -> bin/busybox
/linuxrc其实是指向Busybox的,它其实是Busybox下的一个程序,所以我们需要分析Busybox的源码来研究/linuxrc这个程序做的事情,当在移植好的根文件系统环境下输入/linuxrc可以看到:
# busybox linuxrc init started: BusyBox v1.7.0 (2018-07-26 12:50:40 CST) starting pid 796, tty '': '/etc/init.d/rcS' Please press Enter to activate this console.
这就是执行linuxrc程序之后出现的界面,现在还不确定/linuxrc是Busybox下哪个文件,我们搜索“init started”,在busybox-1.7.0initInit.c中找到了它
935 message(MAYBE_CONSOLE | L_LOG, "init started: %s", bb_banner);
我们看到调用它的是init_main函数,接下去就是分析这个函数,init_main函数的功能大概可以概括为
1、设置处理信号函数
2、读取配置文件、解析配置文件
3、根据配置文件执行用户的程序或脚本
下面分别介绍
1、设置处理信号函数,restart, ctrlaltdel, and shutdown是一些按键事件,这些处理函数在接收到按下相关按键的信号后,进行处理
905 signal(SIGHUP, exec_signal); 906 signal(SIGQUIT, exec_signal); 907 signal(SIGUSR1, shutdown_signal); 908 signal(SIGUSR2, shutdown_signal); 909 signal(SIGINT, ctrlaltdel_signal); 910 signal(SIGTERM, shutdown_signal); 911 signal(SIGCONT, cont_handler); 912 signal(SIGSTOP, stop_handler); 913 signal(SIGTSTP, stop_handler);
2、读取和解析配置文件,先看一下配置文件的格式,文档位于example/inittab中
# inittab的格式为: # <id>:<runlevels>:<action>:<process> # id => /dev/id,用作终端:stdin、stdout、stderr:printf、scanf、err # runlevels:忽略 # action :执行时机Valid actions include: sysinit, respawn, askfirst, wait, once, restart, ctrlaltdel, and shutdown. # process :应用程序或脚本
接着回到init_main函数,看到
967 parse_inittab();//解析inittab参数
找到parse_inittab函数,位于busybox-1.7.0initInit.c中
755 static void parse_inittab(void) 756 { ... ... 764 file = fopen(INITTAB, "r");//以只读方式打开/etc/inittab ... 788 while (fgets(buf, INIT_BUFFS_SIZE, file) != NULL) { ... 836 for (a = actions; a->name != 0; a++) { 837 if (strcmp(a->name, action) == 0) { 838 if (*id != '