https://blog.csdn.net/qq_30621333/article/details/113863338 (详细的启动框架图)
https://zhuanlan.zhihu.com/p/127074795?utm_source=wechat_session
https://blog.csdn.net/lvyaer_1122/article/details/130508216 (Android12 内核启动与init进程启动)
https://www.jianshu.com/p/3460d78e4299

https://www.cnblogs.com/Oude/p/12365102.html

https://blog.csdn.net/weixin_34399060/article/details/91417682 (详解了Action如何触发、Service如何启动)

https://article.itxueyuan.com/xOMye (selinux机制与init启动)
https://zhuanlan.zhihu.com/p/109199714
https://blog.csdn.net/mafei852213034/article/details/117049319

https://mp.weixin.qq.com/s/N1zIlIETYxHwnxBPVvnGfw (系列型文章,非常之详细!)

https://www.cnblogs.com/yuanqiangfei/p/16802086.html(非常全)

一、init进程启动流程

内核是如何启动init进程的

https://blog.csdn.net/fu_kevin0606/article/details/53320515

https://blog.csdn.net/u010783226/article/details/119810208
通过kernel/init/main.c中的static int __ref kernel_init(void *unused)调用init程序

static int __ref kernel_init(void *unused)
{
    if (ramdisk_execute_command) {
        ret = run_init_process(ramdisk_execute_command);
        if (!ret)
            return 0;
        pr_err("Failed to execute %s (error %d)\n",
               ramdisk_execute_command, ret);
    }

    /*
     * 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.
     */
    if (execute_command) {
        ret = run_init_process(execute_command);
        if (!ret)
            return 0;
        panic("Requested init %s failed (error %d).",
              execute_command, ret);
    }
    if (!try_to_run_init_process("/sbin/init") ||
        !try_to_run_init_process("/etc/init") ||
        !try_to_run_init_process("/bin/init") ||
        !try_to_run_init_process("/bin/sh"))
        return 0;

    panic("No working init found.  Try passing init= option to kernel. "
          "See Linux Documentation/init.txt for guidance.");
}

1.init进程的启动

内核启动之后将会初始化软硬件环境,加载驱动程序,挂载根文件系统,然后创建 init 进程,init 作为系统中的第一个用户进程,其进程号为 1,在创建 init 进程之时,系统会执行位于 system/core/init 下的 init.cpp 程序.init 进程主要做了三件事情:创建用户空间文件夹并挂载、启动属性服务、解析位于 system\core\rootdir 文件夹下的 init.rc 文件

2.init.rc配置文件

https://blog.csdn.net/zhonglunshun/article/details/78615980 (几乎每一行都注释了)

要点:

1)Android初始化语言编写(Android Init Language)语法

https://www.jianshu.com/p/13fb7dbc283c

包括:Action、Commands、Services(开机服务)、Options和Import。

1-1)Action
on <trigger> [&& <trigger>]*     //设置触发器  
   <command>  
   <command>      //动作触发之后要执行的命令

Action的command:https://blog.csdn.net/zhangyongfeiyong/article/details/53668124

1-2)Services
service <name> <pathname> [ <argument> ]*   //<service的名字><执行程序路径><传递参数>  
   <option>       //option是service的修饰词,影响什么时候、如何启动services  
   <option>  
   ...  

service的常用option:

https://blog.csdn.net/langxianwenye/article/details/41043261

  • onrestart
    在Service重启时执行命令.

  • shutdown critical
    shutdown critical属性可以被用来标记一个服务为“关闭关键”服务,这意味着在系统关闭过程中,如果这个服务没有正确关闭,系统可能会继续尝试关闭,以防止进入不稳定状态。

service分类

由class关键字标识,有main、core、late_start3种类型。 https://blog.csdn.net/w2064004678/article/details/105651543

Import: 导入子init.rc文件

2)解析

类似于xml解析,反序列化的过程。 Action、Service、Import解析

3.服务的启动(zygote进程启动)

init 进程通过解析 init.rc 文件将 action 保存在 ActionManager 的 actions 链表中,然后通过遍历 actions 链表,执行 action 命令对应的处理函数,从而转至 builtins.cpp 的 do_class_start 函数,之后通过 Service 的 StartIfNotDisabled 调用 Service 的 Start 函数,最终通过 Start 函数创建 zygote 进程,执行对应的 app_main.cpp 文件(frameworks/base/cmds/app_process/app_main.cpp)启动 zygote。

  • 查看服务的运行情况 通过getprop | grep init.svc 可查看所有的service运行状态

4.init进程的作用

init 是系统中的第一个用户进程,它的主要作用是创建用户空间文件夹并挂载、启动属性服务、 解析 init.rc 文件并启动 zygote 进程。

二、Zygote进程启动流程

https://zhuanlan.zhihu.com/p/343232160
https://blog.csdn.net/weixin_34399060/article/details/91417682
init.rc文件中:

import /init.${ro.zygote}.rc

on nonencrypted
    # A/B update verifier that marks a successful boot.
    exec - root -- /system/bin/update_verifier nonencrypted
    class_start main
    class_start late_start复制代码

ro.zygote相关文件中,zygote的class是main,所以nonencrypted触发器被触发时,zygote服务启动。

1)nonencrypted触发器何时触发:
研究class_start的实现原理可知:
1-1)init无限循环时system/core/init/builtins.cpp 下用于启动 zygote 的 do_class_start函数将被执行。
1-2)builtins.cpp会调用service.cpp的 StartIfNotDisabled方法,最终调用Start方法,创建子进程。


bool Service::Start() {
    ....
   //创建子进程
    pid_t pid = fork();
    if (pid == 0) {
        ...
       //执行对应 service 对应的执行文件,args_[0].c_str() 就是执行路径
        if (execve(args_[0].c_str(), (char**) &strs[0], (char**) ENV) < 0) {
            ERROR("cannot execve('%s'): %s\n", args_[0].c_str(), strerror(errno));
        }

        _exit(127);
    }

    ....
    return true;
}

1-3)接着init.zygotexx.rc的zygote服务调用/system/bin/app_processXX程序,最终zygote进程在frameworks/base/cmds/app_process/app_main.cpp中被启动。


0 条评论

发表回复

您的电子邮箱地址不会被公开。