busybox init进程分析

本人喜欢用代码+伪代码的方式写笔记。文中的花括号可能是方便记录而已。

如:

hw_get_module(LED_HARDWARE_MODULE_ID, (const hw_module_t**)&module)
{
    问:怎么获得模块信息的?
    答:hardware\libhardware\Hardware.c

    ...........

}

原创分析, 转载请注明出处:http://www.cnblogs.com/langlang/

作者email: dayhappyhappy@163.com

 

busybox-1.18.5 分析
文件  init.c
int init_main(int argc UNUSED_PARAM, char **argv)
{
    //填充链表init_action_list
    parse_inittab();
    原型:new_init_action(uint8_t action_type, const char *command, const char *cons)
    {
        //读取文件 /etc/inittab
        parser_t *parser = config_open2("/etc/inittab", fopen_for_read);
        //假如 /etc/inittab不存在
        if (parser == NULL)
        {
            new_init_action(CTRLALTDEL, "reboot""");
            原型 new_init_action(uint8_t action_type, const char *command, const char *cons)
            {
                struct init_action *a, **nextp;
                {
                    注 : struct init_action {
                                struct init_action *next;      //链表指针
                                pid_t pid;                    //线程ID
                                uint8_t action_type;        // action的类型  ①
                                char terminal[CONSOLE_NAME_SIZE];   //运行该command的终端  (*cons)
                                char command[COMMAND_SIZE];         //command字段用来指定要执行命令(含路径),包括命令行选项。
                            };
                }
                nextp = &init_action_list;
                
                假如init_action_list不为空
                {
                    比较查找
                }
                假如为空
                {
                    a = xzalloc(sizeof(*a));
                }
                a->action_type = action_type;
                safe_strncpy(a->command, command, sizeof(a->command));
                safe_strncpy(a->terminal, cons, sizeof(a->terminal));
            }
            ..........
        }
        else
        {
            //分析
            new_init_action(1 << action, token[3], tty);
        }
    }

    /* Now run everything that needs to be run */
    /* First run the sysinit command */
    run_actions(SYSINIT);
    原型:void run_actions(int action_type)
    {
        struct init_action *a;
        for (a = init_action_list; a; a = a->next) {
            if (!(a->action_type & action_type))
                continue//继续查找

            if (a->action_type & (SYSINIT | WAIT | ONCE | CTRLALTDEL | SHUTDOWN)) {
                pid_t pid = run(a); //执行
                {
                    创建进程
                    //ASKFIRST类型需要等待回车
                    if (BB_MMU && (a->action_type & ASKFIRST)) {
                        static const char press_enter[] ALIGN1 =
                            "\nPlease press Enter to activate this console. ";
                        char c;
                        //输出
                        dbg_message(L_LOG, "waiting for enter to start '%s'"
                        "(pid %d, tty '%s')\n",a->command, getpid(), a->terminal);
                        full_write(STDOUT_FILENO, press_enter, sizeof(press_enter) - 1);
                        while (safe_read(STDIN_FILENO, &c, 1) == 1 && c != '\n')
                            continue//等待回车
                    }
                }
                if (a->action_type & (SYSINIT | WAIT | CTRLALTDEL | SHUTDOWN))
                    waitfor(pid); //待它的command执行完,再继续执行。
            }
            if (a->action_type & (RESPAWN | ASKFIRST)) {
                /* Only run stuff with pid == 0. If pid != 0,
                * it is already running
                
*/
                if (a->pid == 0)
                    a->pid = run(a); //init则不会等待它执行完
            }
        }
    }
    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);
    while (1) {
        /* (Re)run the respawn/askfirst stuff */
        run_actions(RESPAWN | ASKFIRST);
        maybe_WNOHANG |= check_delayed_sigs();
        /* Don't consume all CPU time - sleep a bit */
        sleep(1);
        maybe_WNOHANG |= check_delayed_sigs();
    
    }
}

① action_type
/* 为init提供初始化命令脚本的路径 */
#define SYSINIT     0x01
/* 告诉init必须等到相应的进程执行完成之后才能继续执行 */
#define WAIT        0x02
/* 仅执行相应的进程一次,而且不会等待它执行完成 */
#define ONCE        0x04
/* 每当相应的进程终止执行时,重新启动该进程 */
#define RESPAWN     0x08
/*  类似respawn,主要用途是减少系统上执行的终端应用程序的数量。
它将会促使init在控制台上显示
“Please press Enter to active this console”的信息,
并在重新启动进程之前等待用户按下“enter”键  
*/
#define ASKFIRST    0x10
/* 当按下Ctrl+Alt+Delete组合键时,执行相应的进程 */
#define CTRLALTDEL  0x20
/* 当系统关机时,执行相应的进程  */
#define SHUTDOWN    0x40
/* 当init重新启动时,执行相应的进程,通常此处所执行的进程就是init本身  */

#define RESTART     0x80 

posted @ 2012-04-19 19:34  朗笑江湖  阅读(1621)  评论(0编辑  收藏  举报