Android应用程序进程启动过程的源代码分析(2)
16lz
2021-01-23
Step 5.ZygoteInit.runSelectLoopMode
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
当Step 4将数据通过Socket接口发送出去后,就会下面这个语句:
- 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);
- }
- }
- }
- }
- ......
- }
这里从peers.get(index)得到的是一个ZygoteConnection对象,表示一个Socket连接,因此,接下来就是调用ZygoteConnection.runOnce函数进一步处理了。 Step 6.ZygoteConnection.runOnce 这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:
- done=peers.get(index).runOnce();
真正创建进程的地方就是在这里了:
- 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);
- }
- }
- ......
- }
有Linux开发经验的读者很容易看懂这个函数调用,这个函数会创建一个进程,而且有两个返回值,一个是在当前进程中返回的,一个是在新创建的进程中返回,即在当前进程的子进程中返回,在当前进程中的返回值就是新创建的子进程的pid值,而在子进程中的返回值是0。因为我们只关心创建的新进程的情况,因此,我们沿着子进程的执行路径继续看下去:
- pid=Zygote.forkAndSpecialize(parsedArgs.uid,parsedArgs.gid,
- parsedArgs.gids,parsedArgs.debugFlags,rlimits);
这里就是调用handleChildProc函数了。 Step 7.ZygoteConnection.handleChildProc
- if(pid==0){
- //inchild
- handleChildProc(parsedArgs,descriptors,newStderr);
- //shouldneverhappen
- returntrue;
- }else{/*pid!=0*/
- ......
- }
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:
由于在前面的Step 3中,指定了"--runtime-init"参数,表示要为新创建的进程初始化运行时库,因此,这里的parseArgs.runtimeInit值为true,于是就继续执行RuntimeInit.zygoteInit进一步处理了。 Step 8.RuntimeInit.zygoteInit 这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
- classZygoteConnection{
- ......
- privatevoidhandleChildProc(ArgumentsparsedArgs,
- FileDescriptor[]descriptors,PrintStreamnewStderr)
- throwsZygoteInit.MethodAndArgsCaller{
- ......
- if(parsedArgs.runtimeInit){
- RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
- }else{
- ......
- }
- }
- ......
- }
- 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);
- }
- ......
- }
- publicclassRuntimeInit{
- ......
- publicstaticfinalnativevoidzygoteInitNative();
- ......
- }
- staticvoidcom_android_internal_os_RuntimeInit_zygoteInit(JNIEnv*env,jobjectclazz)
- {
- gCurRuntime->onZygoteInit();
- }
- staticAndroidRuntime*gCurRuntime=NULL;
- AndroidRuntime::AndroidRuntime()
- {
- ......
- assert(gCurRuntime==NULL);//oneperprocess
- gCurRuntime=this;
- }
- intmain(intargc,constchar*constargv[])
- {
- ......
- AppRuntimeruntime;
- ......
- }
- classAppRuntime:publicAndroidRuntime
- {
- ......
- };
更多相关文章
- C语言函数以及函数的使用
- android:向手机卡上写入文件时总是不成功,解决办法
- 在android中使用HttpURLConnection进行文件上传
- Android系统进程Zygote启动过程的源代码分析(3)
- 转:Android文件操作总结
- 【Android的从零单排开发日记】之入门篇(十)——Android应用配置文
- [Android Studio] Android Studio如何提示函数用法
- 关于android单元测试结合SAX解析xml文件初步分析
- Android 进程和线程模型 .