Copyright:http://blog.csdn.net/myzhzygh/article/details/7721857
1.Introduction
在文档“Android boot and init”中我们已经研究了Android系统的引导和加载过程。本章描述了在Kernel启动完成之后,Android系统执行了根文件系统目录下的init脚本,通过init脚本建立Android系统最初运行的环境。可以看出在这篇文章中,我们更多的侧重于内核启动和init脚本所完成的功能。而在本文中,我们将更多的讨论系统init脚本执行完之后,Android系统是如何完成后续启动过程,包括虚拟机创建,系统服务加载,系统应用程序启动等内容。
Android系统是基于Linux kernel的,抛开Linux kernel启动的过程,从另一个角度,我们可以认为Android的启动过程是从进程init开始的,也就是init脚本执行完成之后第一个执行的程序,所以它是后续所有进程的祖先进程。
2.Native System Service
如果说init程序之前的操作是在为Android系统的启动做准备工作,那么从Android系统的init程序开始,我们就是在真正的创建Android系统运行的环境。在这个过程中,我们要完成文件系统节点的创建,设置系统环境变量和启动相应的系统服务等操作。Android系统提供了灵活的init.rc配置文件,能够实现对这个阶段系统操作进行灵活的配置。在每次系统启动的时候,init程序都会对init.rc配置文件进行解析,完成系统基本参数设置和基本服务的加载。下面我们看看在init.rc文件中所描述的的服务。
init.rc 文件里面的服务有2种, class core和class main。对 init.rc文件中描述的 service 按照 class <name>分类如下:
class core:
service ueventd /sbin/ueventd
service console /system/bin/sh
service adbd /sbin/adbd
service servicemanager /system/bin/servicemanager
service vold /system/bin/vold
class main:
service netd /system/bin/netd
service debuggerd /system/bin/debuggerd
service ril-daemon /system/bin/rild
service surfaceflinger /system/bin/surfaceflinger
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
service drm /system/bin/drmserver
service media /system/bin/mediaserver
service bootanim /system/bin/bootanimation
service dbus /system/bin/dbus-daemon --system --nofork
service bluetoothd /system/bin/bluetoothd -n
service installd /system/bin/installd
service flash_recovery /system/etc/install-recovery.sh
service racoon /system/bin/racoon
service mtpd /system/bin/mtpd
service keystore /system/bin/keystore /data/misc/keystore
service dumpstate /system/bin/dumpstate -s
上面列出了init.rc中描述的所有服务,针对具体的vendor,这些服务并不是都需要启动。在 class core服务启动以后, class main开始启动。下面列出针对Service的一些Options。
表1:init.rc service options
Options for Service |
Description |
setenv <name> <value> |
在启动服务时设置环境变量 |
user <username> |
运行服务之前切换用户 |
oneshot |
如果服务已经存在,将不再启动 |
class <classname> |
为服务设置名字,具有相同名字的服务将一起启动或者关闭 |
socket <name> <type> <perm> [ <user> [ <group> ] ] |
创建以<name>命名的 socket,并将该 socket的文件描述符返回给启动的服务 |
onrestart <command> |
在服务重新启动的时候执行<command> |
对于init程序及init.rc其它规则我们在这里不再做详细的描述。具体可参考Android init language Spec。
3.Zygote Service
下面我们将研究Android系统最重要的服务zygote的启动流程。首先我们必须清楚zygote服务在init.rc配置文件中的描述形式:
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
class main
socket zygote stream 666
onrestart write /sys/android_power/request_state wake
onrestart write /sys/power/state on
onrestart restart media
onrestart restart netd
Zygote服务是标志进入 android系统的最重要服务之一,从上面的描述可以看到,服务名字为 zygote,实际的执行体是 ‘/system/bin/app_process’程序;同时zygote服务带有--zygote和--start-system-server参数,这些参数对zygote服务的启动具有非常重要的作用。zygote服务相关选项所表示的含义如表1所示:
表2:zygote service sample
Option |
Description |
class main |
说明service zygote属于main类型的service |
socket zygote stream 666 |
在服务启动之前,需要创建一个命名为zygote的socket,该socket访问权限标示为666. |
onrestart write /sys/android_power/request_state wake |
该服务重启的时候,需要向电源管理中写入wake参数,电源管理请求为wake |
onrestart restart media |
该服务重启的时候,需要重新启动media服务 |
onrestart restart netd |
该服务重启的时候,需要重新启动netd服务 |
从本文之前的内容我们知道,zygote服务只是init程序在系统启动阶段启动的服务之一,具体的说是main类型服务成员之一。但由于Android系统作为特殊的Linux系统,它所有应用程序都是运行在Java语言的基础上,所以为了支持这种特性,Android系统就必须构建支持Java程序运行的Runtime环境。而Zygote服务就是构建Java Runtime环境的起点,换句话说它是所有Java程序的始祖。所以我们有必要详细的研究,最终清楚Android Runtime构建的流程,并了解在这个过程中所进行的其它操作,如2D display环境的初始化等。
Zygote服务的执行实体为 ’/system/bin/app_process’,所以我们以app_process程序为研究的入口点,具体是以app_process程序的main方法为入口点,通过对main方法的代码实现进行宏观的分析,从分析的结果我们得出其实现的主要逻辑功能如下:
1. 构造AndroidRuntime类的实例
AppRuntime runtime;
系统的AndroidRuntime类定义了基本的Android Runtime接口,但AndroidRuntime类作为一个抽象类,不能实例化自己的对象。在app_process程序中定义了AppRuntime类, AppRuntime类作为AndroidRuntime类的派生类,继承了AndroidRuntime类的部分接口实现,同时实现了AndroidRuntime类所定义的抽象接口,所以zygote服务的启动,我们首先实例化了一个AppRuntime类的对象,作为Runtime实例。接下来我们分析AppRuntime类和AndroidRuntime类的构造函数,从AppRuntime类的构造函数实现我们知道AppRuntime类在构造函数并没有做什么事,所以我们重点研究了AndroidRuntime类的构造函数。
AndroidRuntime::AndroidRuntime()
{
SkGraphics::Init();
// this sets our preference for 16bit images during decode
// in case the src is opaque and 24bit
SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);
// This cache is shared between browser native images, and java "purgeable"
// bitmaps. This globalpool is for images that do not either use the java
// heap, or are not backed by ashmem. See BitmapFactory.cpp for the key
// java call site.
SkImageRef_GlobalPool::SetRAMBudget(512 * 1024);
// There is also a global font cache, but its budget is specified in code
// see SkFontHost_android.cpp
// Pre-allocate enough space to hold a fair number of options.
mOptions.setCapacity(20);
assert(gCurRuntime == NULL); // one per process
gCurRuntime = this;
}
从上面AndroidRuntime类的构造函数实现来看,构造函数最重要的任务就是初始化负责系统2D Display的Skia库,指定系统默认颜色格式,设置images共享缓冲区的大小。
SkImageDecoder::SetDeviceConfig(SkBitmap::kRGB_565_Config);
SkImageRef_GlobalPool::SetRAMBudget(512 * 1024);
2. 解析init.rc中zygote传递的启动参数,设置Runtime启动参数
while (i < argc) {
const char* arg = argv[i++];
if (!parentDir) {
parentDir = arg;
} else if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = "zygote";
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName = arg + 12;