Android进阶知识树——Android系统的启动过程

1、init进程

作为Android开发者和Android使用者,相信每个人都接触过多种Android设备,不管是哪种品牌、哪种类型的Android设置,在使用之前都要完成开机操作,对于普通用户来说开机只是一个操作过程,但对于开发者有没有想过Android是如何开机的?是如何从断电状态启动到可操作交互的?开发者都听过init进程、孵化器进程已经开发中使用的各种服务,那么它们又是如何启动如何工作的呢?带着这些问题进入本篇文章的主题Androdi系统的启动过程;

  • Android系统的启动过程总结
  1. 启动电源:按下电源后,程序从固定地方开始加载引导程序到RAM中
  2. 引导程序BootLoader:Android系统开始执行引导程序,并同时拉起并运行系统的OS
  3. Linux内核启动:当内核启动完成后,首先寻找init.rc配置文件并启动init进程
  4. init进程启动:在init进程中完成属性服务的初始、Zygote进程的启动

由上面的程序启动过程知道,程序在执行完引导程序并启动内核后,首先会查找init文件,在init文件中首先执行main()方法

  • init.main()
......
property_init();//1
......
sigchld_handler_init();//2
......
start_property_service();
......
LoadBootScripts(am, sm);

static void LoadBootScripts(ActionManager& action_manager, ServiceList& service_list) {
   
    Parser parser = CreateParser(action_manager, service_list);
    parser.ParseConfig("/init.rc"); //3
}

在main()函数中主要执行一下操作:

  1. 初始化和启动属性服务
  2. 设置进程信号处理
  3. 解析init.rc配置文件
1.1、属性服务初始化与启动
  • 属性服务的初始化
  1. 创建非阻塞的Socket
  2. 调用listen函数对对属性进行监听
  3. 当有数据更新时,init进程会调用handle_property_set_fd函数进行处理
  • 处理客户端请求
  1. 服务属性接收到客户端请求时调用handle_property_set_fd()处理数据
  2. 根据属性分类处理:普通属性、控制属性
1.2、设置进程信号处理
  • 僵尸进程:父进程通过Fork创建子进程,当子进程终止之后,如果父进程不知道此时子进程已结束,此时系统中会仍然保存着进程的信息,那么子进程就会成为僵尸进程
  1. 僵尸进程危害:系统资源有限,僵尸进程会占用系统资源,当资源耗尽时系统将无法创建新的进程

由僵尸进程的定义知道,出现僵尸进程的原因就是父进程与子进程之间通信中断,signal_handler_init函数就是在父进程中监听子进程的状态,在子进程暂停或终止时会发送SIGCHLD信号,signal_handler_init会接收和处理信号,当接收到子进程终止时及时的释放资源

1.3、解析init配置文件

配置文件的解析和处理也是init进程中最主要的部分,安卓中将系统的配置文件保存在init.rc文件中,而Android 8.0之后对init.rc文件浸信会拆分,将每个服务以启动脚本的形式单独存在,然后在init.rc中引入所需要的服务脚本,在启动的时候就可以实现所有服务的启动,这里以接下来要分析的Zygote的启动脚本为例,看看系统是如何定义和处理脚本的

  • 启动脚本——init.zygote64.rc
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root
    group root readproc reserved_disk
    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
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

启动脚本中参数介绍:

  1. zygote:创建的进程名称
  2. /system/bin/app_process64 :执行的文件路径
  3. class main:表示Zygote的classname为main,后面会根据main查找Zygote服务
  4. onrestart:当服务启动时需要重启的服务

上面启动脚本文件的名称为init.zygote64.rc,脚本文件名称表示只支持64系统,不过有的启动过脚本会同时支持32为和64为系统,如init.zygote64_32.rc

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    class main
      ......
    writepid /dev/cpuset/foreground/tasks

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
    class main
      .......
    writepid /dev/cpuset/foreground/tasks

init.zygote64_32.rc脚本文件中有有两个Zygote服务,一个主模式支持64位的名为zygote进程,另一个辅模式支持32为名为zygote_secondary进程,系统会根据设备的属性决定启动的服务;

  • 解析启动脚本

init进程中会使用ServerParse对Service的启动脚本进行解析,最终会针对启动脚本中的每个服务创建对应的实例,然后将所有的对象实例缓存在Service裢表中,在启动服务时就会从此列表中查找对应的服务对象;

2、Zygote进程启动

在init.rc文件中引入Zygote的启动脚本,所以在解析init.rc配置文件的服务时,就会将Zygote启动脚本中的服务解析保存在Service的裢表中

import /init.${
   ro.zygote}.rc
  • init启动Zygote进程
on nonencrypted
    class_start main
    class_start late_start

在解析服务后,会继续init.rc配置文件中的程序,程序执行class_start main,由前面的服务脚本可知classnam为main代表的时Zygote服务,所以此处代表启动Zygote进程,首先会遍历前面保存解析Service的链表,查找classname为main()的服务,然后执行Service中的start()方法;

Result<Success> Service::Start() {
   
pid_t pid = -1;
    if (namespace_flags_) {
   
        pid = clone(nullptr, nullptr, namespace_flags_ | SIGCHLD, nullptr);
    } else {
   
        pid = fork(); 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值