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函数。
 




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/,如需转载请自行联系原作者

目录
相关文章
|
1月前
|
搜索推荐 Android开发 iOS开发
安卓与iOS系统的用户界面设计对比分析
本文通过对安卓和iOS两大操作系统的用户界面设计进行对比分析,探讨它们在设计理念、交互方式、视觉风格等方面的差异及各自特点,旨在帮助读者更好地理解和评估不同系统的用户体验。
22 1
|
2月前
|
Android开发 数据安全/隐私保护 iOS开发
安卓与iOS系统的发展趋势与比较分析
【2月更文挑战第6天】 在移动互联网时代,安卓和iOS系统作为两大主流移动操作系统,各自呈现出不同的发展趋势。本文将从技术角度出发,对安卓和iOS系统的发展方向、特点及未来趋势进行比较分析,以期为读者提供更深入的了解和思考。
36 4
|
3月前
|
监控 Android开发 C语言
深度解读Android崩溃日志案例分析2:tombstone日志
深度解读Android崩溃日志案例分析2:tombstone日志
86 0
|
4天前
|
存储 Java Android开发
Android系统 设置第三方应用为默认Launcher实现和原理分析
Android系统 设置第三方应用为默认Launcher实现和原理分析
18 0
|
4天前
|
Android开发
Android源代码定制:Overlay目录定制|调试Overlay资源是否生效
Android源代码定制:Overlay目录定制|调试Overlay资源是否生效
11 0
|
4天前
|
存储 Java Linux
Android系统获取event事件回调等几种实现和原理分析
Android系统获取event事件回调等几种实现和原理分析
25 0
|
4天前
|
Android开发
Android源代码定制:添加customize.mk文件进行分项目和分客户的定制
Android源代码定制:添加customize.mk文件进行分项目和分客户的定制
2 0
|
24天前
|
安全 Linux API
Android进程与线程
Android进程与线程
18 0
|
2月前
|
网络协议 算法 Android开发
安卓逆向 -- 实战某峰窝APP(动态分析)
安卓逆向 -- 实战某峰窝APP(动态分析)
32 4
|
2月前
|
安全 搜索推荐 Android开发
Android 与 iOS 的比较分析
【2月更文挑战第5天】 Android 和 iOS 是目前市场上两种最流行的移动操作系统,它们都拥有自己的特点和优势。本文将会分别从操作系统设计、应用生态、安全性等方面对这两种操作系统进行比较和分析,希望能够帮助读者更好地选择适合自己的移动设备。

相关实验场景

更多