Android面试题之说说系统的启动流程(总结)

2024-06-13 21:08:52 浏览数 (1)

启动流程

Boot Rom -> Boot Loader -> Kernel -> 启动Init进程 -> Zygote进程 -> system_server进程 -> 启动AMS、WMS、PMS等服务 -> AMS启动Launcher应用的home activity

init进程(用户级别的第一个进程)

  • 创建和挂载启动所需要的文件目录
  • 初始化和启动属性服务
  • 解析init.c配置文件并启动zygote进程

使用fork函数复制进程

  • 子进程是父进程的一个复制品。它从父进程处继承了整个进程的地址空间;包括进程上下文(进程执行活动全过程的静态描述)、进程堆栈、打开的文件描述符、信号控制设定、进程优先级、进程组号等。子进程所独有的只有它的进程号,计时器等(只有少量信息)。因此fork函数的代价是很大的
子进程和父进程的区别
  • 除了文件锁以外,其他的锁都会被继承
  • 各自的进程ID和父进程ID不同
  • 子进程的未决告警被清除
  • 子进程的未决信号集设置为空集
多线程进程的fork调用
  • 仅当前线程到子进程
  • 如果当前线程有锁,锁也会被复制到子进程。子进程中没有其他方式可以解开,程序发生死锁。
  • 孤儿进程:fork后,父进程和子进程交替运行,顺序不定。如果父进程先退出,子进程还没退出,子进程的父进程就变成了Init进程(任何一个进程都必须有父进程)
  • 僵尸进程:如果子进程先退出,父进程还没退出,那么子进程必须等到父进程捕获到了子进程的退出状态才真正结束,否则这个时候子进程就称为僵尸进程(只保留一些退出信息供父进程查询)

zygote进程

app_main.cpp main()

-> AndroidRunTime.start()

-> startVm()启动虚拟机

-> startReg()注册一些信息

-> 创建socket服务用于进程通信(Binder进程还没启动)

-> startSystemServer(),SystemServer会启动其他的一系列服务

AndroidRunTime

为Android应用运行所需的运行时环境,包括:

  • Dalvik VM 虚拟机,解释运行Dex格式的Java程序,每个进程运行一个虚拟机(就是一些C代码,不停的去解释Dex格式的二进制码,把它们转换成机器码,然后执行,现在大部分虚拟机都支持JIT,也就是bytecode可能在运行前就已经被转换成机器码)
  • Android的Java类库
  • JNI:C和Java互相调用的接口
  • LibC

startVm

Runtime

zygote的app_main.cpp main()函数主要做的就是参数解析,这个函数有2种启动模式:一种是zygote模式,启动zygote进程;一种是application模式,启动普通应用程序。

AndroidRunTime的startVm方法会创建Runtime对象,负责ART虚拟机运行时环境

Runtime的Init方法会开辟堆内存,后面还会用Thread开启线程,命名为“main”,也就是主线程

  • 通过Heap创建堆内存管理对象
  • 通过JavaVMExt创建Java虚拟机对象
  • Thread::Attach连接主线程
  • new ClassLinker创建类连接器,并初始化

zygote的main函数

  • 新建ZygoteServer服务器端,注册socket
  • Preload函数预加载资源,包括指定的类,Android的资源,比如drawablecolor,openGL,加载共用的Library,text资源字体等。系统启动过程中,这一块耗时比较长。
  • 然后主动开启一次GC
  • 然后通过forkSystemServer方法fork出SystemServer进程
  • zygoteServer.runSelectLoop会监听客户端创建进程的请求,收到请求就Fork进程
为什么不从init进程Fork Android的进程,而是从Zygote进程fork?

这是因为zygote进程已经通过Preload函数预加载了很多资源,fork以后新进程就有了,从init的话就得重新加载一遍,非常耗时

那为什么不从SystemServer进程fork新的APP进程呢?

因为SystemServer进程里开启了一系列的AMS、PMS等80多个服务,APP进程是不需要的

forkSystemServer
  • 最终会调用到Linux的fork函数,fork出的是zygote进程
  • fork成功后,会关闭closeServerSocket服务,因为SystemServer进程不需要socket
  • 接着会逐步调用到SystemServer的main函数
SystemServer的main函数
  • 创建系统上下文,SystemContext;会通过ActivityThread来创建Instrumentation;通过ContextImpl创建SystemContext对象,然后创建LoadAPK对象–>创建Application和ClassLoader
  • 启动AMS、PMS、WMS等80多个Android服务
  • 服务都启动完成以后,会调用Looper.loop()
  • 最后启动Launcher程序

以上是系统启动流程的总结,面试的时候经常会问,建议收藏起来以备不时之需。

有问题也欢迎留言讨论。

END

点亮【赞和在看】,让钱和爱都流向你。

心里种花,人生才不会荒芜,如果你也想一起成长,请点个关注吧。

作者介绍

中年程序猿,十年移动端开发老司机,分享一线开发经验和知识,正在探索通过副业渡过中年危机

越努力越幸运,加油

0 人点赞