摘要:Android系统启动的过程可概括为init进程启动、Native服务启动、SystemServer,Android服务启动和Home启动4个步骤。各个步骤紧密联系一环紧扣一环,是一个统一的整体。
关键字:init进程;Zygote进程;SystemServer
1 Android OS架构
Android 系统采用了分层架构,分为4个层次,从高层到底层分别是应用程序层、应用层许框架层、系统运行库层、和Linux核心层。观察Android系统架构图可以发现,其提供的基本应用程序(Home,Camera,Dialer,Browser等)运行在应用程序框架之上。对开发者而言,开发者可以借助Android SDK,调用应用程序框架API开发出应用也运行在应用程序框架层之上。
Android系统架构图
Android系统的各个层次都有不同的功能,在这里不做过多的概述只初步的了解一下。
2 init进程及其启动
init进程是一个用户级进程,init有许多重要任务,比如像启动getty(用于用户登录)、实现运行级别、以及处理孤立进程等。init始终是第一个进程。
启动时,首先通过bootloader(系统加载器),加载Linux内核。在Linux加载启动内核时,与普通的Linux启动过程相同,先初始化内核,然后调用init进程。
init进程启动过程
由init进程启动图可以看出,init进程是在顺序执行完start_kernel()函数、init_post()函数、run_init_process()函数后,最后执行的。实现init进程启动的代码如下:
Static int noinline init_post(void)
{
if(execute_command){
run_init_process(execute_command);
}
run_init_process(“/sbin/init”);
run_init_process(“/etc/init”);
run_init_process(“/bin/init”);
}
Android init进程对各种设备进行初始化,运行Android Framework所需要的各种Daemon、ServiceManager、Zygote等。其中ServiceManager是一个管理Android系统服务的重要进程。系统服务是组成Android Framework的重要组件,提供相机、音频、视频、处理到各种应用程序制作所需要的重要API。
init进程不仅进行子进程的终止处理,当应用程序访问设备驱动时,还会生成设备节点文件,同时提供属性服务,保存系统运行所需的环境变量。此外,它还会分析init.rc启动脚本文件,并根据相关文件中包含的内容,执行相应的功能。
Android启动时,init.rc脚本文件用来设置系统环境,记录待执行的进程;二是action list与service list相关的内容,它们是由init进程根据init.rc生成的。Init.rc文件结构如下
init.rc文件结构
2.1 动作列表(Action List)
在动作列表的“on init”段落中,主要设置环境变量,生成系统运行所需的文件或目录,修改相应的权限,并挂载与系统运行相关的目录。
on init段落
在“on init”根文件系统挂载部分,主要挂载/system与/data两个目录。两个目录挂载完毕后,Android根文件系统就准备好了。
2.2 服务列表(Service List)
在init.rc脚本文件中,“service”段落用来记录init进程启动的进程。由init进程启动的子进程或是一次性程序,或是运行在后台的与应用程序、系统服务管理相关的ServiceManager进程等。
最后init进程并不退出,而是担当起属性服务(property service)的功能。
3 Zygote进程
从字面上看Zygote是“受精卵、结合子、结合体”的意思。在Android系统中运行新的应用,如同卵子受精分裂一样需要跟Zygote进程(拥有应用程序运行时所需的各种元素与条件)结合后才能执行。Zygote是Android系统应用中的一个相当重要的进程,它的主要功能
就是执行Android应用程序。
Zygote进程运行时,会初始化Dalvik虚拟机,并启动它。Android的应用程序时由java编写的,他们不能直接以本地进程的形态运行在Linux上,只能运行在Dalvik虚拟机中。此时我们就可以和Android的架构对应起来了,此时系统已经运行到系统运行库层。Android的服务与应用程序都由Zygote进程启动运行。
由app_process运行ZygoteInit class
Zygote由java编写而成,不能直接由init进程启动运行。若想运行Zygote类,必须先生成Dalvik虚拟机,再在Dalvik虚拟机上装载运行ZygoteInit类,执行这一任务的就是app_process进程。app_process进程执行时,首先常见AppRuntime对象。部分源代码如下
int main(){
...
AppRuntime runtime;
..
//Everything up to ‘--’ or first non ‘-’ arg goes to the *vm
int i = runtime.addVmArguments(argc,argv);
//Next arg is parent directory
if(i
runtime.mParentDir = argv[i++];
}
}
AppRuntime类继承自AndroidRuntime类,AndroidRuntime类运行于初始化并运行Dalvik虚拟机之前,通过AppRuntime对象,分析环境变量以及运行参数,并以此生成虚拟机选项。分析完要传递给虚拟机的参数,并保存到AppRuntime类的对象中,而后加载对象,调用对象的main()方法。
int main(int argc ,const char* const argv[]){
...
if(i
arg = argv[i++];
if(0 == strcmp(“--zygote”,arg)){
bool startSyatemServer = (i < argc)?
strcmp(argv[i],”--start-system-server”) == 0:false;
setArgv0(argv0,”zygote”);
set_process_name(“zygote”);
//生成并初始化虚拟机
runtime.start(“com.android.internal.os.ZygoteInit”
,startSystemSever);
}else {...}
}
...
}
Dalvik虚拟机由runtime启动并初始化(见上面注释),而后将ZygoteInit类加载至虚拟机中,执行其中的main方法。
ZygoteInit类的主要有四大功能,分别是绑定/dev/socket/zygote套接字、加载应用程序Framework中的类与平台资源、运行SystemServer和运行新的Android应用程序。在这里我们只初步解释其中的部分功能。ZygoteInit::main()方法的主要功能如下图:
ZygoteInit功能图
下面我们先看一下ZygoteInit类的部分源代码。
public static void main(String argv[]){
try{
//绑定套接字,接受新的Android应用程序请求
registerZygoteSocket();
...
//加载Android Application Framework使用的类资源
preloadClasses();
preloasResources();
...
//运行SystemSever
if(argv[1].equals(“true”)){
startSystemServer();
}
...
if(ZYGOTE_FORK_MODE){
runForkMode();
}else {
//处理新Android应用程序运行请求
runSelectLoopMode();
}
closeSeverSocket();
}catch(MethodANdArgsCaller caller){
caller.run();
}catch(RuntimeException ex){
log.e(TAG,”Zygote died with exception”,ex);
closeServerSocket();
throw ex;
}
}
ZygoteInit类会调用preloadClasses()与preloadResources()两个方法,这两个方法分别用于将应用程序Framework中的类,以及图标、图像、字符串等资源加载到内存之中,并对装载的类与资源生成链接信息。新生成的Android应用程序在使用这些已经装载的类或资源时,直接使即可。至此,Dalvik虚拟机已经启动并完成初始化,还绑定了套接字,以便接收应用程序的创建请求。并且,包含应用程序Framework中的类与资源也被加载到内存之中。由此ZygoteInit类做好了接收请求创建应用程序并运行的准备。但ZygoteInit在处理应用程序创建请求之前,还有一项工作就是运行SystemServer。
Zygote进程启动Dalvik虚拟机后,会在生成一个Dalvik虚拟机实例,以便运行名称为SystemServer的java服务,SystemServer用于运行Audio Flinger与Surface Flinger本地服务。在运行完所需要的本地服务之后,SystemServer开始运行Android Framework的服务,如ActivityManager(管理Android应用程序的Activity)、PackageManager(设置或安装应用程序)等。
4 Home启动和其他应用程序的启动
4.1 应用程序的启动
在SystemSever运行后,程序会进入一个循环,处理来自所绑定的套接字请求。若ZYGOTE_FORK_MODE为false,程序就会调用runSelectLoopMode()方法,直到zygote进程终止,该方法才返回。
接下来看一下runSelectLoopMode的部分源代码。
private static void runSelectLoopMode() throws MethodAndArgsCaller{
......
fds.add(sSeverSocket.getFileDescriptor());
while(true){
......
index = selectReadable(fdArray);
......
if(index <0){
throw new RuntimeException("Error in select()");
}
else if(index ==0){
ZygoteConnection newPeer = acceptCommandPeer();
peers.add(newPeer);
fds.add(newPeer.getFileDescriptor());
}
else {
boolean done;
done = peers.get(index).runOnce();
if(done){
peers.remove(index);
fds.remove(index);
}
}
}
}
donr = peers.get(index).runOnce()这行代码用于处理新连接的输入输出套接字,并生成新的Android应用程序,具体过程如下。
boolean runOnce() throws ZygoteInit.MethodAndArgsCaller{
...
try{
args = readArgumentList();
...
}
...
int pid;
try{
parseArgs =new Arguments(args);
applyUidSecurityPolicy(pareseArgs,peer);
applyDebuggerSecurityPolicy(parseArgs);
applyRlimitSecurityPolicy(parsedArgs,peer);
applyCapailitiesSecurityPolicy(parseArgs,peer);
int[][] rlimits = null;
if(parsedArgs.rlimits != null){
rlimits = paresedArgs.rlimits.toArry(intArray2d);
}
pid = Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid,parsedArgs.gids,parsedArgs.debugFlagd,rlimits);
}
......
}
runOnce()函数分析请求信息中的字符串数组,为运行进程设置好各个选项,具体包括设置应用程序的gid、uid,调试标记处理,设置rlimit,以及检查运行权限等。之后就可以创建新进程了,Zygote.forkAndSpecialize()方法接受上面分析好的参数,调用Zygote类的本地方法forkAndSpecialize()。然后调用本地函数fork(),创建新进程,并根据新创建的进程传递的选项,设置uid、gid、rlimit等。此时,新运行的应用程序就已经启动完成了。新运行的应用程序由ZygoteInit类动态加载,共用装载到父进程生成虚拟机代码。并且,共应用程序FrameWork中的类及资源的链接信息,这大大加快了应用程序创建与启动的速度。
4.2 Home的启动
Activity的启动必然和ActivityManagerService的启动有关,下面是SystemServer执行init2()的相关源代码。
public static final void init2() {
//建立线程来处理
Thread thr = new ServerThread();
thr.setName("android.server.ServerThread");
thr.start();
}
//看看线程ServerThread里面都做了什么事情?
public void run() {
addBootEvent(new String("Android:SysServerInit_START"));
Looper.prepare();
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
//初始化服务,创建各种服务实例,如:电源、网络、Wifi、蓝牙,USB等,
//初始化完成以后加入到 ServiceManager中,
//事我们用 Context.getSystemService (String name) 才获取到相应的服务
PowerManagerService power = null;
NetworkManagementService networkManagement = null;
WifiP2pService wifiP2p = null;
WindowManagerService wm = null;
BluetoothService bluetooth = null;
UsbService usb = null;
NotificationManagerService notification = null;
StatusBarManagerService statusBar = null;
……
power = new PowerManagerService();
ServiceManager.addService(Context.POWER_SERVICE, power);
……
// ActivityManagerService作为ApplicationFramework最重要的服务
ActivityManagerService.setSystemProcess();
ActivityManagerService.installSystemProviders();
ActivityManagerService.self().setWindowManager(wm);
// We now tell the activity manager it is okay to run third party
// code. It will call back into us once it has gotten to the state
// where third party code can really run (but before it has actually
// started launching the initial applications), for us to complete our
// initialization.
//系统服务初始化准备就绪,通知各个模块
ActivityManagerService.self().systemReady(new Runnable() {
public void run() {
startSystemUi(contextF);
batteryF.systemReady();
networkManagementF.systemReady();
usbF.systemReady();
……
// It is now okay to let the various system services start their
// third party code...
ActivityManagerService.systemReady( );
appWidgetF.systemReady(safeMode);
wallpaperF.systemReady();
}
});
//
//BOOTPROF
addBootEvent(new String("Android:SysServerInit_END"));
Looper.loop();
}
从上面可以看出系统在启动完所有的Android服务后,做了这样一些动作,使用xxx.systemReady()通知各个服务,系统已经就绪。其中也包括ActivityManagerService.system-
Ready( )的回调。Home就是在ActivityManagerService.systemReady( )通知的过程建立的。
public void systemReady(final Runnable goingCallback) {
……
//ready callback
if (goingCallback != null)
goingCallback.run();
synchronized (this) {
// Start up initial activity.
// ActivityStack mMainStack;
mMainStack.resumeTopActivityLocked(null);
}
……
}
final boolean resumeTopActivityLocked(ActivityRecord prev) {
// Find the first activity that is not finishing.
ActivityRecord next = topRunningActivityLocked(null);
if (next == null) {
// There are no more activities! Let's just start up the
// Launcher...
if (mMainStack) {
//ActivityManagerService mService;
return mService.startHomeActivityLocked();
}
}
……
}
从上面分析得出HomeActivity在执行mService.startHomeAct-
ivityLocked后启动。Home界面启动,完成了整个Android启动流程。
5 结语
Android系统层次结构分别为应用程序层、应用层许框架层、系统运行库层、和Linux核心层四应用程序层、应用层许框架层、系统运行库层、和Linux核心层层。各层都有自己的功能,Linux核心层面向底层硬件,系统运行层支撑整个系统,应用层支撑应用程序层,应用程序层面向用户为用户提供良好的交互界面。本文即是在Linux核心层的基础之上出发,绕过硬件层简要的阐述了Android系统的启动过程。
关于这篇文章有很多地方加入了自己的理解,有很多不足之处望理解