Android 系统启动流程
- 启动电源以及系统启动: 当电源按下时,引导芯片代码从预定义的地方(固化在
ROM )开始执行。加载引导程序BootLoader 到RAM ,然后执行。 - 引导程序
BootLoader : 引导程序BootLoader 是在Android 操作系统开始运行前的一个小程序,它的主要作用是把系统OS 拉起来运行。 Linux 内核启动: 当内核启动时,设置缓存、被保护存储器,计划列表、加载驱动。当内核完成系统设置时,它首先在系统文件中寻找init.rc 文件,并启动init 进程。init 进程启动: 初始化和启动属性服务,并且启动Zygote 进程。Zygote 进程启动: 创建Java 虚拟机并为Java 虚拟机注册JNI 方法,创建服务端Socket ,启动SystemServer 进程SystemServer 进程启动: 启动Binder 线程池和SystemServiceManager ,并且启动各种系统服务Launcher 启动: 被SystemServer 进程启动AMS 会启动Launcher ,Launcher 启动后会将已安装应用的快捷图标显示到界面上。
Android 设备的启动必须经历3个阶段,即Boot Loader ,Linux Kernel 和Android 系统服务, 默认情况下,它们都有各自的启动画面。
严格来说,Android 系统实际上是运行于Linux 内核之上的一系列“服务进程”,并不算一个完整意义上的“操作系统”,这些进程是维持设备正常工作的关键,而它们都是由init 进程启动的。
boot loader [计] 引导装载程序 boot [bu?t] 启动 zygote [?za?ɡo?t] 受精卵 launch [l??nt?] 发起,发动,开始
init 进程
init 进程是Android 系统中用户空间的第一个进程,进程号为1,是Android 系统启动流程中的第一个关键的步骤, 作为第一个进程,它被赋予了很多极其重要的工作职责,可以说,在Linux 系统中,所有的进程都是由init 进程直接或间接fork 出来的, 比如创建Zygote (孵化器)和属性服务。
作为Android 系统的第一个进程,init 将通过解析init.rc 来启动其他关键的系统服务进程——其中,最重要的就是ServiceManager ,Zygote 、SystemServer 。
Android 的“DNS 服务器”——ServiceManager
ServiceManager 是Binder 机制中的“DNS 服务器”,负责域名(某Binder 服务在ServiceManager 注册时提供的名称)到IP地址(由底层Binder 驱动分配的值)解析。
当ServiceManager 每次重启时,其他关键进程如zygote ,media ,sufaceflinger 等也会被restart 。
僵尸进程与危害
在UNIX/Linux中,父进程使用fork 创建子进程,在子进程终止之后,如果父进程并不知道子进程已经终止了,这时子进程虽然已经退出了,但是在系统进程中还未它保留了一定的信息(比如进程号、退出状态、运行时间等),这个子进程就被称作为僵尸进程。 系统进程表是一项有限资源,如果系统进程表被僵尸进程耗尽的话,系统就可能无法创建新的进程了。
属性服务
Windows 平台上有一个注册表管理器,注册表的内容采用键值对的形式来记录用户、软件的一些使用信息。即使系统或者软件重启,其还是能够根据之前注册表中的记录,进行相应的初始化工作。Android 也提供了一个类似的机制,叫做属性服务。
init 进程启动时会启动属性服务,并为其分配内存,用来存储这些属性,如果需要这些属性直接读取就可以了。
Zygote 进程
在Android 系统中,DVM(Dalvik 虚拟机)和ART、应用程序进程以及运行系统的关键服务的SystemServer 进程都是由Zygote 进程来创建的(或者说大多数应用进程和系统进程都是通过Zygote 创建出来的),我们也将它称为孵化器。它通过fork (复制进程)的形式来创建应用程序进程和SystemServer 进程。 由于Zygote 进程在启动时会创建DVM或者ART,因此通过fork 而创建的应用程序进程和SystemServer 进程可以在内部获取一个DVM或者ART的实例副本。
为了实现资源共用和更快的启动速度,Android 系统开启新进程的新方式,是通过fork 第一个Zygote 进程实现的。 当系统里面的第一个Zygote 进程运行之后,在这之后再开启APP ,就相当于开启了一个新的进程。所以说,除了第一个Zygote 进程,其他应用所在的进程都是Zygote 的子进程。
每个APP 其实都是:一个单独的dalvik 虚拟机;一个单独的进程。
SystemServer 进程
SystemServer 也是是一个进程,是由Zygote 进程fork 出来的。这个进程是Android Framework 里面非常重要的进程,因为系统里面重要的服务都是在这个进程里开启的。比如ActivityManagerService 、PackageManagerService 、WindowManagerService 等等。
ActivityManagerService : 简称AMS ,服务端对象,负责系统中所有Activity 的生命周期(Activity 的开启、暂停、销毁)。在SystemServer 进程开启的时候,就会初始化ActivityManagerService 。
任何一个Activity 的启动都是由AMS 和应用程序进程(主要是ActivityThread )相互配合来完成的,AMS 服务统一调度系统中所有进程的Activity 启动,而每个Activity 的启动过程则由其所属的进程具体来完成。
SystemServer 进程总结:
- 启动
Binder 线程池,这样就可以和其他进程进行通信 - 创建
SystemServiceManager ,其对于系统的服务进行创建,启动和生命周期管理 - 启动各种系统服务
那么,对于APP 、SystemServer 、Zygote 分别属于三个独立的进程,它们之间是如何通信的呢?APP 和SystemServer 是用Binder IPC 通信的,SystemServer 和Zygote 是用Sockte IPC 进行通信的。
SystemServer 是Android 进入Launcher 前的最后准备,它提供了众多由Java语言编写的“系统服务”
Android系统中的服务端和客户端
服务端、客户端不仅仅存在于Web 开发中,在Android 的框架设计中,使用的也是这样一种模式。服务端指的是所有APP 共用的系统服务,比如ActivityManagerService 、PackageManagerService 、WindowManagerService 等等, 这些基础的系统服务是被所有的APP 共用的,当某个APP 想要实现某个操作的时候,就要告诉这些系统服务,比如你想要打开一个APP ,那么知道这个APP 的包名和MainActivity 类名之后即可以打开:
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_LAUNCHER);
ComponentName cn = new ComponentName(packageName, className);
intent.setComponet(cn);
startActivity(intent);
我们的APP 通过调用startActivity() 并不能直接打开另外的一个APP ,最终是通过AMS 来通知Zygote 进程来fork 一个新进程,来启动目标APP 。 这就像浏览器要打开一个超链接一样,浏览器把网页地址发送给服务器,然后服务器把需要的资源文件发送给客户端。
Launcher 启动流程
系统启动的最后一步是启动一个应用程序用来显示系统中已经安装的应用程序,这个应用程序叫做Launcher 。Launcher 在启动过程中会请求PackageManagerService 返回系统中已经安装的应用程序的信息,并将这些信息封装程一个快捷图标列表显示在系统屏幕上,这样用户可以通过点击这些快捷图标来启动相应的应用程序。
通俗来讲Launcher 就是Android 系统的桌面,它的作用主要有以下两点:
- 作为
Android 系统的启动器,用于启动应用程序 - 作为
Android 系统的桌面,用于显示和管理应用程序的快捷图标或者其他桌面组件
SystemServer 进程在启动的过程中会启动PackageManagerService 、PackageManagerService 启动后会讲系统中的应用程序安装完成。在此之前已经启动的AMS 会将Launcher 启动起来。
点击APP 的图标的时候,这个APP 就由Launcher 启动了。Launcher 本质上也是一个应用程序,和普通的APP 一样。我们在点击APP 图标的时候,捕捉到图标点击事件,然后startActivity() 发送对应的intent 请求。
https://cloud.tencent.com/developer/article/1356506
https://www.pianshen.com/article/10041941900/
https://www.jianshu.com/p/e3a630e85ee0
|