美文网首页
Android系统启动(二)-Init篇

Android系统启动(二)-Init篇

作者: Stan_Z | 来源:发表于2018-11-05 20:01 被阅读48次

    经过前面的开篇介绍,我们对android系统启动有个一个初步的了解。那么接下来会详细分析几个关键过程。

    一、Init简介

    init进程是Android系统中用户空间的第一个进程(pid=1),它是用户进程的鼻祖,负责孵化各种属性服务、守护进程也包括非常重要的Zygote。init进程是由多个源文件共同组成的,这些文件位于源码目录system/core/init。本文将基于Android7.0源码来分析Init进程。

    二、Init分析

    当内核完成系统设置,它首先在系统文件中寻找”init”文件,最后会调用 /system/core/init/Init.cpp 的 main() 方法。它是init的入口函数。那么来看init.cpp main方法:

    int main(int argc, char** argv) {
       …
        //创建文件并挂载
        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);
            #define MAKE_STR(x) __STRING(x)
            mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC));
            mount("sysfs", "/sys", "sysfs", 0, NULL);
        }
        ...
        //初始化属性相关资源
        property_init();
        ...
        //启动属性服务
        start_property_service();
       ...
        Parser& parser = Parser::GetInstance();
        ...
        //解析init.rc配置文件
        parser.ParseConfig("/init.rc");
        ...
        return 0;
    }
    

    主要关注两点:初始化和启动属性服务、解析init.rc配置文件并启动zygote进程。

    2.1 属性服务

    Android提供的属性服务类似于Windows平台上注册表管理器的机制,内容采用键值对的形式来记录用户、软件的一些使用信息。即使系统或者软件重启,它还是能够根据之前在注册表中的记录,进行相应的初始化工作。应用程序可以通过这个属性机制,查询或者设置相应的属性。我们可以使用getprop命令来查看当前系统中都有哪些属性。

        //初始化属性相关资源
        property_init();
        ...
        //启动属性服务
        start_property_service();
    

    此处初始化并启动了属性服务,代码细节不追究,了解下结论。

    2.2 解析init.rc配置文件并启动zygote进程
    2.2.1 了解Android Init Language

    init.rc是一个配置文件,内部由Android初始化语言(Android Init Language)编写的脚本。先来学习下AIL:
    它主要包含四种类型语句:ActionCommandsServicesOptions

    Action(动作): 通过trigger,即以 on开头的语句,决定何时执行相应的service。

    • on early-init; 在初始化早期阶段触发;
    • on init; 在初始化阶段触发;
    • on late-init; 在初始化晚期阶段触发;
    • on boot/charger: 当系统启动/充电时触发,还包含其他情况,此处不一一列举;
    • on property:<key>=<value>: 当属性值满足条件时触发;

    启动顺序:on early-init -> init -> late-init -> boot

    Service(服务):是一个程序,他在初始化时启动,并在退出时重启(可选),由init进程启动,一般运行于另外一个init的子进程,所以启动service前需要判断对应的可执行文件是否存在。init生成的子进程,定义在rc文件,其中每一个service,在启动时会通过fork方式生成子进程。

    例: service servicemanager(服务名 ) /system/bin/servicemanager ( 路径)

    Command(命令): 要执行的命令

    常用的命令:

    • class_start <service_class_name>: 启动属于同一个class的所有服务;
    • start <service_name>: 启动指定的服务,若已启动则跳过;
    • stop <service_name>: 停止正在运行的服务
    • setprop <name> <value>:设置属性值
    • mkdir <path>:创建指定目录
    • symlink <target> <sym_link>: 创建连接到<target>的<sym_link>符号链接;
    • write <path> <string>: 向文件path中写入字符串;
    • exec: fork并执行,会阻塞init进程直到程序完毕;
    • exprot <name> <name>:设定环境变量;
    • loglevel <level>:设置log级别

    Option(选项):Options是Services的可选项,与service配合使用

    • disabled: 不随class自动启动,只有根据service名才启动;
    • oneshot: service退出后不再重启;
    • user/group: 设置执行服务的用户/用户组,默认都是root;
    • class:设置所属的类名,当所属类启动/退出时,服务也启动/停止,默认为default;
    • onrestart:当服务重启时执行相应命令;
    • socket: 创建名为/dev/socket/<name>的socket
    • critical: 在规定时间内该service不断重启,则系统会重启并进入恢复模式

    default: 意味着disabled=false,oneshot=false,critical=false。

    Action与Option配合使用

    on <trigger> 
       <command> 
       <command> 
    

    举例:

    on boot
        ifup lo
        hostname localhost
        domainname localdomain
        class_start default
    

    Service与Command配合使用

    service <name> <pathname> [ <argument> ]* 
              <option> 
              <option>
    

    举例:

    service healthd /sbin/healthd
        class core
        critical
        seclabel u:r:healthd:s0
        group root system wakelock
    

    另外还有个import,它的作用是导入其他rc文件。

    //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
    
    2.2.2 zygote进程的启动

    回到解析init.rc配置文件:

    parser.ParseConfig("/init.rc”);
    

    这个parser即init_parse.cpp,通过它对init.rc进行解析。在Android 7.0中对init.rc文件进行了拆分,每个服务一个rc文件。我们要分析的zygote服务的启动脚本则在system/core/rootdir/init.zygoteXX.rc中定义,这里拿64位处理器为例,init.zygote64.rc的代码如下所示:

    service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
       class main
       socket zygote stream 660 root system
       onrestart write /sys/android_power/request_state wake
       onrestart write /sys/power/state on
       onrestart restart audioserver
       onrestart restart cameraserver
       onrestart restart media
       onrestart restart netd
       writepid /dev/cpuset/foreground/tasks /dev/stune/foreground/tasks
    

    通过init_parser.cpp完成整个service解析工作,此处就不详细展开讲解析过程,该过程主要是创建一个名”zygote”的service结构体,一个socketinfo结构体(用于socket通信),以及一个包含4个onrestart的action结构体。

    Zygote服务会随着main class的启动而启动,退出后会由init重启zygote,即使多次重启也不会进入recovery模式。zygote所对应的可执行文件是/system/bin/app_process64,通过调用pid =fork()创建子进程,通过execve(svc->args[0], (char)svc->args, (char) ENV),进入App_main.cpp的main()函数。故zygote是通过fork和execv共同创建的。

    流程如下:

    app_main.cpp的main()方法中,最终通过Androidrumtime来启动zygote进程。

    2.3 服务重启

    init进程会启动很多native的service,这些service如果不是oneshot的,当service出现异常挂掉后,init需要将其重新启动起来:

    from gityuan

    具体操作不详细跟了,了解一下结论:

    所有的Service里面只有servicemanager ,zygote ,surfaceflinger这3个服务有onrestart关键字来触发其他service启动过程。

    //zygote可触发media、netd以及子进程(包括system_server进程)重启
    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
        class main
        socket zygote stream 660 root system
        onrestart write /sys/android_power/request_state wake
        onrestart write /sys/power/state on
        onrestart restart media
        onrestart restart netd
    
    //servicemanager可触发healthd、zygote、media、surfaceflinger、drm重启
    service servicemanager /system/bin/servicemanager
        class core
        user system
        group system
        critical
        onrestart restart healthd
        onrestart restart zygote
        onrestart restart media
        onrestart restart surfaceflinger
        onrestart restart drm
    
    //surfaceflinger可触发zygote重启
    service surfaceflinger /system/bin/surfaceflinger
        class core
        user system
        group graphics drmrpc
        onrestart restart zygote 
    

    所以,surfaceflinger、servicemanager、system_server以及zygote自身进程被杀都会触发Zygote重启。

    总结init的主要工作:
    1.创建一些文件夹并挂载设备。
    2.初始化和启动属性服务。
    3.通过解析init.rc 和 其他对应rc文件,启动对应的系统级进程。其中包括后面要讲的zygote。

    本文基于Android7.0源码分析。

    参考:
    https://blog.csdn.net/freekiteyu/article/details/79175010
    http://liuwangshu.cn/framework/booting/1-init.html

    相关文章

      网友评论

          本文标题:Android系统启动(二)-Init篇

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