初始化程序的作用:
初始化程序是busybox的init.c生成的,分析源码:
if (argv[1]
&& (strcmp(argv[1], "single") == 0 || strcmp(argv[1], "-s") == 0 || LONE_CHAR(argv[1], '1'))
) {
new_init_action(RESPAWN, bb_default_login_shell, "");
} else {
//解析inittab的参数
parse_inittab();
}
在parse_inittab();函数中首先会打开文件/etc/inittab
parser_t *parser = config_open2("/etc/inittab", fopen_for_read);
如果没有此文件会执行一些①默认操作,否则②解析inittab文件。
①默认操作如下:
if (parser == NULL)
#endif
{
/* No inittab file - set up some default behavior */
/* Sysinit */
new_init_action(SYSINIT, INIT_SCRIPT, "");
/* Askfirst shell on tty1-4 */
new_init_action(ASKFIRST, bb_default_login_shell, "");
//TODO: VC_1 instead of ""? "" is console -> ctty problems -> angry users
new_init_action(ASKFIRST, bb_default_login_shell, VC_2);
new_init_action(ASKFIRST, bb_default_login_shell, VC_3);
new_init_action(ASKFIRST, bb_default_login_shell, VC_4);
/* Reboot on Ctrl-Alt-Del */
new_init_action(CTRLALTDEL, "reboot", "");
/* Umount all filesystems on halt/reboot */
new_init_action(SHUTDOWN, "umount -a -r", "");
/* Swapoff on halt/reboot */
new_init_action(SHUTDOWN, "swapoff -a", "");
/* Restart init when a QUIT is received */
new_init_action(RESTART, "init", "");
return;
}
分析new_init_action(SYSINIT, INIT_SCRIPT, "");函数,此函数会创建一个init_action类型的结构体链表,把每个项目加到链表里去。
struct init_action {
struct init_action *next;
pid_t pid;
uint8_t action_type; //动作时机
char terminal[CONSOLE_NAME_SIZE];//指定用于执行的终端设备,比如设定为tty0,解析后时会变为/dev/tty0.
char command[1]; //执行的动作命令
};
变量action_type是执行的时机,包括SYSINIT、WAIT、ONCE;系统初始化、等待执行结束的任务、执行一次
RESPAWN、ASKFIRST;重复、执行前询问。
CTRLALTDEL、SHUTDOWN、RESTART。ctrl&alt&del快捷键、关机、重启。
command变量就是对应执行的命令。
char terminal[CONSOLE_NAME_SIZE];//就是inittab的<id>项,指定用于执行的终端设备,比如设定为tty0,解析后时会变为/dev/tty0。例如登录时要指定使用那个终端进行登录。
有了action_type、command这两项就可以知道在什么时候要执行什么命令。
如何执行:
有了action_type链表之后会直接执行三种类型的命令SYSINIT、WAIT、ONCE。然后执行RESPAWN | ASKFIRST的命令。
/* Now run everything that needs to be run */
/* First run the sysinit command */
run_actions(SYSINIT);
check_delayed_sigs();
/* Next run anything that wants to block */
run_actions(WAIT);
check_delayed_sigs();
/* Next run anything to be run only once */
run_actions(ONCE);
其他类型的命令会在合适的时机执行。
示例:代码中的默认操作
# define INIT_SCRIPT "/etc/init.d/rcS"
new_init_action(SYSINIT, INIT_SCRIPT, "");
就是在初始化时执行了"/etc/init.d/rcS"这个脚本,所以这个脚本也就是开机配置脚本。
总结:
1、在制作根文件系统时要有/etc/inittab文件,用于指定一些操作,且必须指定一个开机配置脚本,一般为/etc/init.d/rcS。
2、在制作根文件系统时要有/etc/init.d/rcS脚本文件,用于执行开机 配置。