从按下电源键到android桌面启动到底发生了什么?
原文链接 http://www.rogerblog.cn/2015/08/14/e4-bb-8e-e6-8c-89-e4-b8-8b-e7-94-b5-e6-ba-90-e9-94-ae-e5-88-b0android-e6-a1-8c-e9-9d-a2-e5-90-af-e5-8a-a8-e5-88-b0-e5-ba-95-e5-8f-91-e7-94-9f-e4-ba-86-e4-bb-80-e4-b9-88-ef-bc-9f/
注:以下为加速网络访问所做的原文缓存,经过重新格式化,可能存在格式方面的问题,或偶有遗漏信息,请以原文为准。
最近研究了一下andorid的启动过程,记录一点心得.
学习资料主要为这两篇博客: Android Framework启动流程分析 Android启动过程深入解析,感谢博主.
总流程可以用一张图说明:
此处图片中step2中的一个单词拼写错了,Boot Loaeder应该为Boot Loader
我们知道android是基于Linux系统的,那么按下电源键首先启动的自然是linux系统内核.
第一步,启动电源执行引导程序
<!--more-->
电源按下,引导芯片代码开始从预定义的地方(固化在ROM)开始执行.加载引导程序到RAM,然后执行.
引导程序是在Android操作系统开始运行前的一个小程序。引导程序是运行的第一个程序,因此它是针对特定的主板与芯片的。设备制造商要么使用很受欢迎的引导程序比如redboot、uboot、qi bootloader或者开发自己的引导程序,它不是Android操作系统的一部分。引导程序是OEM厂商或者运营商加锁和限制的地方。
引导程序分两个阶段执行。第一个阶段,检测外部的RAM以及加载对第二阶段有用的程序;第二阶段,引导程序设置网络、内存等等。这些对于运行内核是必要的,为了达到特殊的目标,引导程序可以根据配置参数或者输入数据设置内核。
Android引导程序可以在\bootable\bootloader\legacy\usbloader找到。
传统的加载器包含的个文件,需要在这里说明:
init.s初始化堆栈,清零BBS段,调用main.c的_main()函数;
main.c初始化硬件(闹钟、主板、键盘、控制台),创建linux标签
第二步,Linux系统内核
Linux内核加载主要包括初始化kernel核心(内存初始化,打开中断,初始化进程表等)、初始化驱动、启动内核后台(daemons)线程、安装根(root)文件系统等。
Linux加载的最后阶段启动执行第一个用户级进程init(内核引导参数上一般都会设置“init=/init”,由kernel自动执行,PID为1,是所有进程的父进程)。由此进入Android框架的启动阶段。
第三步,init进程
进入android框架启动阶段可以用一张图说明:
init是第一个进程,我们可以说它是root进程或者说有进程的父进程.init进程有两个责任,一是挂载目录,比如/sys、/dev、/proc,二是运行init.rc脚本.
init.rc文件是Android系统的重要配置文件,位于/system/core/rootdir/目录中.主要功能是定义了系统启动时需要执行的一系列action及service:执行特定动作、设置环境变量和属性和执行特定的service.该脚本在init进程的init.c:main函数中解析并启动.
重点说明的是init.rc脚本文件配置了一些重要的服务,init进程通过创建子进程启动这些服务,这里创建的service都属于native服务,运行在Linux空间,通过socket向上层提供特定的服务,并以守护进程的方式运行在后台.
通过init.rc脚本系统启动了以下几个重要的服务:
1)servicemanager:启动binder IPC,管理所有的Android系统服务
2)mountd:设备安装Daemon,负责设备安装及状态通知
3)debuggerd:启动debug system,处理调试进程的请求
4)rild:启动radio interface layer daemon服务,处理电话相关的事件和请求
5)mediaserver:启动AudioFlinger,MediaPlayerService and CameraService,负责多媒体播放相关的功能,包括音视频解码、显示输出
6)zygote:进程孵化器,启动Android Java VMRuntime和启动systemserver,负责Android应用进程的孵化工作
在这个阶段你可以在设备的屏幕上看到“Android”logo了.
第四步,zygote服务启动
在Java中,我们知道不同的虚拟机实例会为不同的应用分配不同的内存。假如Android应用应该尽可能快地启动,但如果Android系统为每一个应用启动不同的Dalvik虚拟机实例,就会消耗大量的内存以及时间。因此,为了克服这个问题,Android系统创造了”Zygote”。Zygote让Dalvik虚拟机共享代码、低内存占用以及最小的启动时间成为可能。Zygote是一个虚拟器进程,正如我们在前一个步骤所说的在系统引导的时候启动。Zygote预加载以及初始化核心库类。通常,这些核心类一般是只读的,也是Android SDK或者核心框架的一部分。在Java虚拟机中,每一个实例都有它自己的核心库类文件和堆对象的拷贝。
zygote进程孵化了所有的Android应用进程,是Android Framework的基础,该进程的启动也标志着Framework框架初始化启动的开始。zygote服务进程的主要功能:
1)注册底层功能的JNI函数到虚拟机
2)预加载java类和资源
3)fork并启动System Server核心进程
4)作为守护进程监听处理“孵化新进程”的请求
虚拟机启动后执行的第一个Java类是ZygoteInit.java,并进入ZygoteInit.java:main()函数中。在main函数中实现了以下逻辑:
1)启动服务端Socket端口:
调用registerZygoteSocket()实现,主要用于接受处理创建新进程的请求。
2)预加载指定的java类和资源:
调用preloadClasses()预加载指定的java类,调用preloadResources()预加载指定的Resources。特别说明的是孵化器进程会把这些预先加载的类和资源共享给所有APK应用进程,这样有效的解决了Framework类和资源共享的问题。
3)启动System Server进程:
调用startSystemServer()创建(fork)SystemServer进程。该函数的关键代码有三处:
—设定启动进程的相关信息:比如进程名称、启动后装载的第一个java类
—调用forkSystemServer()从当前的zygote进程孵化出新的进程
—调用函数hanldeSystemServerProcess()关闭从Zygote进程继承过来的Socket,调用RuntimeInit.zygoteInit()启动SystemServer.java:main()函数
4)循环监听孵化新Dalvik进程的请求:
调用runSelectLoopMode()进入无限循环:监听客户端socket连接,根据请求孵化新的应用进程。Process类中保存了客户端socket,并由ActivityManagerService管理该客户端。每当需要启动新的Dalvik应用进程时,ActivityManagerService都会通过该socket客户端与Zygote进程的socket服务端进行通信,请求Zygote孵化出新的进程。
至此,启动zygote服务工作完成,需要说明的是zygote进程即为app_process可执行程序所在进程。 在这个阶段,你可以看到启动动画.
第五步,System Server进程启动
SystemServer进程在Android的运行环境中扮演了“神经中枢”的作用,Android应用能够直接交互的大部分系统服务都在该进程中运行,如WindowManagerServer、ActivityManagerSystemService、PackageManagerServer等,这些系统服务都是以独立线程的方式存在于SystemServer进程中。System Server进程的主要功能:
1)加载android servers底层函数库
2)启动android系统中的native服务
3)创建、注册并启动Android的系统服务,在独立线程中运行
4)创建Looper消息循环,处理System Server进程中的事件消息
在zygote进程中调用函数startSystemServer()创建和启动Server进程,进程首先执行的函数是SystemServer.java:main()。该函数函数实现的主要逻辑为:
1)加载android_servers函数库
2)启动native服务:
调用本地函数init1()实现,该函数的源码位于文件frameworks/base/services/jni/com_android_server_systemService.cpp中,涉及的函数system_init()实现在文件frameworks/base/cmds/system_server/library/system_init.cpp中。
3)启动Android系统的各种系统服务:
调用函数init2()实现,该函数首先创建了一个ServerThread对象,该对象是一个线程,然后直接运行该线程.
从ServerThread的run()方法内部开始真正启动各种服务线程。
—创建Android系统服务对象,并注册到ServiceManager
—在SystemServer进程中建立Looper消息循环:通过Looper.prepare和Looper.loop来实现
—系统就绪通知:调用systemReady()通知各个服务
System Server进程启动过程中最核心的一步是“启动Android系统的各种系统服务”,这些系统服务构成了整个Android框架的基础(如图所示),通过Binder IPC为上层应用提供各种功能。
1)ActivityManagerService
Activity管理服务,主要功能包括:
—统一管理和调度各应用程序的Activity,维护系统中运行的所有应用Task和Activity
—内存管理:应用程序关闭时对应进程还在运行,当系统内存不足时根据策略kill掉优先级较低进程
—进程管理:维护和管理系统中运行的所有进程,并提供了查询进程信息的API
—Provider、Service和Broadcast管理和调度
2)WindowManagerService
窗口管理服务,主要功能包括为应用程序分配窗口,并管理这些窗口。包括分配窗口的大小、调节各窗口的叠放次序、隐藏或者显示窗口,程序退出时删除窗口。
3)PackageManagerService
程序包管理服务,主要功能为:
—根据intent查找匹配的Activity、Provider以及Service
—进行权限检查,即当应用程序调用某个需要一定权限的函数时,系统能够判断调用者是否具备该权限
—提供安装、删除应用程序的API
4)NotificationManagerService
通知管理服务,负责管理和通知后台事件的发生等,这个和statusbar服务结合在一起,一般会在statusbar上添加响应图标。用户可以通过这知道系统后台发生了什么事情。
5)AudioService
音频管理服务,AudioFlinger的上层管理封装,主要是音量、音效、声道及铃声等的管理。
6)TelephonyRegistry
电话服务管理,用于监听和上报电话状态,包括来电、通话、信号变化等。
到这里,Android Framework的启动已经完成,框架中提供的各种服务也已经就绪,可以正常运行并响应处理应用的各种操作请求。
第六步,Home应用启动
在ServerThread:run()函数的最后调用了ActivityManagerService.self().systemReady方法,该方法实现了如下代码用于启动第一个Activity:
mMainStack.resumeTopActivityLocked(null);
由于系统刚启动时没有任何Activity对象,代码会调用ActivityManagerService:startHomeActivityLocked函数启动Home应用:
Intent intent = new Intent( mTopAction, mTopData != null ? Uri.parse(mTopData) : null); intent.setComponent(mTopComponent); if (mFactoryTest != SystemServer.FACTORY_TEST_LOW_LEVEL) { intent.addCategory(Intent.CATEGORY_HOME); }
至此桌面应用已经完全启动!以上都是一些学习笔记,许多都是复制粘贴做一些记录~还请大家多多参研原博哈~