rootfs启动第1个程序
static int noinline init_post(void)
{
if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) //标准输出
(void) sys_dup(0); //复制,作为标准输入
(void) sys_dup(0); //复制,作为标准错误
if (execute_command) {
run_init_process(execute_command); //若有传入参数,"init=...",则执行该函数,该函数一般是死循环,一去不返
}
run_init_process("/sbin/init"); //若上面的函数执行失败,则执行该函数,该函数一般是死循环,一去不返
run_init_process("/etc/init"); //若上面的函数执行失败,则执行该函数,该函数一般是死循环,一去不返
run_init_process("/bin/init"); //若上面的函数执行失败,则执行该函数,该函数一般是死循环,一去不返
run_init_process("/bin/sh"); //若上面的函数执行失败,则执行该函数,该函数一般是死循环,一去不返
}
static int __init init_setup(char *str)
{
execute_command = str;
}
__setup("init=", init_setup);
根文件系统下的,ls,cp,init 程序,本质是链接到 busybox.
内核的目的:启动应用程序。
/sbin/init 等第一个应用程序启动后,是要启动客户的应用程序
init 程序:
(1)读取配置文件
(2)解析配置文件
(3)执行(用户程序)
busybox -> init_main busybox-1.7.0\init\init.c
| signal(SIGINT, ctrlaltdel_signal);
| run_actions(CTRLALTDEL);
| signal(SIGTERM, shutdown_signal);
| shutdown_system();
| run_actions(SHUTDOWN);
| parse_inittab
| file = fopen(INITTAB, "r"); //打开配置文件 "/etc/inittab" /* inittab file location */
| new_init_action(a->action, command, id); //(1)创建一个 init_action 结构,填充 (2)把这个结构放入 init_action_list 链表
| run_actions(SYSINIT);
| waitfor(a, 0); //执行应用程序,等待它执行完毕
| run(a); //创建process子进程
| waitpid(runpid, &status, 0); //等待它结束
| delete_init_action(a); //在 init_action_list 链表中删除
| run_actions(WAIT);
| waitfor(a, 0); //执行应用程序,等待它执行完毕
| run(a); //创建process子进程
| waitpid(runpid, &status, 0); //等待它结束
| delete_init_action(a); //在 init_action_list 链表中删除
| run_actions(ONCE);
| run(a); //创建process子进程
| delete_init_action(a); //在 init_action_list 链表中删除
| while(1){
run_actions(RESPAWN);
| if (a->pid == 0) {
a->pid = run(a);
}
run_actions(ASKFIRST);
| if (a->pid == 0) {
a->pid = run(a);
| 打印"\nPlease press Enter to activate this console. "
| while (read(0, &c, 1) == 1 && c != '\n'); 等待回车
| 创建进程
}
wpid = wait(NULL); //等待子进程推出
while (wpid > 0) {
a->pid = 0; //退出后,就设置pid=0
}
}
static void parse_inittab(void)
{
if (file == NULL) {
/* No inittab file -- set up some default behavior */ //从默认的 new_init_action 反推出默认的配置文件
/* Reboot on Ctrl-Alt-Del */
new_init_action(CTRLALTDEL, "reboot", ""); //::CTRLALTDEL:reboot
/* Umount all filesystems on halt/reboot */
new_init_action(SHUTDOWN, "umount -a -r", ""); //::SHUTDOWN:umount -a -r
/* Swapoff on halt/reboot */
if (ENABLE_SWAPONOFF) new_init_action(SHUTDOWN, "swapoff -a", ""); //该项一般不用
/* Prepare to restart init when a HUP is received */
new_init_action(RESTART, "init", ""); //::RESTART:init
/* Askfirst shell on tty1-4 */
new_init_action(ASKFIRST, bb_default_login_shell, ""); //::ASKFIRST:-/bin/sh
new_init_action(ASKFIRST, bb_default_login_shell, VC_2); //tty2::ASKFIRST:-/bin/sh
new_init_action(ASKFIRST, bb_default_login_shell, VC_3); //tty3::ASKFIRST:-/bin/sh
new_init_action(ASKFIRST, bb_default_login_shell, VC_4); //tty4::ASKFIRST:-/bin/sh
/* sysinit */
new_init_action(SYSINIT, INIT_SCRIPT, ""); //::SYSINIT:/etc/init.d/rcS
}
}
new_init_action(ASKFIRST, bb_default_login_shell, VC_2); //实际等于 new_init_action(ASKFIRST, "-/bin/sh", "/dev/tty2");
static void new_init_action(int action, const char *command, const char *cons)
(1)创建一个 init_action 结构,填充
(2)把这个结构放入 init_action_list 链表
busybox-1.7.0\examples\inittab 的格式如下
# Format for each entry: <id>:<runlevels>:<action>:<process>
id ==> /dev/id,用作终端, stdin, stdout, stderr
runlevels: 忽略
action: 执行时机 sysinit, respawn, askfirst, wait, once, restart, ctrlaltdel, and shutdown.
process: 应用程序或脚本
参考:韦东山Linux教程