Android系统进程Zygote启动过程的源代码分析
声明:
RTFSC(Read the fucking source code)是Linus的名言,也是学习IT技术一个重要手段。学习android最好手段就是对android进行系统分析,关于android系统的源码,CSDN的老罗分析分析是最系统一个。但是老罗的分析源码的blog,有几点不够好:
1.废话太多,可能考虑太多的小白读者,可以谅解。
2.分析结果一般都一文字形式存在于博文内部,对于一些急需结论的用户,笔者将分析后结果提前了。
3.老罗blog有些讲的不全的地方,笔者有补充,但建议读老罗的blog, 原汁原味。
4.本blog更多以监督自己学习为主,需要看官监督下,才能有心继续。
5.每篇文章都标明文章出处,尊重老罗的辛勤输出,我只是一个二次传播者
在android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,这也许就是为什么要把它称为Zygote(受精卵)的原因吧。Zygote进程的启动是又是由android的系统进程init解析init.rc文件来启动的。系统启动脚本system/core/rootdir/init.rc文件中,我们可以看到启动Zygote进程的脚本命令:
3.onrestart关键字: 表示这个zygote进程重启时需要执行的命令。
关于init.rc文件的更多信息,请参考system/core/init/readme.txt文件。
分析结论:
1. init进程通过解析init.rc启动Zygote进程, Zygote进程会完成以工作
2. 启动虚拟机(ART或者Dalivk)
3. 创建一个名ANDROID_SOCKET_zygote机的服务Socket. 这个socket用于AMS的请求Zygote 创建一个Android应用程序的进程。
4. 启动SystemServer进程,SystemServer进程回启动android系统中各种服务,其中比较重要的AMS, PMS。 在SystemServer中会关闭Socket, 因为android系统的组件和SystemServer不在使用Socket机制,而是使用Binder机制。
5. Zygote进程进入循环等待Socket连接状态。 一旦AMS有请求Zygote进程请求创建一个android 应用程序进程, 就会调用ZygoteConnection.runOnce。
分析过程:
Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。在分析Zygote进程启动的过程之前,我们先来看看它的启动序列图,从总体流程看看Zygote启动进程简单过程。

下面我们就详细分析每一个步骤。
Step 1. app_process.main 这个函数定义在frameworks/base/cmds/app_process/app_main.cpp
int main(int argc,constchar*const argv[]){// These are global variables in ProcessState.cppAppRuntime runtime;.....// Next arg is parent directoryif(i < argc){runtime.mParentDir = argv[i++];}// Next arg is startup classname or "--zygote"if(i < argc){arg = argv[i++];if(0== strcmp("--zygote", arg)){bool startSystemServer =(i < argc)?strcmp(argv[i],"--start-system-server")==0:false;setArgv0(argv0,"zygote");set_process_name("zygote");runtime.start("com.android.internal.os.ZygoteInit",startSystemServer);}else{......}}}
runtime.start("com.android.internal.os.ZygoteInit",startSystemServer);
Step 2. AndroidRuntime.start : frameworks/base/core/jni/AndroidRuntime.cpp plain
/** Start the Android runtime. This involves starting the virtual machine* and calling the "static void main(String[] args)" method in the class* named by "className".** Passes the main function two arguments, the class name and the specified* options string.*/voidAndroidRuntime::start(constchar* className,constchar* options){- ....
/* start the virtual machine */JNIEnv* env;if(startVm(&mJavaVM,&env)!=0){return;}onVmCreated(env);/** Register android functions.*/if(startReg(env)<0){LOGE("Unable to register all android natives ");return;}/** We want to call main() with a String array with arguments in it.* At present we have two arguments, the class name and an option string.* Create an array to hold them.*/jclass stringClass;jobjectArray strArray;jstring classNameStr;jstring optionsStr;stringClass = env->FindClass("java/lang/String");assert(stringClass != NULL);strArray = env->NewObjectArray(2, stringClass, NULL);assert(strArray != NULL);classNameStr = env->NewStringUTF(className);assert(classNameStr != NULL);env->SetObjectArrayElement(strArray,0, classNameStr);optionsStr = env->NewStringUTF(options);env->SetObjectArrayElement(strArray,1, optionsStr);/** Start VM. This thread becomes the main thread of the VM, and will* not return until the VM exits.*/char* slashClassName = toSlashClassName(className);jclass startClass = env->FindClass(slashClassName);if(startClass == NULL){LOGE("JavaVM unable to locate class '%s' ", slashClassName);/* keep going */}else{jmethodID startMeth = env->GetStaticMethodID(startClass,"main","([Ljava/lang/String;)V");if(startMeth == NULL){LOGE("JavaVM unable to find main() in '%s' ", className);/* keep going */}else{env->CallStaticVoidMethod(startClass, startMeth, strArray);}}free(slashClassName);}
这个函数的作用是启动Android系统运行时库,它主要做了三件事情,
1.一是调用函数startVM启动虚拟机(这个会在稍后虚拟机源码分析源码系列讲解)
2.二是调用函数startReg注册JNI方法 (建立android系统,Java层-Native层之间的联系)
3.三是调用了com.android.internal.os.ZygoteInit类的main函数。
Step 3. ZygoteInit.main : frameworks/base/core/Java/com/android/internal/os/ZygoteInit.java
publicclassZygoteInit{......publicstaticvoid main(String argv[]){try{......registerZygoteSocket();............if(argv[1].equals("true")){startSystemServer();}elseif(!argv[1].equals("false")){......}......if(ZYGOTE_FORK_MODE){......}else{runSelectLoopMode();}......}catch(MethodAndArgsCaller caller){......}catch(RuntimeException ex){......}}......}view plai copy
publicclassZygoteInit{......privatestaticfinalString ANDROID_SOCKET_ENV ="ANDROID_SOCKET_zygote";/*** Registers a server socket for zygote command connections** @throws RuntimeException when open fails*/privatestaticvoid registerZygoteSocket(){if(sServerSocket ==null){int fileDesc;try{String env =System.getenv(ANDROID_SOCKET_ENV);fileDesc =Integer.parseInt(env);}catch(RuntimeException ex){......}try{sServerSocket =newLocalServerSocket(createFileDescriptor(fileDesc));}catch(IOException ex){.......}}}......}view plain co
view pStep 5. ZygoteInit.startSystemServer:frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
publicclassZygoteInit{......privatestaticboolean startSystemServer()throwsMethodAndArgsCaller,RuntimeException{/* Hardcoded command line to start the system server */String args[]={"--setuid=1000","--setgid=1000","--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003","--capabilities=130104352,130104352","--runtime-init","--nice-name=system_server","com.android.server.SystemServer",};ZygoteConnection.Arguments parsedArgs =null;int pid;try{parsedArgs =newZygoteConnection.Arguments(args);....../* Request to fork the system server process */pid =Zygote.forkSystemServer(parsedArgs.uid, parsedArgs.gid,parsedArgs.gids, debugFlags,null,parsedArgs.permittedCapabilities,parsedArgs.effectiveCapabilities);}catch(IllegalArgumentException ex){......}/* For child process */if(pid ==0){handleSystemServerProcess(parsedArgs);}returntrue;}......}view plain cop
Step 6. ZygoteInit.handleSystemServerProcess 这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
publicclassZygoteInit{......privatestaticvoid handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)throwsZygoteInit.MethodAndArgsCaller{closeServerSocket();/** Pass the remaining arguments to SystemServer.* "--nice-name=system_server com.android.server.SystemServer"*/RuntimeInit.zygoteInit(parsedArgs.remainingArgs);/* should never reach here */}......}view plain cop
Step 7. RuntimeInit.zygoteInit 这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
publicclassRuntimeInit{......publicstaticfinalvoid zygoteInit(String[] argv)throwsZygoteInit.MethodAndArgsCaller{......zygoteInitNative();......// Remaining arguments are passed to the start class's static mainString startClass = argv[curArg++];String[] startArgs =newString[argv.length - curArg];System.arraycopy(argv, curArg, startArgs,0, startArgs.length);invokeStaticMain(startClass, startArgs);}......}
Step 8. RuntimeInit.zygoteInitNative 这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
Step 9. SystemServer.main : frameworks/base/services/java/com/android/server/SystemServer.java
publicclassSystemServer{......nativepublicstaticvoid init1(String[] args);......publicstaticvoid main(String[] args){......init1(args);......}publicstaticfinalvoid init2(){Slog.i(TAG,"Entered the Android system server!");Thread thr =newServerThread();thr.setName("android.server.ServerThread");thr.start();}......}view plain cop
Step 10. ZygoteInit.runSelectLoopMode : frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
publicclassZygoteInit{......privatestaticvoid runSelectLoopMode()throwsMethodAndArgsCaller{ArrayList<FileDescriptor> fds =newArrayList();ArrayList<ZygoteConnection> peers =newArrayList();FileDescriptor[] fdArray =newFileDescriptor[4];fds.add(sServerSocket.getFileDescriptor());peers.add(null);int loopCount = GC_LOOP_COUNT;while(true){int index;......try{fdArray = fds.toArray(fdArray);index = selectReadable(fdArray);}catch(IOException ex){thrownewRuntimeException("Error in select()", ex);}if(index <0){thrownewRuntimeException("Error in select()");}elseif(index ==0){ZygoteConnection newPeer =();peers.add(newPeer);fds.add(newPeer.getFileDesciptor());}else{boolean done;done = peers.get(index).runOnce();if(done){peers.remove(index);fds.remove(index);}}}}......}view plai co
关于笔者:
