Android启动分析
Android的启动主要是三部分:bootloader启动,linux kernel 启动,android启动
因为android系统在本质上是基于linux系统开发的,所以其启动与一般linux启动有很多相似的地方(比如说bootloader启动和加载linux kernel)。分析一般linux系统可以在某种程度上加深对android系统的理解;因此我们先分析一般linux系统的启动,然后在分析andrid系统的启动;我们可以比较一下他们之间的不同,并更深入的理解android系统的启动过程。
全文一共分为两个部分:
第一部分:一般的linux的启动
第二部分:android系统的启动
(附注)android系统的启动中具体有:init启动守护进程,启动Zygote进程,启动Runtime进程,启动各种服务,最后System service启动launcher。
第一部分:一般的linux的启动
注:讲解的是linux启动的一般过程,并借以分析android系统的启动
【简述】
1. linux开机从POST加电自检开始,当自检完成,读取第一个硬盘的第0个磁头里的前446个字节,运行里面的bootloader
2. 通过grub传递参数给内核,初始化加载内核过程,内核调用initrd(小型内存文件系统,五脏俱全,是一个微型linux),通过initrd,以只读方式挂载根文件系统
3. 当根文件系统被挂载后,就会读取并运行/sbin/init来进行初始化工作
4. 按次序依次执行/rc/sysinit ,这个时候会重新以读写的方式挂载根文件系统
5. 读取/etc/rc.d/rcN.d/来启动以s开头的服务,停止以k开头的服务
6. 当一切准备完毕,打印终端,出现熟悉的Login界面!(当然,如果你是以5级别启动的话,Linux就会启动图形界~)
【详解】
1 启动第一步--加载BIOS
当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它。这是因为BIOS中包含了CPU的相关信息、设备启动顺序信息、硬盘信息、内存信息、时钟信息、PnP特性等等。在此之后,计算机心里就有谱了,知道应该去读取哪个硬件设备了。
2. 启动第二步--读取MBR
众所周知,硬盘上第0磁道第一个扇区被称为MBR,也就是Master Boot Record,即主引导记录,它的大小是512字节,别看地方不大,可里面却存放了预启动信息、分区表信息。
系统找到BIOS所指定的硬盘的MBR后,就会将其复制到0x7c00地址所在的物理内存中。其实被复制到物理内存的内容就是Boot Loader,而具体到你的电脑,那就是lilo或者grub了。
3. 启动第三步--Boot Loader
Boot Loader 就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核做好一切准备。Boot Loader有若干种,其中Grub、Lilo和spfdisk是常见的Loader。
4. 启动第四步--加载内核
根据grub设定的内核映像所在路径,系统读取内存映像,并进行解压缩操作。此时,屏幕一般会输出“Uncompressing Linux”的提示。当解压缩内核完成后,屏幕输出“OK, booting the kernel”。
系统将解压后的内核放置在内存之中,并调用start_kernel()函数来启动一系列的初始化函数并初始化各种设备,完成Linux核心环境的建立。至此,Linux内核已经建立起来了,基于Linux的程序应该可以正常运行了。
5. 启动第五步--用户层init依据inittab文件来设定运行等级
内核被加载后,第一个运行的程序便是/sbin/init,该文件会读取/etc/inittab文件,并依据此文件来进行初始化工作。
其实/etc/inittab文件最主要的作用就是设定Linux的运行等级,其设定形式是“:id:5:initdefault:”,这就表明Linux需要运行在等级5上。Linux的运行等级设定如下:
0:关机
1:单用户模式
2:无网络支持的多用户模式
3:有网络支持的多用户模式
4:保留,未使用
5:有网络支持有X-Window支持的多用户模式
6:重新引导系统,即重启
6. 启动第六步--init进程执行rc.sysinit
在设定了运行等级后,Linux系统执行的第一个用户层文件就是/etc/rc.d/rc.sysinit脚本程序,它做的工作非常多,包括设定PATH、设定网络配置(/etc/sysconfig/network)、启动swap分区、设定/proc等等。如果你有兴趣,可以到/etc/rc.d中查看一下rc.sysinit文件,里面的脚本够你看几天的:P
7. 启动第七步--启动内核模块
具体是依据/etc/modules.conf文件或/etc/modules.d目录下的文件来装载内核模块。
8. 启动第八步--执行不同运行级别的脚本程序
根据运行级别的不同,系统会运行rc0.d到rc6.d中的相应的脚本程序,来完成相应的初始化工作和启动相应的服务。
9. 启动第九步--执行/etc/rc.d/rc.local
rc.local就是在一切初始化工作后,Linux留给用户进行个性化的地方。你可以把你想设置和启动的东西放到这里。
10. 启动第十步--执行/bin/login程序,进入登录状态
此时,系统已经进入到了等待用户输入username和password的时候了,你已经可以用自己的帐号登入系统了。
第二部分:对比linux系统启动,我们来分析android系统的启动
前两部分的启动大体是相同的,基本上都是bootloader的启动然后加载linux kernel。所不同的是从加载完linux kernel开始:linux系统执行init进程,启动linux服务,执行用户设置并进入logo;而android系统则执行了自己定义的init进程(重写了linux的init进程),然后在这里开始了android系统的模块
为了启动并运行整个android系统,google实现了自己的init进程:
Android的init进程:
注:这里所说的linux系统完全可以理解为android系统
当linux内核启动之后,运行的第一个进程是init,这个进程是一个守护进程,它的生命周期贯穿整个linux 内核运行的始终, linux中所有其他的进程的共同始祖均为init进程。
Init进程启动之后做了哪些事情呢?
Init进程启动后,会根据init.c 和init.xxx.rc脚本文件建立几个基本服务:Service Manager,Zygote ,Vold等。 但是最后init进程并不退出,而是担当起了property service的功能。
Init.c是init进程的源码
Init.rc则是android中使用的启动脚本,可以在系统初始化中进行一点简单的初始化操作。这个脚本被直接安装到目标系统的根文件系统中,被Init可执行程序解析。其中init.rc是在init进程启动后被执行的启动脚本
启动linux守护进程:
Usbd进程(USB Daemon):USB连接后台进程,负责管理USB连接。
adbd 进程(Android Debug Bridge Daemon):ADB连接后台进程,负责管理ADB连接。
debuggerd 进程(Debugger Daemon) :调试器后台进程,负责管理调试请求及调试过程。
rild进程 (Radio Interface Layer Daemon): 无线接口层后台进程,负责管理无线通信服务。
Zygote进程
在启动守护进程的同时,init进程启动Zygote进程
Zygote 进程启动后,首先初始化一个Dalvik VM实例,然后为它加载资源与系统共享库,并开启Socket监听服务,当收到创建Dalvik VM实例请求时,会通过COW(copy on write)技术最大程度地复用自己,生成一个新的Dalvik VM实例。Dalvik VM实例的创建方法基于linux系统的fork原理。
Runtime进程
启动Zygote进程之后init进程启动runtime进程
在Zygote进程启动完成之后,Init进程会启动Runtime进程。Runtime进程首先初始化服务管理器(Service Manager),并把它注册为绑定服务(Binder services)的默认上下文管理器,负责绑定服务的注册与查找。然后Runtime进程会向Zygote进程发送启动系统服务(System Service)的请求,Zygote进程收到请求后,会“孵化”出一个新的Dalvik VM实例并启动系统服务进程
启动各种服务
System Service会首先启动两个本地服务(由C或C++编写的native服务),Surface Flinger和Audio Flinger,这两个本地系统服务向服务管理器注册成为IPC服务对象,以便在需要它们的时候很容易查找到。然后SystemService 会启动一些 Android 系统管理服务,包括硬件服务和系统框架核心平台服务,并注册它们成为IPC服务对象。
首先启动系统服务System Server
再启动本地服务(主要是Audio Flinger和Surface Flinger)
最后再启动android服务(他们都需要向Service Manager 注册而作为服务)
启动Home Launcher
当SystemServer 加载了所有的系统服务后就意味着系统就准备好了,它会向所有服务发送一个系统准备完毕(systemready) 广播。当ActivityManager 接收到systemready广播后,会向Zygoute进程发送创建Dalvik 虚拟机实例的请求,Zygoute进程会负责生成一个新的Dalvik 虚拟机实例,然后ActivityManagerService在系统中查找具有<category android:name = "android.intent.category.HOME"/>属性的Activity,并启动它。ActivityManagerService同时也会使用同样的方法启动Contact(联系人)应用程序。
Home Launcher 启动是由System service 发动的。
至此android系统已经运行起来了。对比linux系统的启动,android系统与之关键的区别是在init进程所做的事情上面。android系统在init进程中启动了一些自己的服务和进程创建机制。至此简单的分析结束。
(总结):最后是自己画的一张图,如有错误还望指正: