美文网首页
android FrameWork-Init进程启动过程

android FrameWork-Init进程启动过程

作者: Peakmain | 来源:发表于2021-03-19 10:59 被阅读0次

    init入口函数

    直接看 /system/core/init/Init.cpp 的 main() 方法

    int main(int argc, char** argv) {
        // 清除unmask
        umask(0);
       //1、创建目录挂载分区
        if (is_first_stage) {
            mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
            mkdir("/dev/pts", 0755);
            mkdir("/dev/socket", 0755);
            mount("devpts", "/dev/pts", "devpts", 0, NULL);
            mount("proc", "/proc", "proc", 0, NULL);
            mount("sysfs", "/sys", "sysfs", 0, NULL);
        }
        if (!is_first_stage) {
            //2、对属性进行初始化
            property_init();
        }
       //3、设置子进程信号处理
        signal_handler_init();
       //4、启动属性服务
        start_property_service();
        //5、解析init.rc配置文件
        init_parse_config_file("/init.rc");
    
        while (true) {
            if (!waiting_for_exec) {
               //6、执行命令
                execute_one_command();
             //7、重启进程
                restart_processes();
            }
             ....
        return 0;
    }
    

    main主要做了以下几件事情:

    1. 创建目录、挂载分区
    2. 属性初始化
    3. 设置子进程信号处理函数,主要用于防止init的子进程成为僵尸进程
      • 子进程在暂停和终止的时候发出SIGCHLD信号,Signal_handle_init函数就是用来接收SIGCHILD信号的
      • signal_handle_init函数会调用handle_signal函数,经过层层函数调用,最终会找到zygote进程并移除所有的zygote进程的信息,再重启

    4.启动属性服务
    5.解析init.rc文件
    6.执行命令
    7.重启进程
    僵尸进程
    父进程使用fork创建子进程,在子进程终止之后,如果父进程不知道子进程已经终止了,这是子进程虽然已经退出了,但是系统进程表中还为它保留了一定的信息(比如进程号,退出状态、运行时间),这个子进程就被称为僵尸进程

    解析init.rc

    init.rc源码位于 /system/core/rootdir/init.rc

    import /init.environ.rc
    import /init.usb.rc
    import /init.${ro.hardware}.rc
    import /init.usb.configfs.rc
    import /init.${ro.zygote}.rc
    import /init.trace.rc
    on early-init
    on init
    
    service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    service servicemanager /system/bin/servicemanager
    service surfaceflinger /system/bin/surfaceflinger
    service media /system/bin/mediaserver
    service installd /system/bin/installd
    

    命令主要是:on、import、service。上面列出主要的服务,接下来分析怎么解析的也就是上面的第五步

    int init_parse_config_file(const char* path) {
        INFO("Parsing %s...\n", path);
        Timer t;
        std::string data;
        if (!read_file(path, &data)) {
            return -1;
        }
    
        data.push_back('\n'); // TODO: fix parse_config.
      //解析
        parse_config(path, data);
        dump_parser_state();
    
        NOTICE("(Parsing %s took %.2fs.)\n", path, t.duration());
        return 0;
    }
    static void parse_config(const char *fn, const std::string& data)
    {
        struct listnode import_list;
        struct listnode *node;
        for (;;) {
             //next_token内部是一行一行解析的
            switch (next_token(&state)) {
            case T_EOF:
               //文件结尾
                state.parse_line(&state, 0, 0);
                goto parser_done;
            case T_NEWLINE:
                //新的一行
                state.line++;
                if (nargs) {
                  //不同命令选择不同结构
                    int kw = lookup_keyword(args[0]);
                    if (kw_is(kw, SECTION)) {
                        state.parse_line(&state, 0, 0);
                        parse_new_section(&state, kw, nargs, args);
                    } else {
                        state.parse_line(&state, nargs, args);
                    }
                    nargs = 0;
                }
                break;
            case T_TEXT:
                if (nargs < INIT_PARSER_MAXARGS) {
                    args[nargs++] = state.text;
                }
                break;
            }
        }
    
    parser_done:
        list_for_each(node, &import_list) {
             //循环解析import
             struct import *import = node_to_item(node, struct import, list);
             int ret;
             ret = init_parse_config_file(import->filename);
             if (ret)
                 ERROR("could not import file '%s' from '%s'\n",
                       import->filename, fn);
        }
    }
    

    守护进程

    void signal_handler_init() {
        // Create a signalling mechanism for SIGCHLD.
        int s[2];
        if (socketpair(AF_UNIX, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0, s) == -1) {
            ERROR("socketpair failed: %s\n", strerror(errno));
            exit(1);
        }
    
        signal_write_fd = s[0];
        signal_read_fd = s[1];
    
        // Write to signal_write_fd if we catch SIGCHLD.
        struct sigaction act;
        memset(&act, 0, sizeof(act));
        act.sa_handler = SIGCHLD_handler;
        act.sa_flags = SA_NOCLDSTOP;
        sigaction(SIGCHLD, &act, 0);
          //判断子进程是否退出,里面是个死循环,如果退出则进行处理
        reap_any_outstanding_children();
    
        register_epoll_handler(signal_read_fd, handle_signal);
    }
    //写数据
    static void SIGCHLD_handler(int) {
        if (TEMP_FAILURE_RETRY(write(signal_write_fd, "1", 1)) == -1) {
            ERROR("write(signal_write_fd) failed: %s\n", strerror(errno));
        }
    }
    void register_epoll_handler(int fd, void (*fn)()) {
        epoll_event ev;
        ev.events = EPOLLIN;
        ev.data.ptr = reinterpret_cast<void*>(fn);
        //通过设置epoll_ctl来注册回调函数handle_signal
        if (epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd, &ev) == -1) {
            ERROR("epoll_ctl failed: %s\n", strerror(errno));
        }
    }
    //实际是读数据
    static void handle_signal() {
        // Clear outstanding requests.
        char buf[32];
        read(signal_read_fd, buf, sizeof(buf));
        reap_any_outstanding_children();
    }
    static void reap_any_outstanding_children() {
        while (wait_for_one_process()) {
        }
    }
    static bool wait_for_one_process() {
        int status;
    //子进程如果没有退出则返回0,否则返回进程pid
        pid_t pid = TEMP_FAILURE_RETRY(waitpid(-1, &status, WNOHANG));
        if (pid == 0) {
            return false;
        } else if (pid == -1) {
            return false;
        }
        //根据pid找到对应的服务
        service* svc = service_find_by_pid(pid);
        //当flags不是oneshot或者restart则杀死所有进程
        if (!(svc->flags & SVC_ONESHOT) || (svc->flags & SVC_RESTART)) {
            kill(-pid, SIGKILL);
        }
        //移除所有已经创建的socket
        for (socketinfo* si = svc->sockets; si; si = si->next) {
            char tmp[128];
            snprintf(tmp, sizeof(tmp), ANDROID_SOCKET_DIR"/%s", si->name);
            unlink(tmp);
        }
     //flags 是exec的话,释放所有资源
        if (svc->flags & SVC_EXEC) {
            INFO("SVC_EXEC pid %d finished...\n", svc->pid);
            waiting_for_exec = false;
            list_remove(&svc->slist);
            free(svc->name);
            free(svc);
            return true;
        }
    
        svc->pid = 0;
        svc->flags &= (~SVC_RUNNING);
    
        // Oneshot processes go into the disabled state on exit,
        // except when manually restarted.
        if ((svc->flags & SVC_ONESHOT) && !(svc->flags & SVC_RESTART)) {
            svc->flags |= SVC_DISABLED;
        }
    
        // 禁用和重置进程不会自动重启。
        if (svc->flags & (SVC_DISABLED | SVC_RESET))  {
            svc->NotifyStateChange("stopped");
            return true;
        }
        svc->flags &= (~SVC_RESTART);
        svc->flags |= SVC_RESTARTING;
    
        // 执行重启命令
        struct listnode* node;
        list_for_each(node, &svc->onrestart.commands) {
            command* cmd = node_to_item(node, struct command, clist);
            cmd->func(cmd->nargs, cmd->args);
        }
        return true;
    }
    

    当init的子进程zygote终止的时候,signal_handler_init函数会调用handle_signal函数,最终会找到zygote进程并移除所有zygote进程信息,并重启zygote带有onrestart选项的服务

    epoll和select区别

    • epoll内部用于保存事件的数据类型是红黑树,查找速度快
    • select采用的数组保存信息,查找速度慢

    相关文章

      网友评论

          本文标题:android FrameWork-Init进程启动过程

          本文链接:https://www.haomeiwen.com/subject/rqkpcltx.html