Android:启动流程
Posted 临木小屋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android:启动流程相关的知识,希望对你有一定的参考价值。
android启动流程
第一步:启动电源以及系统启动
当电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行。加载引导程序到RAM,然后 执行
第二步:引导程序
引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针 对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运 营商加锁和限制的地方。
引导程序分两个阶段执行。
第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序; 第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程 序可以根据配置参数或者输入数据设置内核。 Android引导程序可以在\\bootable\\bootloader\\legacy\\usbloader找到。传统的加载器包含两个文件, 需要在这里说明:
init.s初始化堆栈,清零BBS段,调用main.c的_main()函数; main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签
第三步:内核
Android内核与桌面linux内核启动的方式差不多。内核启动时,设置缓存、被保护存储器、计划列表, 加载驱动。当内核完成系统设置,它首先在系统文件中寻找”init”文件,然后启动root进程或者系统的第 一个进程
第四步:init进程 (搭建环境+启动zygote)
init进程是Linux系统中用户空间的第一个进程,进程号固定为1。Kernel启动后,在用户空间启动init进程,并调用init中的main()方法执行init进程的职责。
- 创建和挂载启动所需的文件目录
- 初始化和启动属性服务
- 解析init.rc配置文件并 启动zygote进程
3.1 ----》SystemServers—》开启一系列服务(AMS、WMS、PKMS、PMS、、、、)
3.2 ----》Launcher --> app —> 从 zygote fork 子进程 app
第五步:启动Lancher App
fork函数
pid_t fork(void)
返回值分两种情况:
- 返回0表示成功创建子进程,并且接下来进入子进程执行流程
- 返回PID(>0),成功创建子进程,并且继续执行父进程流程代码
- 返回非正数(<0),创建子进程失败,失败原因主要有: 进程数超过系统所能创建的上限,errno会被设置为EAGAIN系统内存不足,errno会被设置为 ENOMEM
使用 fork() 函数得到的子进程是父进程的一个复制品,它从父进程处继承了整个进程的地址空 间:包括进程上下文(进程执行活动全过程的静态描述)、进程堆栈、打开的文件描述符、信号控 制设定、进程优先级、进程组号等。子进程所独有的只有它的进程号,计时器等(只有小量信 息)。因此,使用 fork() 函数的代价是很大的
子进程与父进程的区别:
- 除了文件锁以外,其他的锁都会被继承
- 各自的进程ID和父进程ID不同
- 子进程的未决告警被清除;
- 子进程的未决信号集设置为空集。
相关面试题
你了解Android启动流程吗
当按电源键触发开机,首先会从ROM中预定义的地方加载引导程序BootLoader到RAM中,并执行BootLoader程序启动Linux kernel,然后启动用户级别的第一个进程:init进程。init进程会解析init.rc脚本并做一些初始化工作,包括挂载文件系统、创建工作目录以及启动系统服务进程等,其中系统服务进程包括Zygote、system manger、media等。在zygote中会进一步启动system_server进程,并启动AMS、WMS、PMS等服务,等这些服务启动后AMS就会打开Launcher应用的home activity,然后看到了手机的“桌面”
system_server为什么要在zygote中启动,而不是由init启动
zygote作为孵化器可以提前加载一些资源,这样fork()时基于Copy_On_Write 机制创建的其他进程就能直接使用这些资源而不用重新加载。比如system_server可以直接使用Zygote中的JNI函数、共享库、常用的类、以及主题资源
zygote为什么不用Binder机制进行IPC通信
Binder 机制中存在 Binder 线程池,是多线程的,如果 Zygote 采用 Binder 的话就存在上面说的fork() 与 多线程的问题了。其实严格来说,Binder 机制不一定要多线程,所谓的 Binder 线程只不过是在循环读取 Binder 驱动的消息而已,只注册一个 Binder 线程也是可以工作的,比如 service manager就是这样的。实际上 Zygote 尽管没有采取 Binder 机制,它也不是单线程的,但它在 fork() 前主动停止了其他线程,fork() 后重新启动了。
Android的Launcher启动流程 “Launcher部分启动流程”
研究代码从:AndroidManifest.xml、自定义的Application.java开始。
Android系统启动时,系统需要一个Home应用程序来负责将这些应用程序展示出来;也就是该应用的目的在于:Android系统启动后,第一个启动的应用程序。在Android系统中,这个默认的Home应用程序就是Launcher。
要把某个应用程序作为Home,只需要在Android.xml文件中添加一个category:
<intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.HOME" /> <category android:name="com.aliyun.ushell.action.detailpage" /> </intent-filter>
对于AndroidManifest.xml文件中的几个属性说明:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.aliyun.ushell" coreApp="true" android:sharedUserId="android.uid.system" android:versionCode="2" android:versionName="1.2.3" >
其中android:sharedUserId决定是否需要系统签名;android:theme决定整个应用的theme和style;andrid:debuggable决定应用是否处于调试模式。
疑问:
1. Launcher是如何被启动的?Android系统为什么在启动时会默认启动Launcher?
2. Launcher主要做什么工作?
Android系统开机会启动Launcher,Launcher是由ActivityManager启动的,而ActivityManager是由SystemServer启动。
此处就用到了在AndroidManifest.xml文件中添加的intent-filter属性值:category_home。一般绑定使用上述的三个category,也就是关键词:main/default/home。
Launcher的主要工作是:监听应用的安装、更新、删除等导致Launcher数据库变化的操作。Launcher数据都是使用ContentProvider来提供数据,也就是需要自定义ContentResolver监听指定Uri数据的变化。
private final ContentObserver mObserver = new ContentObserver(new Handler()) { @Override public void onChange(boolean selfChange, Uri uri) { final int nightSwitch = Global.getInt(UShellApplication.this.getContentResolver(), SWITCH_KEY, -1); final int nightOn = Global.getInt(UShellApplication.this.getContentResolver(), ON_KEY, -1); final boolean wallpaperOn = (Global.getInt(UShellApplication.this.getContentResolver(), WALLPAPER_KEY, DEFAULT_WALLPAPER) == 1); mWallpaperOn = wallpaperOn; if (readTime() || nightSwitch != mNightSwitch || nightOn != mNightOn) { mNightSwitch = nightSwitch; mNightOn = nightOn; if (!Utilities.IS_ZHONGHONG) { onTimeChanged(); } else { onZHChanged(null); } } } };
Launcher启动的过程主要就是加载界面数据然后显示出来,界面数据都是系统App有关的数据(可能包含Launcher数据库)。
以上是关于Android:启动流程的主要内容,如果未能解决你的问题,请参考以下文章