Android应用程序进程启动过程的源代码分析(2)

    Step 5. ZygoteInit.runSelectLoopMode
        这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
 
 
  1. public class ZygoteInit {   
  2.     ......   
  3.    
  4.     /**  
  5.     * Runs the zygote process's select loop. Accepts new connections as  
  6.     * they happen, and reads commands from connections one spawn-request's  
  7.     * worth at a time.  
  8.     *  
  9.     * @throws MethodAndArgsCaller in a child process when a main() should  
  10.     * be executed.  
  11.     */   
  12.     private static void runSelectLoopMode() throws MethodAndArgsCaller {   
  13.         ArrayList<FileDescriptor> fds = new ArrayList();   
  14.         ArrayList<ZygoteConnection> peers = new ArrayList();   
  15.         FileDescriptor[] fdArray = new FileDescriptor[4];   
  16.    
  17.         fds.add(sServerSocket.getFileDescriptor());   
  18.         peers.add(null);   
  19.    
  20.         int loopCount = GC_LOOP_COUNT;   
  21.         while (true) {   
  22.             int index;   
  23.             /*  
  24.             * Call gc() before we block in select().  
  25.             * It's work that has to be done anyway, and it's better  
  26.             * to avoid making every child do it.  It will also  
  27.             * madvise() any free memory as a side-effect.  
  28.             *  
  29.             * Don't call it every time, because walking the entire  
  30.             * heap is a lot of overhead to free a few hundred bytes.  
  31.             */   
  32.             if (loopCount <= 0) {   
  33.                 gc();   
  34.                 loopCount = GC_LOOP_COUNT;   
  35.             } else {   
  36.                 loopCount--;   
  37.             }   
  38.    
  39.    
  40.             try {   
  41.                 fdArray = fds.toArray(fdArray);   
  42.                 index = selectReadable(fdArray);   
  43.             } catch (IOException ex) {   
  44.                 throw new RuntimeException("Error in select()", ex);   
  45.             }   
  46.    
  47.             if (index < 0) {   
  48.                 throw new RuntimeException("Error in select()");   
  49.             } else if (index == 0) {   
  50.                 ZygoteConnection newPeer = acceptCommandPeer();   
  51.                 peers.add(newPeer);   
  52.                 fds.add(newPeer.getFileDesciptor());   
  53.             } else {   
  54.                 boolean done;   
  55.                 done = peers.get(index).runOnce();   
  56.    
  57.                 if (done) {   
  58.                     peers.remove(index);   
  59.                     fds.remove(index);   
  60.                 }   
  61.             }   
  62.         }   
  63.     }   
  64.    
  65.     ......   
  66. }   
        当Step 4将数据通过Socket接口发送出去后,就会下面这个语句:
 
 
  1. 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文件中:
 
 
  1. class ZygoteConnection {   
  2.     ......   
  3.    
  4.     boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {   
  5.         String args[];   
  6.         Arguments parsedArgs = null;   
  7.         FileDescriptor[] descriptors;   
  8.    
  9.         try {   
  10.             args = readArgumentList();   
  11.             descriptors = mSocket.getAncillaryFileDescriptors();   
  12.         } catch (IOException ex) {   
  13.             ......   
  14.             return true;   
  15.         }   
  16.    
  17.         ......   
  18.    
  19.         /** the stderr of the most recent request, if avail */   
  20.         PrintStream newStderr = null;   
  21.    
  22.         if (descriptors != null && descriptors.length >= 3) {   
  23.             newStderr = new PrintStream(   
  24.                 new FileOutputStream(descriptors[2]));   
  25.         }   
  26.    
  27.         int pid;   
  28.            
  29.         try {   
  30.             parsedArgs = new Arguments(args);   
  31.    
  32.             applyUidSecurityPolicy(parsedArgs, peer);   
  33.             applyDebuggerSecurityPolicy(parsedArgs);   
  34.             applyRlimitSecurityPolicy(parsedArgs, peer);   
  35.             applyCapabilitiesSecurityPolicy(parsedArgs, peer);   
  36.    
  37.             int[][] rlimits = null;   
  38.    
  39.             if (parsedArgs.rlimits != null) {   
  40.                 rlimits = parsedArgs.rlimits.toArray(intArray2d);   
  41.             }   
  42.    
  43.             pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,   
  44.                 parsedArgs.gids, parsedArgs.debugFlags, rlimits);   
  45.         } catch (IllegalArgumentException ex) {   
  46.             ......   
  47.         } catch (ZygoteSecurityException ex) {   
  48.             ......   
  49.         }   
  50.    
  51.         if (pid == 0) {   
  52.             // in child   
  53.             handleChildProc(parsedArgs, descriptors, newStderr);   
  54.             // should never happen   
  55.             return true;   
  56.         } else { /* pid != 0 */   
  57.             // in parent...pid of < 0 means failure   
  58.             return handleParentProc(pid, descriptors, parsedArgs);   
  59.         }   
  60.     }   
  61.    
  62.     ......   
  63. }   
 
      真正创建进程的地方就是在这里了:
 
 
  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,   
  2.     parsedArgs.gids, parsedArgs.debugFlags, rlimits);   
       有Linux开发经验的读者很容易看懂这个函数调用,这个函数会创建一个进程,而且有两个返回值,一个是在当前进程中返回的,一个是在新创建的进程中返回,即在当前进程的子进程中返回,在当前进程中的返回值就是新创建的子进程的pid值,而在子进程中的返回值是0。因为我们只关心创建的新进程的情况,因此,我们沿着子进程的执行路径继续看下去:
 
 
  1.    if (pid == 0) {   
  2. // in child   
  3. handleChildProc(parsedArgs, descriptors, newStderr);   
  4. // should never happen   
  5. return true;   
  6.    } else { /* pid != 0 */   
  7. ......   
  8.    }   
       这里就是调用handleChildProc函数了。
        Step 7. ZygoteConnection.handleChildProc
        这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java文件中:
 
 
  1. class ZygoteConnection {   
  2.     ......   
  3.    
  4.     private void handleChildProc(Arguments parsedArgs,   
  5.             FileDescriptor[] descriptors, PrintStream newStderr)   
  6.             throws ZygoteInit.MethodAndArgsCaller {   
  7.         ......   
  8.    
  9.         if (parsedArgs.runtimeInit) {   
  10.             RuntimeInit.zygoteInit(parsedArgs.remainingArgs);   
  11.         } else {   
  12.             ......   
  13.         }   
  14.     }   
  15.    
  16.     ......   
  17. }   
 
     由于在前面的Step 3中,指定了"--runtime-init"参数,表示要为新创建的进程初始化运行时库,因此,这里的parseArgs.runtimeInit值为true,于是就继续执行RuntimeInit.zygoteInit进一步处理了。
        Step 8. RuntimeInit.zygoteInit
        这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
  1. public class RuntimeInit {  
  2.     ......  
  3.   
  4.     public static final void zygoteInit(String[] argv)  
  5.             throws ZygoteInit.MethodAndArgsCaller {  
  6.         // TODO: Doing this here works, but it seems kind of arbitrary. Find  
  7.         // a better place. The goal is to set it up for applications, but not  
  8.         // tools like am.  
  9.         System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));  
  10.         System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));  
  11.   
  12.         commonInit();  
  13.         zygoteInitNative();  
  14.   
  15.         int curArg = 0;  
  16.         for ( /* curArg */ ; curArg < argv.length; curArg++) {  
  17.             String arg = argv[curArg];  
  18.   
  19.             if (arg.equals("--")) {  
  20.                 curArg++;  
  21.                 break;  
  22.             } else if (!arg.startsWith("--")) {  
  23.                 break;  
  24.             } else if (arg.startsWith("--nice-name=")) {  
  25.                 String niceName = arg.substring(arg.indexOf('=') + 1);  
  26.                 Process.setArgV0(niceName);  
  27.             }  
  28.         }  
  29.   
  30.         if (curArg == argv.length) {  
  31.             Slog.e(TAG, "Missing classname argument to RuntimeInit!");  
  32.             // let the process exit  
  33.             return;  
  34.         }  
  35.   
  36.         // Remaining arguments are passed to the start class's static main  
  37.   
  38.         String startClass = argv[curArg++];  
  39.         String[] startArgs = new String[argv.length - curArg];  
  40.   
  41.         System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);  
  42.         invokeStaticMain(startClass, startArgs);  
  43.     }  
  44.   
  45.     ......  
  46. }  
        这里有两个关键的函数调用,一个是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
  1. public class RuntimeInit {  
  2.     ......  
  3.   
  4.     public static final native void zygoteInitNative();  
  5.   
  6.     ......  
  7. }  
        这里可以看出,函数zygoteInitNative是一个Native函数,实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
 
 
[cpp]  view plain copy
  1. static void com_android_internal_os_RuntimeInit_zygoteInit(JNIEnv* env, jobject clazz)  
  2. {  
  3.     gCurRuntime->onZygoteInit();  
  4. }  
 
        这里它调用了全局变量gCurRuntime的onZygoteInit函数,这个全局变量的定义在frameworks/base/core/jni/AndroidRuntime.cpp文件开头的地方:
 
[cpp]  view plain copy
  1. static AndroidRuntime* gCurRuntime = NULL;  
        这里可以看出,它的类型为AndroidRuntime,它是在AndroidRuntime类的构造函数中初始化的,AndroidRuntime类的构造函数也是定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
 
 
[cpp]  view plain copy
  1. AndroidRuntime::AndroidRuntime()  
  2. {  
  3.     ......  
  4.   
  5.     assert(gCurRuntime == NULL);        // one per process  
  6.     gCurRuntime = this;  
  7. }  
        那么这个AndroidRuntime类的构造函数又是什么时候被调用的呢?AndroidRuntime类的声明在frameworks/base/include/android_runtime/AndroidRuntime.h文件中,如果我们打开这个文件会看到,它是一个虚拟类,也就是我们不能直接创建一个AndroidRuntime对象,只能用一个AndroidRuntime类的指针来指向它的某一个子类,这个子类就是AppRuntime了,它定义在frameworks/base/cmds/app_process/app_main.cpp文件中:
 
 
[cpp]  view plain copy
  1. int main(int argc, const charconst argv[])  
  2. {  
  3.     ......  
  4.   
  5.     AppRuntime runtime;  
  6.       
  7.     ......  
  8. }  
        而AppRuntime类继续了AndroidRuntime类,它也是定义在frameworks/base/cmds/app_process/app_main.cpp文件中:
[cpp]  view plain copy
  1. class AppRuntime : public AndroidRuntime  
  2. {  
  3.     ......  
  4.   
  5. };  
        因此,在前面的com_android_internal_os_RuntimeInit_zygoteInit函数,实际是执行了AppRuntime类的onZygoteInit函数。
 
 
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值