【Android FrameWork】①系统服务及应用进程相关

1,506 阅读9分钟

复习内容均来自于某网站安卓付费视频培训课程

系统服务

1. Zygote作用、启动流程、工作原理

  • 1.1 作用:
    • 启动SystemServer
    • 孵化应用进程
  • 1.2 启动流程
    • init进程(Linux启动后用户空间的第一个进程),首先加载启动配置文件init.rc,配置文件中包含了要启动的系统服务
    • zygote就是要启动的服务之一,其他的如ServiceManager也是这样启动的
    • 启动进程的两种方式
      • fork+handle
      • fork+execve
  • 1.3 Zygote启动之后做了什么
    • Zygote的Native世界(C++)
      • 启动Android虚拟机:JNI_CreateJavaVM
      • 注册Android的JNI函数
      • 进入java世界
    • Zygote的Java世界
      • 预加载资源 Preload Resources
      • 启动System Server, fork出System Server的进程
      • 进入loop循环,等待socket消息
  • 1.4 注意事项
    • zygote fork要单线程
    • zygote的IPC(跨进程通信机制)没有采用binder
  • 问题
    • 孵化应用进程这种事为什么不交给SystemServer来做,而专门设计一个Zygote?

    • Zygote的IPC通信机制为什么不采用binder?如果采用binder的话会有什么问题么?

2. Android系统的启动

  • init.rc系统进程,如图
  • 2.1 Zygote启动回顾
    • init进程fork出zygote进程
    • 启动虚拟机,注册jni函数,为进入java的世界做准备
    • 预加载系统资源
    • 启动SystemServer,SystemServer跑了很多系统服务
    • 进入Socket Loop,不断接收及处理Socket消息
  • 2.2 SystemServer如何启动
    • zygote fork创建出SystemServer进程
    • 如图7
  • 2.3 系统服务是怎么启动的
    • 系统服务怎么发布,让应用程序可见?
      • 把系统服务binder注册到ServiceManager中
    • 系统服务跑在什么线程?
      • DisplayThread 负责显示
      • FgThread 前台任务
      • loThread IO任务
      • UiThread 值得一提的是,这个是子线程
      • binder线程
    • 问题:
      • 为什么系统服务不都跑在binder线程里呢?
      • 为什么系统服务不都跑在自己私有的工作线程里呢?
      • 跑在binder线程和跑在工作线程,如何取舍?
  • 2.4 怎么解决系统服务启动的相互依赖
    • 分批启动
      • 先启动基础服务,AMS PMS PKMS
      • 后启动上层的一些服务
    • 分阶段启动
  • 2.5 桌面的启动
    • AMS就绪之后,会调用SystemReady函数,而其内部又调用了STARThomeActivity函数
    • PMS查询已安装的应用,并显示在桌面上
    • 点击应用之后就会启动应用的LauncherActivity
    • 如图8

答题要点

说说Android系统的启动流程

  • 简答:首先启动zygote,再启动SystemServer,然后启动桌面
  • 答题技巧:
    • 回答出zygote如何启动:init->zygote->native世界->java世界
    • 回答出SystemServer是怎么启动的
    • 回答出系统服务是怎么启动的

3. 怎么添加一个系统服务

  • 关键词
    • 方便
    • 开放
    • IPC 跨进程通信
  • 如何使用系统服务
    • 根据服务名称获取服务
    • 原理如图10
  • 系统服务如何注册
    • addService传入服务名和Binder对象
    • 图11
  • 什么时候注册的系统服务
    • SystemServer启动时注册的
    • 图12
  • 独立进程的系统服务
    • 以surfaceflinger为例,这是一个native实现的系统服务
    • 不管是独立进程的服务还是SystemServer的服务,都需要向SeviceManager注册
    • 图13
  • 启动binder机制
    • 打开binder驱动
    • 映射内存,分配缓冲区
    • 启动binder线程,进入binder loop

答题要点

  • 答题关键点
    • 为什么要添加系统服务:给别人用的
    • 如何让别人使用:弃用binder机制ipc通信,注册开放出去,让其他调用者可以使用
    • 具体有那些事要干
  • 添加系统服务时机:SystemServer启动时注册
  • 服务端要做的事
    • 启用binder机制
    • 服务初始化工作
    • binder注册到ServiceManager
  • 应用端要做哪些事
    • 系统服务调用方式Context.getSystemSevice
    • 如果自己添加服务,也要与系统服务调用保持一致,需要为服务注册serviceFeature

4. 系统服务和bind的应用服务有什么区别

启动方式上的区别

  • 系统服务大多数运行在SystemServer中,如AMS WMS PMS
    • 图14
  • 应用服务:最终会调到AMS中,AMS负责Service的管理和调度,servcie启动和加载由应用端负责
    • 图15

注册方式上的区别

  • 系统服务:binder实体对象注册到ServiceManager中,只有系统服务才能注册到ServiceManager中
  • 应用服务:与系统服务不同,应用服务需要应用bindService,而且需要AMS去请求它
    • 图16

使用方式上的区别

  • 系统服务:
    • 图17
  • 应用服务
    • 图18

5. ServiceManager的启动和工作原理

ServiceManager的启动流程是怎样的?

  • 启动进程
  • 启用binder机制:打开binder驱动,映射内存
  • 发布自己的服务:
  • 等待并响应请求:loop循环,读请求处理请求

怎么获取ServiceManager的binder对象?

  • 根据0号handle值,创建一个BpBinder

怎么向ServiceManager添加服务?

怎么从ServiceManager获取服务?

  • 先获取ServiceManager的binder对象
  • 然后发起getService调用

应用进程相关

1. 应用进程是怎么启动的

考察点:

  • 了解Linux下进程启动的方式
  • 熟悉应用进程启动的基本流程
  • 深入理解应用进程启动的原理

什么时候触发的进程启动?

  • 查找组件所在进程
  • 如果没有启动,就调用AMS的startProcessLocked来发起启动

应用的启动

  • AMS向zygote发起启动应用进程的请求之后,会返回进程pid给AMS
  • 应用进程启动好之后亲自告诉AMS自己启动好了
  • ActivityThread并不是一个线程,它只是一个类
  • 图20

题解

  • 应用进程是什么时候启动的
    • 启动应用组件,如Activity、Service会先判断应用所在进程是否启动,如果没有启动,就会先启动进程
  • 进程启动由谁发起
    • 由AMS向zygote发起请求,通过socket进行通信
  • zygote fork出应用进程,执行ActivityThread的入口main函数,入口函数的java类名是AMS通过socket发给zygote的
  • 进程启动之后向AMS报告,注册Application Thread整个启动才算结束,只有向AMS报告,进程才是可用的
  • 图22

2. 应用是怎么启用binder机制的

考察点

  • 了解binder是用来干什么的?
    • -> 跨进程通信
  • 应用里面哪些地方用到了binder机制?
    • -> 系统服务,发广播,启动Activity,凡涉及到应用组件的基本都涉及到binder机制
  • 应用的大致启动流程是怎样的?
    • -> 由AMS向zygote发起请求 -> zygote fork出应用进程 -> 进程启动之后向AMS报告,注册Application Thread -> 进程可用
  • 一个进程是怎么启用binder机制的?
    • 如下题解

题解

  • 首先回答binder启动时机:应用进程启动好之后就支持binder了
  • 然后回答如下4点
    • 打开binder驱动
    • 映射内存,分配缓冲区
    • 注册binder线程
    • 进入binder loop

3. 谈谈对Application的理解

考察点

  • 了解Application的作用(初级)
  • 熟悉Application的类继承关系以及生命周期(中级)
  • 深入理解Application的初始化原理(高级)

作用

  • 保存应用进程内的全局变量
  • 由于Application比其他四大组件要早,所以可以进行一些初始化操作,SDK init等,
  • 提供应用上下文
  • 注意:Application与进程相关,有几个进程,就有几个Application

继承关系: Application - ContextWrapper

生命周期

  • 启动
    • 构造函数 new Application()
    • attchBaseContext
    • onCreate
  • 结束
    • onTerminate(),只在模拟器中有用,不在本题讨论范围

Application怎么初始化

  • ActivityThread.attch()->
  • 图24
  • 总结:
    • 如上图,先调用ActivityThread.attch()函数,最终是通过反射创建了Application实例
    • 然后会准备上下文 application.attchBaseContext()
    • 最后调用了application Oncreate函数
    • 整体流程如图25
  • 注意:
    • 不要在Application的生命周期中执行耗时操作,因为这可能会阻塞应用的UI线程(code过程要小心了,Application onCreate中耗时的操作如sdk耗时的初始化操作要避免)
    • Application中静态变量的bug
        • 在Application中声明变量static String name
        • MainActivity中初始化name的值
        • TestActivity中获取name的值
      • 问题:假设应用进程被杀死,切回应用的时候,系统会重建应用并恢复TestActivity,此时name并没有被初始化,所以name为null,这回引发一些异常

4. 谈谈对Context的理解

讲的不错的一篇文章:juejin.cn/post/686434…

考察点

  • 了解Context的作用
    • 是应用组件的上下文
    • 访问特定资源类
    • 应用层调用: 启动Activity,发送广播,接收intents
    • 图26
  • 深入理解不同应用组件之间Context的区别,类继承关系
  • 熟悉Context初始化流程

应用里面有多少个Context?不同的Context之间有什么区别?

Application中Context的个数(多进程下有多个Application的context)+ Activity的Context个数+Service的Context个数,区别是直接Activity由于有UI所以是继承于ContextThemeWrapper,间接继承了ContextWrapper,而Service和Application则是直接继承了ContextWrapper

  • Application:与应用进程启动相关(上题有讲到)
    • 继承关系: Application ← ContextWrapper ← Context
    • 调用顺序, →attachBaseContext → onCreate
    • ContextWrapper里包含一个Context,调用都委托给他了
  • Activity:
    • 图27
    • 继承关系: Activity ← ContextThemeWrapper ← ContextWrapper ← Context
    • 调用顺序, → attachBaseContext → onCreate
  • Service:
    • 图28
    • 继承关系: Application ← ContextWrapper ← Context
  • 广播没有Context
    • 广播是一个抽象类,没有直接或间接继承于Context
    • onReceive中的Context,如果是动态注册的,那么context就是注册广播用的context;如果是静态注册,则是一个以application为mBase的ContextWrapper(后续会讲到)
  • ContentProvider没有Context,
    • Context成员变量是由ContentProvider初始化的时候传进来的,传的是Application的Context,ContentProvider的初始化即onCreate是在Applicaiton onCreate之前调用的
    • 图29

Activity里的this和getBaseContext有什么区别?

  • this返回Activity指向自己
  • getBaseContext返回ContextWrapper中的mBase

getApplication和getApplicationContext有什么区别?

  • 都是返回Applicaiton对象
  • getApplicationContext是Context中的一个抽象函数,getApplication是Activity和Service特有的,在其他地方如广播中是不能使用的

应用组件的构造,onCreate、attachBaseContext调用顺序?

  • 先调用组件的构造函数,再调用attachBaseContext赋予上下文,再调用onCreate