内核启动第一个程序

从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/init
lrwxrwxrwx    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 就运行起来了


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值