• 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 

  • 相关阅读:
    【Java Web开发学习】Spring加载外部properties配置文件
    【Java Web开发学习】Spring4整合thymeleaf视图解析
    快速入门系列--MVC--06视图
    快速入门系列--WebAPI--03框架你值得拥有
    快速入门系列
    iOS 自己封装的网络请求,json解析的类
    iOS 本地通知
    iOS8 自定义navigationItem.titleView
    iOS8 UICollectionView横向滑动demo
    基于Spring开发
  • 原文地址:https://www.cnblogs.com/langlang/p/2457757.html
Copyright © 2020-2023  润新知