Framework -- 系统架构

一、前言

framework的学习,需要掌握到什么程度?

  • App 的启动流程:整体的过程,具体到某些类在整个流程中所起的作用;
  • 组件的设计模式,核心设计思想;
  • 需要知晓目前已知的问题,以及解决方案。

二、Android系统架构

1.首先先看下Google官方提供的经典分层架构图
Framework -- 系统架构_第1张图片

  • Linux内核层
  • HAL层(硬件抽象层)
  • 系统运行库层(系统Native库和Android运行时环境)
  • Framwork层(Java框架层)
  • Application层(包括Systema Apps和三方App)

2.从进程上划分

Loader 开机引导程序

由BootLoader引导开机

当手机处于关机状态时,长按电源进行开机。
原因:主板通电之后,开启引导烧录在存储器里的预设代码,然后加载引导程序到内存中,这个主要做一些内存检测以及硬件参数的初始化过程

linux kernel 硬件抽象层

开机引导程序执行完成之后,开始加载linux kernel 核心代码

        这层主要是加载一些硬件驱动,如相机驱动,视频驱动,显示屏驱动,输入驱动

        上层应用想要调用这些硬件驱动的话,为了解决各大应用商提供的驱动不统一的问题,由硬件抽象层来适配,提供统一的api,

C++ FrameWork

        硬件驱动加载完成之后会加载linux 中第一个用户进程 init 进程,还会孵化出adbd deme进程,以及log deme进程。
        这就是为什么在运行时可以断点调试和输出日志的原因,就是因为这两个守护进程的存在

Android Framework

在ZygoteInit main方法里面还启动了SystemServer 系统服务进程

3.关键进程

init进程

是Linux系统中用户空间的第一个进程,进程号为1(pid=1),由于Android是基于Linux内核的,所以init也是Android系统中用户空间的第一个进程。

init进程的作用

  • 孵化出ueventd、logd、healthd、installd、adbd、lmkd等用户守护进程(守护进程一般以d结尾)
  • 提供property service(属性服务)来管理Android系统的属性。
  • 启动servicemanager(binder服务管家)、bootanim(开机动画)等重要服务
  • 孵化出Zygote进程,Zygote进程是Android系统的第一个Java进程(即虚拟机进程),Zygote是所有Java进程的父进程,Zygote进程本身是由init进程孵化而来的。

Zygote进程

      Init进程启动后,最重要的一个进程就是Zygote进程,Zygote是所有应用的鼻祖。SystemServer和其他所有Dalivik虚拟机进程都是由Zygote fork而来。

        Zygote进程由app_process启动,Zygote是一个C/S模型,Zygote进程作为服务端,其他进程作为客户端向它发出“孵化-fork”请求,而Zygote接收到这个请求后就“孵化-fork”出一个新的进程。

        是一个承上启下,连接Java世界和Linux 世界,zygote 进程创建完成之后就进入Java世界了,会调用ZygoteInit java 类,在这个类的入口方法,会创建Android Framework 系统服务,System Server 进程,所有app的进程都是由Zygote 进程孵化而来的
app进程创建完成之后,都会由ZygoteInit 反射调用app进程的入口类,也就是ActivityThread这个类,从而使app得以启动

1. 我们知道Java调用C++可以通过JNI。那么C++是如何转到Java的,也就是说ZygoteInit.java这个类是如何被调用的?
        在java中,class文件是由ClassLoader来加载的,但实际上,ClassLoader在加载java文件的过程中,也是通过C++来完成的(Bootstrp loader就是用C++写的,具体可以去看java类加载过程及机制,Java类加载器ClassLoader总结),所以C++如果想要访问java文件的话,是非常轻松的

2. 进程间通信通常使用的是binder,为什么SystemServer和Zygote之间通信要采用Socket

        UNIX上C++程序设计守则3:多线程程序里不准使用fork

        Binder通讯是需要多线程操作的,代理对象对Binder的调用是在Binder线程,需要再通过Handler调用主线程来操作。

        害怕父进程binder线程有锁,然后子进程的主线程一直在等其子线程(从父进程拷贝过来的子进程)的资源,但是其实父进程的子进程并没有被拷贝过来,造成死锁。

3.为什么一个java应用一个虚拟机?

        android为每个程序提供一个vm,可以使每个app都运行在独立的运行环境,使稳定性提高。每个程序一个虚拟机,各个程序之间也不可以随意访问内存,所以此类木马病毒几乎没有。

4.什么是Zygote资源预加载?

        预加载是指在zygote进程启动的时候就加载,这样系统只在zygote执行一次加载操作,所有APP用到该资源不需要再重新加载,减少资源加载时间,加快了应用启动速度,一般情况下,系统中App共享的资源会被列为预加载资源。
        zygote fork子进程时,根据fork的copy-on-write机制可知,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。

5. Zygote为什么要预加载

       应用程序都从Zygote孵化出来,应用程序都会继承Zygote的所有内容。
       如果在Zygote启动的时候加载这些类和资源,这些孵化的应用程序就继承Zygote的类和资源,这样启动引用程序的时候就不需要加载类和资源了,启动的速度就会快很多。
      开机的次数不多,但是启动应用程序的次数非常多。

6.Zygote预加载的原理是什么?

        zygote进程启动后将资源读取出来,保存到Resources一个全局静态变量中,下次读取系统资源的时候优先从静态变量中查找。

//1从classpath路径下搜索ZygoteInit这个类,并返回该类的Class对象,进程创建创建完成后会固定加载这个类
jClass clazz = (*env)->Findclass(env, "com/ android/internal/os/zygoteInit"):
//2获取类的默认构造方法ID
jmethodID mid_construct = (*env) ->GetMethodID (env, clazz,
"" "(v");
//3创建该类的实例
jobject jobj = (*env)->NewObject(env, clazz,mid_construct);
//4查找实例方法的ID
jmethodID mid_instance = (wenv)->GetMethodID(env, clazz, "main", "(Ljava/lang/String; I
1/5调用对象的实例方法
A
jstring str_arg = (*env)->NewstringUTF(env,”我是实例方法");
(wenv) ->CallVoidMethod (env, jobj,mid_instance, str_arg, 200) ;

Zygoteinit main 方法里做了四件事情

  1. 资源的预加载,加载系统的class文件,资源文件动态库。上层应用会使用大量的系统资源,如果在app启动的时候再去加载的话,会造成app启动缓慢,预加载可以提高app启动速度,也能共享这些资源文件
  2. 通过main方法传入的args 数组,判断是否有包含start-system-server 这个参数,来来决定是否启动systemserver 进程,该进程是Android framework 的核心进程
  3. 创建一个socket 服务,用来接受AMS 进程创建请求的
  4. socket 服务创建完成之后,进入阻塞状态,等待客户端的连接
ZygoteInit-java
public static void main(String argv []){
    //1.预加载frameworks/base/preloaded-classes和framework_res.apk资源
    preloadClasses();
    preloadResources();
    preloadSharedLibraries();

    //2.启动system_server进程。该进程是framework的核心。
    if (argv [1].equals("start-system-server")) {
        startSystemServer();
    }
    //3.创建Socket服务
    registerZygoteSocket();

    //4.进入阻塞状态,等待连接,用以处理来自AMS申请进程创建的请求
    runSelectLoopMode();
    }
}

SystemService进程

        在zygoteInit main 方法中启动了SystemService系统服务进程,这个进程创建成功之后

通过反射的方法启动SystemServer.java的main()方法

        在他的main 方法里面会启动非常多的系统服务,比如 ActivityManagerService、PowerManagerService、DisplayManagerService、PackageManagerService、WindowManagerService、LauncherAppsService等多个核心系统服务

Framework -- 系统架构_第2张图片

这些系统服务大致可分为三类

  1. 引导服务
  2. 核心服务
  3. 其他一般服务

这些系统服务构成了Android的framework层,为app日常开发和运行提供了保障

当这些服务启动完成之后;其中的ActivityManagerService最终会调用systemReady()方法。是时候去通知ActivityManager去启动第三方应用了

4.Android系统启动流程总结:

  1. 手机开机后,引导芯片启动,开启引导烧录在存储器里的预设代码,然后加载引导程序到内存中,BootLoader检查RAM,初始化硬件参数等功能
  2. 硬件参数初始化完成后,进入到Kernel层,Kernel层主要加载一些硬件设备驱动(如相机驱动,视频驱动,显示屏驱动,输入驱动),初始化进程管理等操作。在Kernel中首先启动swapper进程(pid=0),用于初始化进程管理、内管管理、加载Driver等操作,再启动kthread进程(pid=2),这些linux系统的内核进程,kthread是所有内核进程的鼻祖;
  3. Kernel层加载完毕后,硬件设备驱动与HAL层进行交互。初始化进程管理等操作会启动init进程 ,这些在Native层中;
  4. init进程(pid=1,init进程是所有进程的鼻祖,第一个启动)启动后,会启动adbd,logd等用户守护进程,并且会启动servicemanager(binder服务管家)等重要服务,同时孵化出zygote进程,这里属于C++ Framework,代码为C++程序;
  5. zygote进程是由init进程解析init.rc文件后fork生成,它会加载虚拟机,启动System Server(zygote孵化的第一个进程);SystemServer负责启动和管理整个Java Framework,包含ActivityManager,WindowManager,PackageManager,PowerManager等服务;
  6. zygote同时会启动相关的APP进程,它启动的第一个APP进程为Launcher,然后启动Email,SMS等进程,所有的APP进程都有zygote fork生成。

三、Launcher应用的启动流程

进程的入口类一般有两种:

  • native 进程的入口类一般是init 
  • Java进程的入口类一般都是main 方法

总结:Zygote 进程创建成功之后,会进入到Java世界,第一个创建的是ZygoteInit 这个Java类,在它的入口方法里主要做了系统资源的预加载,以提高App 启动的响应速度,同时也是为了App 运行时能够共享系统的资源,其次它还会启动系统服务进程SystemService,这个进程的入口类是SystemService.java,而这个类里面一个启动了一百多个服务,共同为App 运行提供保障服务,当所有的服务启动完成之后,会通知ActivityManagerService去启动launcher应用

1.相关类介绍

ActivityManagerService 

        负责管理四大组件和进程,包括生命周期和状态切换。它的systemReady()方法,是Launcher应用启动的入口。

ActivityTaskManagerService 

        把原先在ActivityManagerService 对Activity生命周期管理和调度等工作全部转移到此,由它来管理Activity 的工作(Android10新增)。

RootActivityContainer 

        调用PackageManagerService去查询手机系统中已安装的所有的应用,哪一个是符合launcher标准,且得到一个Intent 对象,并交给ActivityStarter。

ActivityStater 

        得到这个Intent 对象之后交由ActivityStarter启动器进一步的启动,在它里面会做启动之前的各项检查,比如检查Activity 有没有在清单文件中注册,class文件是否存在,这个activity 是否有权限启动等。

ActivityRecord 

        在Activity 启动的时候就会涉及到进栈和出栈的操作,在Service端是无法拿到Activity 实例的,而ActivityRecrd 是在Service端对Activity 的一种映射,它里面记录和存储了Activity 所有的信息。

        代表一个Activity。

TaskRecord 

        任务栈,记录一个或多个ActivityRecord 的实例。

        Activity栈,内部维护一个ArrayList

ActivityStack 

        任务栈的管理者,应用在运行的时候会有一个或多个任务栈,这些任务栈会交给ActivityStack 来管理。

        负责管理各个Activity栈,内部维护一个ArrayList

ActivityStackSupervisor 

        由于手机在运行中会启动一个或多个应用,这个时候会产生一个或多个ActivityStack 对象,用来管理Launcher和非Launcher应用的ActivityStack实例。

        内部持有一个ActivityStack,而ActivityStack内部也持有ActivityStackSupervisor,相当于ActivityStack的辅助管理类

ProcessList 

        职责是把原先在ActivityManagerService钟启动进程的工作转移到此(Android10新增)。

ZygoteProcess 

        建立起与Zygote 进程的socket 链接,并且把创建进程所需要的参数给发送过去,

Instrumentation

        负责调用Activity和Application生命周期。

2.Activity任务栈之间的关系 (包含多个)

        ActivityStackSupervisor -> ActivityStack -> TaskRecord -> ActivityRecord

3.Launcher启动流程分析

BootRom -> BootLoader -> Linux Kernel -> Init -> Zygote -> SystemServer -> Launcher

1. ActivityManagerService.java 调用 systemReady() 系统服务启动完毕后,launcher应用的入口

//启动HomeActivity(即Launcher应用的入口Activity):本意是在所有的屏幕上启动桌面应用
//因为Android10.0开始是支持多屏幕的,比如手机屏幕,虚拟投屏,外接屏幕
mAtmInternal.startHomeOnAllDisplays(currentUserId, "systemReady");

2. 这里的mAtmInternal是ActivityTaskManagerInternal,是一个抽象类。真正的实现类在ActivityTaskManagerService的内部类LocalService中,进而调用startHomeOnAllDisplays(),在这里会做一层转发,进而委托给RootActivityContainer

3. 在RootActivityContainer的startHomeOnAllDisplays()中调用PackageManagerService中去查询手机系统中已安装的所有的应用,哪一个符合launcher标准,且得到一个Intent对象,并交给ActivityStarter

4. ActivityStarter中调用startActivityUnchecked() 进行清单文件校验,启动权限检查,根据启动模式和Intent.flag计算出该Activity所属的任务栈并加入,但此时并不会显示

5. ActivityTask中调用resumeTopActivityInnerLocked(),启动新的Activity之前会把当前可见的Activity暂停,计算待启动的Activity所属进程是否存在

6. 在ActivityStackSuperVisor.java类的startSpecificActivityLocked()去判断进程是否存在,如果存在,调用realStartActivityLocked去启动Activity,否则调用ActivityManagerIntenal::startProcess去创建进程

7. ActivityManagerService$LocalService.javastartProcess(),委派给ProcessList来负责进程的创建

8. ProcessList中调用startProcessLocked() 

9. ProcessList中调用startProcess() 中 调用annovaote.getProcess().start()

10. ZygoteProcessor.java 中的attemptZygoteSendArgsAndGetResult()

11. ActivityThread.java 进入应用的进程

你可能感兴趣的:(Android:系统架构篇,系统架构)