【Android】之【系统启动】

一、流程总览

系统启动->BootLoader->Linux内核->init -> zygote -> systemserver->Launcher

① 启动电源以及系统启动

当电源按下时引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序Bootloader到RAM,然后执行。

② 引导程序BootLoader

引导程序BootLoader是在Android操作系统开始运行前的一个小程序,它的主要作用是把系统OS拉起来并运行。

③ Linux内核启动

内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置,它首先在系统文件中寻找init.rc文件,并启动init进程。

④ init进程启动

解析init.rc配置文件,初始化和启动属性服务,并且启动Zygote进程。

⑤ Zygote进程启动

创建JavaVM并为JavaVM注册JNI,创建服务端Socket,启动SystemServer进程。

⑥ SystemServer进程启动

启动Binder线程池和SystemServiceManager,并且启动各种系统服务。

⑦ Launcher启动

被SystemServer进程启动的ActivityManagerService会启动Launcher,Launcher启动后会将已安装应用的快捷图标显示到界面上。
在这里插入图片描述

在这里插入图片描述

二、模块解析

Init进程

init是一个进程,确切地说,它是Linux系统中用户空间的第一个进程。由于Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程,它的进程号是1。作为天字第一号的进程,init被赋予了很多极其重要的工作职责,简单概括为

1、创建和挂载启动所需的文件目录。
2、初始化和启动Linux属性服务。
3、解析init.rc配置文件,首先开启ServiceManager和MediaServer等关键进程。
4、init进程fork启动Zygote服务进程。

将init的工作流程精简为以下四点
1、解析两个配置文件,其中,将分析对init.rc文件的解析
2、执行各个阶段的动作,创建Zygote的工作就是在其中的某个阶段完成的。
3、调用property_init初始化属性相关的资源,并且通过property_start_service启动属性服务。
4、init进入一个无限循环,并且等待一些事情的发生。重点关注init如何处理来自socket和来自属性服务器相关的事情。

init进程的入口函数是main(system/core/init/init.c)
[–>init.c]

   main(){
   //解析init.rc配置文件
   parse_config_file("/init.rc");
  
   //初始化和属性相关的资源
   property_init();
   }

[–>init.rc]

  import /init.${ro.zygote}.rc  
  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 media
    onrestart restart netd

Zygote进程

Zygote的中文翻译为“受精卵”,是生命的开始,从字面意思,我们大致可以领会到它在Android系统中的地位。Dalvik/ART,应用程序进程以及运行系统的关键服务SystemServer都是由Zygote进程创建的,所以一般也称它为孵化器。Zygote需要做很多工作,归纳起来大致有如下几条:
(1)创建Dalvik/ART(启动VM虚拟机)
startVm property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m"); 设置虚拟机heapsize,默认为16MB。绝大多数厂商都会修改这个值,一般是32MB。 heapsize不能设置过小,否则在操作大尺寸的图片时无法分配所需内存。 这里有一个问题,即heapsize既然是系统级的属性,那么能否根据不同应用程序的需求来进行动 态调整?我开始也考虑过能否实现这一构想,不过希望很快就破灭了。对这一问题,我们将在拓展部分深入讨论。
(2)从Native层进入到Java框架层。也就是说Zygote开创了Java框架层,这一步是通过Native层通过JNI方式调用ZygoteInit类的main方法来实现。Zygote的路径为:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
(3)ZygoteInit的main方法中会创建一个Service端的Socket,名称为“zygote”,用于等待AMS请求Zygote创建新的应用程序进程。
(4)ZygoteInit的main方法中还会通过fork方式创建并启动SystemServer进程

总结下关键的几个步骤
1、启动VM虚拟机。
2、创建Zygote的Socket服务端。
3、加载预加载的类到内存。
4、加载Android通用的资源比如color、drawable等。
5、加载JNI注册、lib库等等资源。
6、fork出SystemServer进程。
7、开启循环监听客户端的请求。

Zygote是由init进程根据init.rc文件中的配置项而创建的。zygote最初的名字叫“app_process”,这个名字是在Android.mk文件中被指定的,但app_process在运行过程中,通过Linux下的pctrl系统调用将自己的名字换成了“zygote”,所以我们通过ps命令看到的进程名是“zygote”。

它的原型app_process所对应的源文件是App_main.cpp,代码如下所示

[–>App_main.cpp]

static const char ZYGOTE_NICE_NAME[] = "zygote";

int main(int argc, char* const argv[]){
    set_process_name(niceName.string());//设置本进程名为zygote,这正是前文所讲的“换名把戏”。

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args);
    }
}    

Zygote的这个main函数虽很简单,但其重要功能却是由AppRuntime的start来完成的。下面,我们就来具体分析这个AppRuntime。

[–>AndroidRuntime.cpp]

void AndroidRuntime::start(const char*className, const bool startSystemServer)
{
    //className的值是"com.android.internal.os.ZygoteInit"
    //startSystemServer的值是true
    //① 创建虚拟机
    if(startVm(&mJavaVM, &env) != 0)
        goto bail;
       
       /*
       startVm
       property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m");
       设置虚拟机heapsize,默认为16MB。绝大多数厂商都会修改这个值,一般是32MB。
       heapsize不能设置过小,否则在操作大尺寸的图片时无法分配所需内存。
       这里有一个问题,即heapsize既然是系统级的属性,那么能否根据不同应用程序的需求来进行动
       态调整?我开始也考虑过能否实现这一构想,不过希望很快就破灭了。对这一问题,我们将在拓展
       部分深入讨论。
       */

  //②注册JNI函数
    if(startReg(env) < 0) {
        goto bail;
      }   

  //找到ZygoteInit类的static main函数的jMethodId。
     startMeth = env->GetStaticMethodID(startClass, "main","([Ljava/lang/String;)V");
     ......
     /*
        ③通过JNI调用Java函数,注意调用的函数是main,所属的类是
          com.android.internal.os.ZygoteInit,传递的参数是
          “com.android.internal.os.ZygoteInit true”,
          调用ZygoteInit的main函数后,Zygote便进入了Java世界!
          也就是说,Zygote是开创Android系统中Java世界的盘古。
     */
}

Welcome to Java World
[–>ZygoteInit.java]

public static void main(String argv[]) {
  try {
       SamplingProfilerIntegration.start();
       //①注册Zygote用的socket
       registerZygoteSocket();
       //②预加载类和资源
       preloadClasses();
       preloadResources();
       ......
       //强制一次垃圾收集
       gc();
      
       //我们传入的参数满足if分支
       if (argv[1].equals("true")) {
          startSystemServer();//③启动system_server进程
       }
    }
}

SystemServer进程

ZygoteInit.java
  startSystemServer();
   init1
    init2 启动一个ServerThread

   SystemServer.java
     ServerThread的run函数
      //系统各种重要服务都在这里启动
       startBootstrapServices();
       startCoreServices(); //AMS LightsService BatteryService UsageStatsService ...
       startOtherServices();

三、App 启动过程

在这里插入图片描述

这里以启动微信为例子说明

  1. Launcher 通知 AMS 要启动微信了,并且告诉AMS要启动的是哪个页面也就是首页是哪个页面。
  2. AMS 收到消息告诉 Launcher 知道了,并且把要启动的页面记下来。
  3. Launcher 进入Paused状态,告诉 AMS,你去找微信吧。

上述就是 Launche r和 AMS 的交互过程

  1. AMS 检查微信是否已经启动了也就是是否在后台运行,如果是在后台运行就直接启动,如果不是,AMS
    会在新的进程中创建一个ActivityThread 对象,并启动其中的 main 函数。
  2. 微信启动后告诉 AMS,启动好了。
  3. AMS 通过之前的记录找出微信的首页,告诉微信应该启动哪个页面。
  4. 微信按照AMS通知的页面去启动就启动成功了。

在这里插入图片描述

四、Activity启动过程

Activity 启动过程是由 ActivityMangerService(AMS) 来启动的,底层 原理是 Binder实现的 最终交给 ActivityThread 的 performActivity 方法来启动它

ActivityThread 大概可以分为以下五个步骤

  1. 通过 ActivityClientRecoed 对象获取 Activity 的组件信息
  2. 通过 Instrument 的 newActivity 使用类加载器创建 Activity 对象
  3. 检验 Application 是否存在,不存在的话,创建一个,保证 只有一个 Application
  4. 通过 ContextImpl 和 Activity 的 attach 方法来完成一些初始化操作
  5. 调用 onCreate方法。

五、参考

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Crazy程序猿2020

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值