Android深水区:Android系统启动

2021-06-30  本文已影响0人  天马呵呵拳

Android深水区:Android系统启动

开篇

对于Android系统,有一张大家都见过的系统架构图

Android系统.png

我们平时接触的Android应用开发及开源代码都位于最上层(Application层),对Android FrameWork层接触不多,但Android系统很多的精妙设计都处于FrameWork层及以下,要想理解Android系统则必须学习FrameWork层。本系列我将和大家一起开始FrameWork层的学习,我们将依次学习Android启动、Android跨进程Binder机制,Android四大组件启动过程。在学习过程中不仅会接触大量的Java层源码,由于Android系统底层是linux,因此学习过程中还会涉及一些linux知识及C++代码,为了不让大家陷入代码、纠于细节,本系列主要会从架构层面解释具体原理,对应节点会列出对应源码位置,有兴趣的同学可以去进一步阅读源码。要想学好Android,只有那句程序猿至理名言RTFSC(Read The Fucking Source Code)。
关于Android源码阅读,推荐一个非常好的在线阅读源码阅读网址:Android源码

Android系统启动流程

本文主要介绍Android系统的启动过程,主要目的一是让大家大致了解Android手机启动后都在做什么,二是介绍几个核心的系统服务及进程,为后续文章做一个铺垫。本文以Android 9.0.0_r8系统源码为例,Android系统启动大致可以分为四步:

Android系统启动.png

下面我们依次来分析每一步都在做什么

系统环境准备

该步骤主要是用户按下开机键后的一些硬件初始化、系统加载过程,简单介绍不作过多说明

BootLoader

Bootloader是嵌入式系统在加电后执行的第一段代码,进行硬件初始化,获取内存大小信息等,调整手机到适配状态。在它完成CPU和相关硬件的初始化之后,再将操作系统映像或固化的嵌入式应用程序加载到内存中然后跳转到操作系统所在的空间,最终目标是拉起操作系统。当用户按下开机键后,芯片就会开始将BootLoader加载到内存中。

系统加载

BootLoader加载成功后,手机会通过BootLoader加载系统,启动系统内核(Kernel)并做相应的环境初始化设置,开始init进程启动

init进程

init进程简介

init启动流程分析

init是处于linux系统的用户空间,在第一步系统环境准备后,linux内核启动成功便会调用/system/core/init/Init.cpp 中的main()开始init进程的启动。init.cpp中main()函数较长,做相应截取说明

int main(int argc, char** argv) {
     ...
    // 1、创建、挂载相应文件
    // Get the basic filesystem setup we need put together in the initramdisk
    // on / and then we'll let the rc file figure out the rest.
    mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755");
    mkdir("/dev/pts", 0755);
     ...
    // 2.初始化log服务、属性服务
    InitKernelLogging(argv);
    ....
    property_init();
    ...
    // 3、解析init.rc
    LoadBootScripts(am, sm);
    ...
    // 相关逻辑执行完后,会进入一个while true循环等待任务执行
}

代码很长,我们关心的主要包含3步

第一步 创建、挂载相应文件

第二步 初始化log服务、属性服务

第三步 解析init.rc配置文件

    # Now we can start zygote for devices with file based encryption
    trigger zygote-start

Zygote进程

Zygote进程简介

Zygote是受精卵的意思,它是Android中的一个非常重要的守护进程服务(Daem Service),所有的其他Dalvik虚拟机(进程)都是通过zygote孵化(fork)出来的。Android应用程序是由Java语言编写的,运行在各自独立的Dalvik虚拟机(进程)中。如果每个应用程序在启动之时都需要单独运行和初始化一个虚拟机(进程),会大大降低系统性能,因此Android首先创建一个zygote虚拟机(进程),然后通过它孵化出其他的虚拟机(进程),进而共享虚拟机内存和框架层资源,这样大幅度提高应用程序的启动和运行速度。
Zygote是Android中最重要的一个进程,和Init进程,SystemServer进程是支撑Android世界的三极。Android8.0后对zygote.rc文件进行了拆分,存在以下四种:

我们以init.zygote32.rc为例来简单分析下

service zygote /system/bin/app_process -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

代码不多,共15行,也是Android Init Language语法,执行逻辑就是启动进程,名称为zygote,执行程序为/system/bin/app_process,类名为main,当Zygote进程重启时,重启audioserver、cameraserver、media等进程。下面我们通过frameworks/base/cmds/app_process/app_main.cpp具体分析Zygote进程初始化流程。

Zygote启动流程分析

Zygote进程初始化过程会进入Java层,因此我们分为C++层跟Java层分别分析。

C++层

同样,我们看下app_main.cpp中的main方法,代码较长,我们截取分析。

int main(int argc, char* const argv[])
{
    ...
   // 1、创建AppRuntime变量
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));     // 1
    // Process command line arguments
    // ignore argv[0]
    argc--;
    argv++;

    ...
    // 2、创建Zygote进程
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) {
            // Zygote进程自己
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {     
            // SystemServer进程
            startSystemServer = true; 
        } else if (strcmp(arg, "--application") == 0) {
           // 普通应用进程
            application = true;
        } 
        
        ...
    }

    ...

    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);      
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else {
        fprintf(stderr, "Error: no class name or --zygote supplied.\n");
        app_usage();
        LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
    }
}
第一步 创建AppRuntime变量
第二步 创建Zygote进程,进入Java层

Java层

我们截取看下ZygoteInit中的main方法

         // 1、创建Socket
          ...
          String socketName = "zygote";
          ...
          zygoteServer.registerServerSocketFromEnv(socketName);
          ...
         // 2、预加载类、资源
         preload(bootTimingsTraceLog);
         ...
         // 3、fork SystemServer进程
         if (startSystemServer) {
             Runnable r = forkSystemServer(abiList, socketName, zygoteServer); 
             ...
             if (r != null) {
                 r.run();
                 return;
              }
         }
          ...
            
         // 4、等待AMS消息
         // The select loop returns early in the child process after a fork and
         // loops forever in the zygote.
          caller = zygoteServer.runSelectLoop(abiList); 

第一步 创建Socket
第二步 预加载类、资源
第三步 fork SystemServer进程
第四步

SystemServer进程

SystemServer进程简介

SystemServer启动流程分析

上文谈到forkSystemServer()方法,该方法进行一系列调用后,最终启动SystemServer进程会进入com.android.server.SystemServer.java,该类的main方法直接调用SystemServer的run()方法,我们直接看run方法。

private void run() {
     ...
     // 创建主线程
     Looper.prepareMainLooper();
     ...
     // 1、加载动态库
     System.loadLibrary("android_servers");
     ...
     // 创建system Context
     createSystemContext();
     ...
     // 2、创建ServiceManager
     mSystemServiceManager = new SystemServiceManager(mSystemContext);
     ...
     // 3、启动引导服务、启动核心服务、启动其他服务
     startBootstrapServices();    
     startCoreServices();         
     startOtherServices();
     ...
}

第一步 加载动态库

第二步 创建ServiceManager

第三步 启动引导服务、启动核心服务、启动其他服务

总结

至此,Android系统启动核心部分已经分析结束。我们分析了Android系统启动后硬件环境准备,init进程如何启动Zygote进程,Zygote进程如何孵化SystemServer进程。本文分析主要是流程分析,源码分析只是指出关键方法,很多代码细节一笔带过,有兴趣的同学可以自己去源码内研究。

上一篇 下一篇

猜你喜欢

热点阅读