service zygote/system/bin/app_process -Xzygote /system/bin --zygote--start-system-server classmain socketzygote stream 666 onrestartwrite /sys/android_power/request_state wake onrestartwrite /sys/power/state on onrestartrestart media onrestartrestart netd |
以上是在init.rc中定义了一个名称为zygote的服务,首先第一行中使用service指令告诉操作系统将zygote程序加入到系统服务中,service的语法如下:
service service_name 可执行程序的路径 可执行程序自身所需的参数列表 |
此处的服务被定义为zygote,理论上讲该服务的名称可以是任意的。可执行程序的路径正是/system/bin/app_process,参数一共包含四个,分别如下:
Ø -Xzygote,该参数将作为虚拟机启动时所需要的参数,是在AndroidRuntime.cpp类的startVm()函数中调用JNI_CreateJavaVM()时被使用的。
Ø /system/bin,代表虚拟机程序所在目录,因为app_process完全可以不和虚拟机在同一个目录,而在app_process内部的AndroidRuntime类内部需要知道虚拟机所在的目录。
Ø --zygote,指明以ZygoteInit类作为虚拟机执行的入口,如果没有--zygote参数,则需要明确指定需要执行的类名。
Ø --start-system-server,仅在指定--zygote参数时才有效,意思是告知ZygoteInit启动完毕后孵化出第一个进程SystemServer。
接下来的配置命令socket用于指定该服务所使用到的socket,后面的参数依次是名称、类型、端口地址。onrestart命令指定该服务重启的条件,即当满足这些条件后,zygote服务就需要重启,这些条件一般是一些系统异常条件。
System/core/init/init.c里定义了一个main函数,是android启动的入口,之后解析init.rc中定义的服务
Zygote本身是一个Native应用程序,根据上一节可知,它是由Init进程根据init.rc文件中的配置项来创建的。
程序入口:frameworks/base/cmds/app_process/app_main.cpp
int main(int argc,const char* const argv[]) { while(i < argc) { constchar* 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; }else { className= arg; break; } } runtime.mParentDir= parentDir; if(zygote) { runtime.start("com.android.internal.os.ZygoteInit",start-system-server); } |
这个main函数主要是解析init.rc传进来的参数,最重要的功能是由AppRuntime的start方法来完成。
AppRuntime类的声明和实现都在App_main.cpp中,是由AndroidRuntime类派生出来的,并且重载了onStarted、onZygoteInit和onExit函数。入口:
AndroidRuntime.start("com.android.internal.os.ZygoteInit","start-system-server")
voidAndroidRuntime::start(const char* className, const char*options) { //创建虚拟机 JNIEnv*env; if(startVm(&mJavaVM,&env) != 0) { return; } //注册JNI函数 if (startReg(env) <0) { LOGE("Unableto register all android natives\n"); return; } …….
char* slashClassName =toSlashClassName(className); jclassstartClass =env->FindClass(slashClassName); if(startClass == NULL) { LOGE("JavaVMunable to locate class '%s'\n", slashClassName); }else { jmethodIDstartMeth = env->GetStaticMethodID(startClass,"main", "([Ljava/lang/String;)V"); if(startMeth == NULL) { LOGE("JavaVMunable to find main() in '%s'\n", className); }else { env->CallStaticVoidMethod(startClass,startMeth, strArray); } }
} |
通过以上代码分析,AndroidRuntime.start()方法主要是为了进入java世界做准备,分为三件事情:
Ø 创建虚拟机——startVm。调用JNI的虚拟机创建函数,其参数都是在startVm中确定的。
Ø 注册JNI函数——startReg。Java世界用到的一些函数是采用native方式实现的,所以需要给虚拟机注册这些函数。
Ø 进入java世界的入口。调用env->CallStaticVoidMethod(startClass,startMeth, strArray)进入java世界,这个JNI调用的意义是,调用com.android.internal.os.ZygoteInit java类的main函数,传递的参数是
“com.android.internal.os.ZygoteInit start-system-server”。
由上一小节可知,CallStaticVoidMethod最终调用com.android.internal.os.ZygoteInit的main函数。
public static voidmain(String argv[]) { registerZygoteSocket(); preload(); if(argv[1].equals("start-system-server")) { startSystemServer(); } if(ZYGOTE_FORK_MODE) { runForkMode(); }else { runSelectLoopMode(); } closeServerSocket(); } |
以上列出ZygoteInit类main函数几个重要的处理函数,其主要完成了4大关键点:
1、 注册Socket服务端——registerZygoteSocket
private static voidregisterZygoteSocket() { if(sServerSocket == null) { intfileDesc; try{ Stringenv = System.getenv(ANDROID_SOCKET_ENV); fileDesc= Integer.parseInt(env); }catch (RuntimeException ex) { thrownew RuntimeException( ANDROID_SOCKET_ENV+ " unset or invalid", ex); } try{ sServerSocket= new LocalServerSocket( createFileDescriptor(fileDesc)); }catch (IOException ex) { thrownew RuntimeException( "Errorbinding to local socket '" + fileDesc + "'", ex); } } } |
Zygote及系统中其他程序的通信没有使用Binder通信,而是采用了基于AF_UNIX类型的Socket通信,以上代码就是注册Socket通信的服务端,用于监听客户端发过来的消息。
2、 预加载类和资源
Preload()方法完成预加载类和资源,其中调用preloadClassed()预加载类,调用preloadResources预加载资源。
Ø preloadClassed
在frameworks/base目录中有一个名为“preloaded-classes”的文件,罗列出所有需要加载的类,是有framework/base/tools/preload工具生成的。
Ø preloadResources
主要加载framework-res.apk中的资源。
3、 启动system_server进程
private static booleanstartSystemServer() throwsMethodAndArgsCaller, RuntimeException { intpid; try{
pid= Zygote.forkSystemServer( parsedArgs.uid,parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); }catch (IllegalArgumentExceptionex) { thrownew RuntimeException(ex); }
if(pid == 0) { handleSystemServerProcess(parsedArgs); } returntrue; } |
这里创建了java世界中系统service所在的进程system_server,该进程是framework的核心,如果它死了,就会导致zygote自杀。通过调用Zygote.forkSystemServer这个函数创建出system_server进程,其工作是在handleSystemServerProcess(parsedArgs)方法中。
4、 等待客户端请求——runSelectLoopMode
private static voidrunSelectLoopMode() throws MethodAndArgsCaller { while(true) { fds.add(sServerSocket.getFileDescriptor()); try{ fdArray= fds.toArray(fdArray); index= selectReadable(fdArray); }catch (IOException ex) { thrownew RuntimeException("Error in select()", ex); } if(index < 0) { thrownew RuntimeException("Error in select()"); }else if (index == 0) { ZygoteConnectionnewPeer = acceptCommandPeer(); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); }else { booleandone= peers.get(index).runOnce(); } } } |
sServerSocket是第1点中在registerZygoteSocket中建立的Socket,selectReadable内部调用select,当客户端连接或有数据时,selectReadable就会有返回。客户端在Zygote的代表是ZygoteConnection,当有一个客户端连接上的时候index==0,当客户端发送请求的时候,index>0,后续处理由ZygoteConnection.runOnce()完成.
由第二节介绍可知,在ZygoteInit中调用native函数Zygote.forkSystemServer()创建的的进程。
SystemServer创建后,就与Zygote区分开来,有了自己的使命:
pid=Zygote.forkSystemServer() if (pid == 0){ handleSystemServerProcess(parsedArgs); } |
调用handleSystemServerProcess来完成自己的工作。
privatestatic void handleSystemServerProcess( ZygoteConnection.ArgumentsparsedArgs) throwsZygoteInit.MethodAndArgsCaller { closeServerSocket(); RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs); } } |
调用closeServerSocket()关闭从Zygote那里继承下来的Socket,接着调用RuntimeInit.zygoteInit,再接着调用RuntimeInit.invokeStaticMain方法去调用com.android.server.SystemServer的main函数,这才是SystemServer的真面目:
publicstatic void main(String[] args) { …… //加载libandroid_servers.so库 System.loadLibrary("android_servers"); //调用native的init1函数 init1(args); } |
其中main函数将加载libandroid_servers.so库,这个库所包含的源码文件在文件夹framwork/base/services/jni下。
Ø init1分析
init1是native函数,在com_android_server_SystemServer.cpp中实现,其主要工作是创建一些系统服务,然后把调用线程加入到Binder通信中。期间还通过JNI调用了com.android.server.SystemServer类中的init2函数。
Ø init2分析
publicstatic final void init2() { Threadthr = new ServerThread(); thr.setName("android.server.ServerThread"); thr.start(); } |
启动了一个serverThread线程,用以启动系统各项重要服务,例如启动电源管理服务、电池管理服务、windowManager服务、ActivityManager服务等,总之,系统各项重要的服务都在这里被启动。
Zygote创建出system_server后,就通过runSelectLoopMode等待并处理来自客户端的消息。我们以创建一个Activity的启动为例,具体分析Zygote是如何分裂和繁殖的。
ActivityManagerService是由System_server创建的。假设通过startActivity来启动一个新的Activity,并且它不属于一个未启动的进程,从ActivityManagerService中的startProcessLocked函数看,代码如下所示:
[àActivityManagerService.java]
privatefinal void startProcessLocked(ProcessRecord app, StringhostingType, String hostingNameStr) { …… Process.ProcessStartResult startResult =Process.start("android.app.ActivityThread", app.processName,uid, uid, gids, debugFlags, app.info.targetSdkVersion,null); ……. } |
Process类是android提供的,并非JDK的Process类,是android.os.Process,start函数代码如下:
[àProcess.java]
publicstatic final ProcessStartResult start(final StringprocessClass, finalString niceName, intuid, int gid, int[] gids, intdebugFlags, int targetSdkVersion, String[]zygoteArgs) { return startViaZygote(processClass,niceName, uid, gid, gids, debugFlags,targetSdkVersion, zygoteArgs); ….. } |
[àProcess.java::startViaZygote()]
privatestatic ProcessStartResult startViaZygote(final StringprocessClass, finalString niceName, finalint uid, final int gid, finalint[] gids, intdebugFlags, int targetSdkVersion, String[]extraArgs) throwsZygoteStartFailedEx { argsForZygote.add("--runtime-init");//一些参数设置 argsForZygote.add("--setuid="+ uid); argsForZygote.add("--setgid="+ gid); …… return zygoteSendArgsAndGetResult(argsForZygote); } } |
[àProcess.java:: zygoteSendArgsAndGetResult()]
privatestatic ProcessStartResultzygoteSendArgsAndGetResult(ArrayList<String>args) throwsZygoteStartFailedEx { //打开与Zygote通信的Socket openZygoteSocketIfNeeded(); //把请求参数发送到Zygote sZygoteWriter.write(Integer.toString(args.size())); sZygoteWriter.newLine(); …… sZygoteWriter.write(arg); sZygoteWriter.newLine(); } //等待Zygote处理结束,获取创建进程的pid sZygoteWriter.flush(); ProcessStartResultresult = new ProcessStartResult(); result.pid= sZygoteInputStream.readInt(); if(result.pid < 0) { thrownew ZygoteStartFailedEx("fork() failed"); } result.usingWrapper= sZygoteInputStream.readBoolean(); returnresult; } |
[àZygoteInit.java:: runSelectLoopMode()]
private static voidrunSelectLoopMode() throws MethodAndArgsCaller { while(true) { fds.add(sServerSocket.getFileDescriptor()); try{ fdArray= fds.toArray(fdArray); index= selectReadable(fdArray); }catch (IOException ex) { thrownew RuntimeException("Error in select()", ex); } }else if (index == 0) { ZygoteConnectionnewPeer = acceptCommandPeer(); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); }else { booleandone= peers.get(index).runOnce(); } } } |
每当有请求数据发来,Zygote就会用ZygoteConnetion的runOnce函数处理数据:
[àZygoteConnetion.java:: runOnce()]
booleanrunOnce() throws ZygoteInit.MethodAndArgsCaller { args= readArgumentList(); descriptors= mSocket.getAncillaryFileDescriptors(); ….. parsedArgs= new Arguments(args); ….. pid= Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags, rlimits); ….. if(pid == 0) { IoUtils.closeQuietly(serverPipeFd); serverPipeFd= null; handleChildProc(parsedArgs,descriptors, childPipeFd, newStderr); returntrue; }else { returnhandleParentProc(pid, descriptors, serverPipeFd,parsedArgs); }
} |
调用readArgumentList()读取System_server发送过来的参数,然后调用Zygote.forkAndSpecialize()创一个子进程,接着调用handleChidProc进行子进程的处理,其实就是要创建Activity对应的子进程。
[àZygoteConnetion.java:: handleChildProc()]
privatevoid handleChildProc(Arguments parsedArgs, FileDescriptor[]descriptors, FileDescriptor pipeFd, PrintStreamnewStderr) throwsZygoteInit.MethodAndArgsCaller { if (parsedArgs.runtimeInit) { RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs); } } |
RuntimeInit.zygoteInit()大家应该熟悉了,在创建System_server的时候用到。这里也一样,调用RuntimeInit.zygoteInit()之后,再调用RuntimeInit. invokeStaticMain去执行android.app.ActivityThread类的main函数,这也就是apk程序对应的main函数。