Android应用程序进程启动过程的源代码分析(2)
Step 5.ZygoteInit.runSelectLoopMode 这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中: publicclassZygoteInit{ ...... /** *Runsthezygoteprocess'sselectloop.Acceptsnewconnectionsas *theyhappen,andreadscommandsfromconnectionsonespawn-request's *worthatatime. * *@throwsMethodAndArgsCallerinachildprocesswhenamain()should *beexecuted. */ privatestaticvoidrunSelectLoopMode()throwsMethodAndArgsCaller{ ArrayList<FileDescriptor>fds=newArrayList(); ArrayList<ZygoteConnection>peers=newArrayList(); FileDescriptor[]fdArray=newFileDescriptor[4]; fds.add(sServerSocket.getFileDescriptor()); peers.add(null); intloopCount=GC_LOOP_COUNT; while(true){ intindex; /* *Callgc()beforeweblockinselect(). *It'sworkthathastobedoneanyway,andit'sbetter *toavoidmakingeverychilddoit.Itwillalso *madvise()anyfreememoryasaside-effect. * *Don'tcalliteverytime,becausewalkingtheentire *heapisalotofoverheadtofreeafewhundredbytes. */ if(loopCount<=0){ gc(); loopCount=GC_LOOP_COUNT; }else{ loopCount--; } try{ fdArray=fds.toArray(fdArray); index=selectReadable(fdArray); }catch(IOExceptionex){ thrownewRuntimeException("Errorinselect()",ex); } if(index<0){ thrownewRuntimeException("Errorinselect()"); }elseif(index==0){ ZygoteConnectionnewPeer=acceptCommandPeer(); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); }else{ booleandone; done=peers.get(index).runOnce(); if(done){ peers.remove(index); fds.remove(index); } } } } ...... } 当Step 4将数据通过Socket接口发送出去后,就会下面这个语句: done=peers.get(index).runOnce(); 这里从peers.get(index)得到的是一个ZygoteConnection对象,表示一个Socket连接,因此,接下来就是调用ZygoteConnection.runOnce函数进一步处理了。 Step 6.ZygoteConnection.runOnce 这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中: classZygoteConnection{ ...... booleanrunOnce()throwsZygoteInit.MethodAndArgsCaller{ Stringargs[]; ArgumentsparsedArgs=null; FileDescriptor[]descriptors; try{ args=readArgumentList(); descriptors=mSocket.getAncillaryFileDescriptors(); }catch(IOExceptionex){ ...... returntrue; } ...... /**thestderrofthemostrecentrequest,ifavail*/ PrintStreamnewStderr=null; if(descriptors!=null&&descriptors.length>=3){ newStderr=newPrintStream( newFileOutputStream(descriptors[2])); } intpid; try{ parsedArgs=newArguments(args); applyUidSecurityPolicy(parsedArgs,peer); applyDebuggerSecurityPolicy(parsedArgs); applyRlimitSecurityPolicy(parsedArgs,peer); applyCapabilitiesSecurityPolicy(parsedArgs,peer); int[][]rlimits=null; if(parsedArgs.rlimits!=null){ rlimits=parsedArgs.rlimits.toArray(intArray2d); } pid=Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags,rlimits); }catch(IllegalArgumentExceptionex){ ...... }catch(ZygoteSecurityExceptionex){ ...... } if(pid==0){ //inchild handleChildProc(parsedArgs,descriptors,newStderr); //shouldneverhappen returntrue; }else{/*pid!=0*/ //inparent...pidof<0meansfailure returnhandleParentProc(pid,descriptors,parsedArgs); } } ...... } 真正创建进程的地方就是在这里了: pid=Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid, parsedArgs.gids,parsedArgs.debugFlags,rlimits); 有Linux开发经验的读者很容易看懂这个函数调用,这个函数会创建一个进程,而且有两个返回值,一个是在当前进程中返回的,一个是在新创建的进程中返回,即在当前进程的子进程中返回,在当前进程中的返回值就是新创建的子进程的pid值,而在子进程中的返回值是0。因为我们只关心创建的新进程的情况,因此,我们沿着子进程的执行路径继续看下去: if(pid==0){ //inchild handleChildProc(parsedArgs,descriptors,newStderr); //shouldneverhappen returntrue; }else{/*pid!=0*/ ...... } 这里就是调用handleChildProc函数了。 Step 7.ZygoteConnection.handleChildProc 这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中: classZygoteConnection{ ...... privatevoidhandleChildProc(ArgumentsparsedArgs, FileDescriptor[]descriptors,PrintStreamnewStderr) throwsZygoteInit.MethodAndArgsCaller{ ...... if(parsedArgs.runtimeInit){ RuntimeInit.zygoteInit(parsedArgs.remainingArgs); }else{ ...... } } ...... } 由于在前面的Step 3中,指定了"--runtime-init"参数,表示要为新创建的进程初始化运行时库,因此,这里的parseArgs.runtimeInit值为true,于是就继续执行RuntimeInit.zygoteInit进一步处理了。 Step 8.RuntimeInit.zygoteInit 这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中: publicclassRuntimeInit{ ...... publicstaticfinalvoidzygoteInit(String[]argv) throwsZygoteInit.MethodAndArgsCaller{ //TODO:Doingthishereworks,butitseemskindofarbitrary.Find //abetterplace.Thegoalistosetitupforapplications,butnot //toolslikeam. System.setOut(newAndroidPrintStream(Log.INFO,"System.out")); System.setErr(newAndroidPrintStream(Log.WARN,"System.err")); commonInit(); zygoteInitNative(); intcurArg=0; for(/*curArg*/;curArg<argv.length;curArg++){ Stringarg=argv[curArg]; if(arg.equals("--")){ curArg++; break; }elseif(!arg.startsWith("--")){ break; }elseif(arg.startsWith("--nice-name=")){ StringniceName=arg.substring(arg.indexOf('=')+1); Process.setArgV0(niceName); } } if(curArg==argv.length){ Slog.e(TAG,"MissingclassnameargumenttoRuntimeInit!"); //lettheprocessexit return; } //Remainingargumentsarepassedtothestartclass'sstaticmain StringstartClass=argv[curArg++]; String[]startArgs=newString[argv.length-curArg]; System.arraycopy(argv,curArg,startArgs,0,startArgs.length); invokeStaticMain(startClass,startArgs); } ...... } 这里有两个关键的函数调用,一个是zygoteInitNative函数调用,一个是invokeStaticMain函数调用,前者就是执行Binder驱动程序初始化的相关工作了,正是由于执行了这个工作,才使得进程中的Binder对象能够顺利地进行Binder进程间通信,而后一个函数调用,就是执行进程的入口函数,这里就是执行startClass类的main函数了,而这个startClass即是我们在Step 1中传进来的"android.app.ActivityThread"值,表示要执行android.app.ActivityThread类的main函数。 我们先来看一下zygoteInitNative函数的调用过程,然后再回到RuntimeInit.zygoteInit函数中来,看看它是如何调用android.app.ActivityThread类的main函数的。 step 9.RuntimeInit.zygoteInitNative 这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中: [java] view plain copy publicclassRuntimeInit{ ...... publicstaticfinalnativevoidzygoteInitNative(); ...... } 这里可以看出,函数zygoteInitNative是一个Native函数,实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中: [cpp] view plain copy staticvoidcom_android_internal_os_RuntimeInit_zygoteInit(JNIEnv*env,jobjectclazz) { gCurRuntime->onZygoteInit(); } 这里它调用了全局变量gCurRuntime的onZygoteInit函数,这个全局变量的定义在frameworks/base/core/jni/AndroidRuntime.cpp文件开头的地方: [cpp] view plain copy staticAndroidRuntime*gCurRuntime=NULL; 这里可以看出,它的类型为AndroidRuntime,它是在AndroidRuntime类的构造函数中初始化的,AndroidRuntime类的构造函数也是定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中: [cpp] view plain copy AndroidRuntime::AndroidRuntime() { ...... assert(gCurRuntime==NULL);//oneperprocess gCurRuntime=this; } 那么这个AndroidRuntime类的构造函数又是什么时候被调用的呢?AndroidRuntime类的声明在frameworks/base/include/android_runtime/AndroidRuntime.h文件中,如果我们打开这个文件会看到,它是一个虚拟类,也就是我们不能直接创建一个AndroidRuntime对象,只能用一个AndroidRuntime类的指针来指向它的某一个子类,这个子类就是AppRuntime了,它定义在frameworks/base/cmds/app_process/app_main.cpp文件中: [cpp] view plain copy intmain(intargc,constchar*constargv[]) { ...... AppRuntimeruntime; ...... } 而AppRuntime类继续了AndroidRuntime类,它也是定义在frameworks/base/cmds/app_process/app_main.cpp文件中: [cpp] view plain copy classAppRuntime:publicAndroidRuntime { ...... }; 因此,在前面的com_android_internal_os_RuntimeInit_zygoteInit函数,实际是执行了AppRuntime类的onZygoteInit函数。 本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/,如需转载请自行联系原作者