内核启动第一个程序

来源:互联网 发布:手机蜂窝数据打不开 编辑:程序博客网 时间:2024/05/21 09:45

从kernel_init()函数我们知道,init_post是最后执行的一个函数,我们来分析这个函数:

static int noinline init_post(void){    free_initmem();    unlock_kernel();    mark_rodata_ro();    system_state = SYSTEM_RUNNING;    numa_default_policy();    /* 首先打开终端设备 */    if (sys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0)        printk(KERN_WARNING "Warning: unable to open an initial console.\n");    /* 然后复制两个,共三个,分别是stdin,stdout,stderr */    (void) sys_dup(0);    (void) sys_dup(0);    if (ramdisk_execute_command) {        run_init_process(ramdisk_execute_command);        printk(KERN_WARNING "Failed to execute %s\n",                ramdisk_execute_command);    }    /*     * We try each of these until one succeeds.     *     * The Bourne shell can be used instead of init if we are     * trying to recover a really broken machine.     */    /* 执行命令行传入的int=xxxx程序,       如果没有就接着向下执行,如果成功则会一直运行不会向下执行。     */    if (execute_command) {        run_init_process(execute_command);        printk(KERN_WARNING "Failed to execute %s.  Attempting "                    "defaults...\n", execute_command);    }        /* 如果上面没有成功,则向下执行 */    run_init_process("/sbin/init");    run_init_process("/etc/init");    run_init_process("/bin/init");    run_init_process("/bin/sh");    panic("No init found.  Try passing init= option to kernel.");}
从上面可以看出如果执行命令里没有 init=xxx 的参数,那么就会依次向下执行

run_init_process("/sbin/init");......

因为我们的执行命令里没有init=xxx参数,所以 init 就是我们的第一个进程

但是如果我们执行下面的命令:

ls -l /sbin/initlrwxrwxrwx    1 messageb messageb       14 Dec 21  2012 /sbin/init -> ../bin/busybox

我们发现第一个程序是链接到busybox的,也就是说启动是busybox程序,所以我们要分析busybox源码里的init.c源码。

打开 busybox 源码中的 init.c文件,分析int.c 是怎么解析 /etc/inittab 文件以及执行程序的:

init_main    parse_inittab        file = fopen(INITTAB, "r");  //打开配置文件        new_init_action              //创建init_action结构,并加入init_action_list链表            run_actions(SYSINIT);            waitfor(a, 0);               //执行应用程序,等待它执行完毕                run(a);              //创建process子进程                waitpid              //等待它结束        delete_init_action(a);       //从init_action_list链表中删掉                            run_actions(WAIT);        waitfor(a, 0);               //执行应用程序,等待它执行完毕                run(a);              //创建process子进程                waitpid              //等待它结束        delete_init_action(a);       //从init_action_list链表中删掉                        run_actions(ONCE);        run(a);                      //不等待了,运行完后直接结束        delete_init_action(a);                        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. ";                                        等待回车                }                            wpid = wait(NULL);           //等待子进程退出        while (wpid > 0) {                a->pid = 0;        }    }

当然在busybox/example下,我们可以查到 inittab的格式说明:

# Format for each entry: <id>:<runlevels>:<action>:<process>
id --> /dev/it  用于终端:stdin, stdout,stderr
runlevels       : 忽略
action             :执行时机
process         : 应用程序或脚本

这样第一个进程 init 就运行起来了


原创粉丝点击