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

简介: 这篇文章概述了Android系统的启动流程,从Boot Rom到Zygote进程和SystemServer的启动。init进程作为用户级别的第一个进程,负责创建文件目录、初始化服务并启动Zygote。Zygote通过预加载资源和创建Socket服务,使用fork函数生成SystemServer进程。fork过程中,子进程继承父进程大部分信息但具有独立的进程ID。Zygote预加载资源以减少后续进程的启动时间,而SystemServer启动众多服务并最终开启Launcher应用。文中还讨论了为何从Zygote而非init或SystemServer fork新进程的原因。

本文首发于公众号“AntDream”,欢迎微信搜索“AntDream”或扫描文章底部二维码关注,和我一起每天进步一点点

启动流程

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的资源,比如drawable\color,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程序

欢迎关注我的公众号AntDream查看更多精彩文章!

目录
相关文章
|
5天前
|
搜索推荐 Android开发 iOS开发
探索安卓与iOS系统的用户界面设计哲学
现代移动操作系统的设计哲学不仅仅是技术的表现,更是用户体验与功能实现的结合。本文将深入分析安卓与iOS两大主流系统在用户界面设计方面的差异与共通之处,探讨它们背后的思维模式及其对用户体验的影响。 【7月更文挑战第11天】
|
1天前
|
安全 Android开发 Kotlin
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
**Kotlin中的`by lazy`和`lateinit`都是延迟初始化技术。`by lazy`用于只读属性,线程安全,首次访问时初始化;`lateinit`用于可变属性,需手动初始化,非线程安全。`by lazy`支持线程安全模式选择,而`lateinit`适用于构造函数后初始化。选择依赖于属性特性和使用场景。**
12 5
Android经典面试题之Kotlin延迟初始化的by lazy和lateinit有什么区别?
|
2天前
|
Android开发 Kotlin
kotlin开发安卓app,如何让布局自适应系统传统导航和全面屏导航
使用`navigationBarsPadding()`修饰符实现界面自适应,自动处理底部导航栏的内边距,再加上`.padding(bottom = 10.dp)`设定内容与屏幕底部的距离,以完成全面的布局适配。示例代码采用Kotlin。
32 15
|
4天前
|
Android开发 Kotlin
Android面试题之kotlin中怎么限制一个函数参数的取值范围和取值类型等
在Kotlin中,限制函数参数可通过类型系统、泛型、条件检查、数据类、密封类和注解实现。例如,使用枚举限制参数为特定值,泛型约束确保参数为Number子类,条件检查如`require`确保参数在特定范围内,数据类封装可添加验证,密封类限制为一组预定义值,注解结合第三方库如Bean Validation进行校验。
17 6
|
4天前
|
Android开发
Android面试题之自定义View注意事项
在Android开发中,自定义View主要分为四类:直接继承View重写onDraw,继承ViewGroup创建布局,扩展特定View如TextView,以及继承特定ViewGroup。实现时需注意:支持wrap_content通过onMeasure处理,支持padding需在onDraw或onMeasure/onLayout中处理。避免在View中使用Handler,使用post系列方法代替。记得在onDetachedFromWindow时停止线程和动画以防止内存泄漏。处理滑动嵌套时解决滑动冲突,并避免在onDraw中大量创建临时对象。
14 4
|
2天前
|
Android开发
Android面试题之View的invalidate方法和postInvalidate方法有什么区别
本文探讨了Android自定义View中`invalidate()`和`postInvalidate()`的区别。`invalidate()`在UI线程中刷新View,而`postInvalidate()`用于非UI线程,通过消息机制切换到UI线程执行`invalidate()`。源码分析显示,`postInvalidate()`最终调用`ViewRootImpl`的`dispatchInvalidateDelayed`,通过Handler发送消息到UI线程执行刷新。
11 1
|
5天前
|
Android开发 Kotlin
Android面试题之 Kotlin中退出迭代器的方式有哪些
在Android和Kotlin中,遍历集合时可使用迭代器结合`break`提前终止循环。例如,使用`while`和迭代器,或用`forEach`配合`return@forEach`来中断遍历。若需退出外层函数,可定义自定义标签。在遍历并删除元素时,这些技巧尤其有用。
13 3
|
6天前
|
Java 数据格式
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
11 0
|
5天前
|
开发工具 Android开发 iOS开发
探索Android与iOS开发的差异与挑战
【7月更文挑战第11天】在移动应用开发的广阔天地中,Android和iOS两大平台如同双子星座般耀眼,各自拥有独特的开发生态和用户群体。本文将深入分析这两个平台的显著差异,从技术架构到开发工具,再到市场定位,揭示它们之间的异同。通过比较,我们不仅能够更好地理解各自的优势和局限,还能洞察未来移动应用开发的趋势。
|
8天前
|
Java Android开发 iOS开发
探索Android与iOS开发的差异:平台选择对项目成功的影响
【7月更文挑战第8天】在移动应用开发的广阔天地中,Android与iOS两大平台各自占据着半壁江山。本文将深入探讨这两个平台在开发环境、用户界面设计、性能优化以及市场覆盖等方面的根本差异,并分析这些差异如何影响项目的成功。通过比较和分析,旨在为开发者在选择平台时提供更全面的视角,帮助他们根据项目需求和目标市场做出更明智的决策。