Android系統進程Zygote啓動過程的源代碼分析

 原文地址:http://blog.csdn.net/luoshengyang/article/details/6747696java

 

Android應用程序框架層建立的應用程序進程具備兩個特色,一是進程的入口函數是ActivityThread.main,二是進程自然支持Binder進程間通訊機制;這兩個特色都是在進程的初始化過程當中實現的,本文將詳細分析Android應用程序進程建立過程當中是如何實現這兩個特色的。android

        Android應用程序框架層建立的應用程序進程的入口函數是ActivityThread.main比較好理解,即進程建立完成以後,Android應用程序框架層就會在這個進程中將ActivityThread類加載進來,而後執行它的main函數,這個main函數就是進程執行消息循環的地方了。Android應用程序框架層建立的應用程序進程自然支持Binder進程間通訊機制這個特色應該怎麼樣理解呢?前面咱們在學習Android系統的Binder進程間通訊機制時說到,它具備四個組件,分別是驅動程序、守護進程、Client以及Server,其中Server組件在初始化時必須進入一個循環中不斷地與Binder驅動程序進行到交互,以便得到Client組件發送的請求,具體可參考Android系統進程間通訊(IPC)機制Binder中的Server啓動過程源代碼分析一文,可是,當咱們在Android應用程序中實現Server組件的時候,咱們並無讓進程進入一個循環中去等待Client組件的請求,然而,當Client組件獲得這個Server組件的遠程接口時,卻能夠順利地和Server組件進行進程間通訊,這就是由於Android應用程序進程在建立的時候就已經啓動了一個線程池來支持Server組件和Binder驅動程序之間的交互了,這樣,極大地方便了在Android應用程序中建立Server組件。app

        在Android應用程序框架層中,是由ActivityManagerService組件負責爲Android應用程序建立新的進程的,它原本也是運行在一個獨立的進程之中,不過這個進程是在系統啓動的過程當中建立的。ActivityManagerService組件通常會在什麼狀況下會爲應用程序建立一個新的進程呢?當系統決定要在一個新的進程中啓動一個Activity或者Service時,它就會建立一個新的進程了,而後在這個新的進程中啓動這個Activity或者Service,具體能夠參考Android系統在新進程中啓動自定義服務過程(startService)的原理分析Android應用程序啓動過程源代碼分析Android應用程序在新的進程中啓動新的Activity的方法和過程分析這三篇文章。框架

        ActivityManagerService啓動新的進程是從其成員函數startProcessLocked開始的,在深刻分析這個過程以前,咱們先來看一下進程建立過程的序列圖,而後再詳細分析每個步驟。socket

       點擊查看大圖ide

        Step 1. ActivityManagerService.startProcessLocked函數

        這個函數定義在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:oop

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. public final class ActivityManagerService extends ActivityManagerNative    
  2.         implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {    
  3.     
  4.     ......    
  5.     
  6.     private final void startProcessLocked(ProcessRecord app,    
  7.                 String hostingType, String hostingNameStr) {    
  8.     
  9.         ......    
  10.     
  11.         try {    
  12.             int uid = app.info.uid;    
  13.             int[] gids = null;    
  14.             try {    
  15.                 gids = mContext.getPackageManager().getPackageGids(    
  16.                     app.info.packageName);    
  17.             } catch (PackageManager.NameNotFoundException e) {    
  18.                 ......    
  19.             }    
  20.                 
  21.             ......    
  22.     
  23.             int debugFlags = 0;    
  24.                 
  25.             ......    
  26.                 
  27.             int pid = Process.start("android.app.ActivityThread",    
  28.                 mSimpleProcessManagement ? app.processName : null, uid, uid,    
  29.                 gids, debugFlags, null);    
  30.                 
  31.             ......    
  32.     
  33.         } catch (RuntimeException e) {    
  34.                 
  35.             ......    
  36.     
  37.         }    
  38.     }    
  39.     
  40.     ......    
  41.     
  42. }    

        它調用了Process.start函數開始爲應用程序建立新的進程,注意,它傳入一個第一個參數爲"android.app.ActivityThread",這就是進程初始化時要加載的Java類了,把這個類加載到進程以後,就會把它裏面的靜態成員函數main做爲進程的入口點,後面咱們會看到。學習

 

        Step 2. Process.start ui

        這個函數定義在frameworks/base/core/java/android/os/Process.java文件中:

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. public class Process {  
  2.     ......  
  3.   
  4.     public static final int start(final String processClass,  
  5.         final String niceName,  
  6.         int uid, int gid, int[] gids,  
  7.         int debugFlags,  
  8.         String[] zygoteArgs)  
  9.     {  
  10.         if (supportsProcesses()) {  
  11.             try {  
  12.                 return startViaZygote(processClass, niceName, uid, gid, gids,  
  13.                     debugFlags, zygoteArgs);  
  14.             } catch (ZygoteStartFailedEx ex) {  
  15.                 ......  
  16.             }  
  17.         } else {  
  18.             ......  
  19.   
  20.             return 0;  
  21.         }  
  22.     }  
  23.   
  24.     ......  
  25. }  

       這裏的supportsProcesses函數返回值爲true,它是一個Native函數,實如今frameworks/base/core/jni/android_util_Process.cpp文件中:

 

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. jboolean android_os_Process_supportsProcesses(JNIEnv* env, jobject clazz)  
  2. {  
  3.     return ProcessState::self()->supportsProcesses();  
  4. }  

 

       ProcessState::supportsProcesses函數定義在frameworks/base/libs/binder/ProcessState.cpp文件中:

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. bool ProcessState::supportsProcesses() const  
  2. {  
  3.     return mDriverFD >= 0;  
  4. }  

       這裏的mDriverFD是設備文件/dev/binder的打開描述符,若是成功打開了這個設備文件,那麼它的值就會大於等於0,所以,它的返回值爲true。

 

       回到Process.start函數中,它調用startViaZygote函數進一步操做。

       Step 3. Process.startViaZygote

       這個函數定義在frameworks/base/core/java/android/os/Process.java文件中:

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. public class Process {  
  2.     ......  
  3.   
  4.     private static int startViaZygote(final String processClass,  
  5.             final String niceName,  
  6.             final int uid, final int gid,  
  7.             final int[] gids,  
  8.             int debugFlags,  
  9.             String[] extraArgs)  
  10.             throws ZygoteStartFailedEx {  
  11.         int pid;  
  12.   
  13.         synchronized(Process.class) {  
  14.             ArrayList<String> argsForZygote = new ArrayList<String>();  
  15.   
  16.             // --runtime-init, --setuid=, --setgid=,  
  17.             // and --setgroups= must go first  
  18.             argsForZygote.add("--runtime-init");  
  19.             argsForZygote.add("--setuid=" + uid);  
  20.             argsForZygote.add("--setgid=" + gid);  
  21.             if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {  
  22.                 argsForZygote.add("--enable-safemode");  
  23.             }  
  24.             if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {  
  25.                 argsForZygote.add("--enable-debugger");  
  26.             }  
  27.             if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {  
  28.                 argsForZygote.add("--enable-checkjni");  
  29.             }  
  30.             if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {  
  31.                 argsForZygote.add("--enable-assert");  
  32.             }  
  33.   
  34.             //TODO optionally enable debuger  
  35.             //argsForZygote.add("--enable-debugger");  
  36.   
  37.             // --setgroups is a comma-separated list  
  38.             if (gids != null && gids.length > 0) {  
  39.                 StringBuilder sb = new StringBuilder();  
  40.                 sb.append("--setgroups=");  
  41.   
  42.                 int sz = gids.length;  
  43.                 for (int i = 0; i < sz; i++) {  
  44.                     if (i != 0) {  
  45.                         sb.append(',');  
  46.                     }  
  47.                     sb.append(gids[i]);  
  48.                 }  
  49.   
  50.                 argsForZygote.add(sb.toString());  
  51.             }  
  52.   
  53.             if (niceName != null) {  
  54.                 argsForZygote.add("--nice-name=" + niceName);  
  55.             }  
  56.   
  57.             argsForZygote.add(processClass);  
  58.   
  59.             if (extraArgs != null) {  
  60.                 for (String arg : extraArgs) {  
  61.                     argsForZygote.add(arg);  
  62.                 }  
  63.             }  
  64.   
  65.             pid = zygoteSendArgsAndGetPid(argsForZygote);  
  66.         }  
  67.     }  
  68.   
  69.     ......  
  70. }  

        這個函數將建立進程的參數放到argsForZygote列表中去,如參數"--runtime-init"表示要爲新建立的進程初始化運行時庫,而後調用zygoteSendAndGetPid函數進一步操做。

 

        Step 4. Process.zygoteSendAndGetPid

        這個函數定義在frameworks/base/core/java/android/os/Process.java文件中:

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. public class Process {  
  2.     ......  
  3.   
  4.     private static int zygoteSendArgsAndGetPid(ArrayList<String> args)  
  5.             throws ZygoteStartFailedEx {  
  6.         int pid;  
  7.   
  8.         openZygoteSocketIfNeeded();  
  9.   
  10.         try {  
  11.             /** 
  12.             * See com.android.internal.os.ZygoteInit.readArgumentList() 
  13.             * Presently the wire format to the zygote process is: 
  14.             * a) a count of arguments (argc, in essence) 
  15.             * b) a number of newline-separated argument strings equal to count 
  16.             * 
  17.             * After the zygote process reads these it will write the pid of 
  18.             * the child or -1 on failure. 
  19.             */  
  20.   
  21.             sZygoteWriter.write(Integer.toString(args.size()));  
  22.             sZygoteWriter.newLine();  
  23.   
  24.             int sz = args.size();  
  25.             for (int i = 0; i < sz; i++) {  
  26.                 String arg = args.get(i);  
  27.                 if (arg.indexOf('\n') >= 0) {  
  28.                     throw new ZygoteStartFailedEx(  
  29.                         "embedded newlines not allowed");  
  30.                 }  
  31.                 sZygoteWriter.write(arg);  
  32.                 sZygoteWriter.newLine();  
  33.             }  
  34.   
  35.             sZygoteWriter.flush();  
  36.   
  37.             // Should there be a timeout on this?  
  38.             pid = sZygoteInputStream.readInt();  
  39.   
  40.             if (pid < 0) {  
  41.                 throw new ZygoteStartFailedEx("fork() failed");  
  42.             }  
  43.         } catch (IOException ex) {  
  44.             ......  
  45.         }  
  46.   
  47.         return pid;  
  48.     }  
  49.   
  50.     ......  
  51. }  

         這裏的sZygoteWriter是一個Socket寫入流,是由openZygoteSocketIfNeeded函數打開的:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. public class Process {  
  2.     ......  
  3.   
  4.     /** 
  5.     * Tries to open socket to Zygote process if not already open. If 
  6.     * already open, does nothing.  May block and retry. 
  7.     */  
  8.     private static void openZygoteSocketIfNeeded()  
  9.             throws ZygoteStartFailedEx {  
  10.   
  11.         int retryCount;  
  12.   
  13.         if (sPreviousZygoteOpenFailed) {  
  14.             /* 
  15.             * If we've failed before, expect that we'll fail again and 
  16.             * don't pause for retries. 
  17.             */  
  18.             retryCount = 0;  
  19.         } else {  
  20.             retryCount = 10;  
  21.         }  
  22.       
  23.         /* 
  24.         * See bug #811181: Sometimes runtime can make it up before zygote. 
  25.         * Really, we'd like to do something better to avoid this condition, 
  26.         * but for now just wait a bit... 
  27.         */  
  28.         for (int retry = 0  
  29.             ; (sZygoteSocket == null) && (retry < (retryCount + 1))  
  30.             ; retry++ ) {  
  31.   
  32.                 if (retry > 0) {  
  33.                     try {  
  34.                         Log.i("Zygote", "Zygote not up yet, sleeping...");  
  35.                         Thread.sleep(ZYGOTE_RETRY_MILLIS);  
  36.                     } catch (InterruptedException ex) {  
  37.                         // should never happen  
  38.                     }  
  39.                 }  
  40.   
  41.                 try {  
  42.                     sZygoteSocket = new LocalSocket();  
  43.                     sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,  
  44.                         LocalSocketAddress.Namespace.RESERVED));  
  45.   
  46.                     sZygoteInputStream  
  47.                         = new DataInputStream(sZygoteSocket.getInputStream());  
  48.   
  49.                     sZygoteWriter =  
  50.                         new BufferedWriter(  
  51.                         new OutputStreamWriter(  
  52.                         sZygoteSocket.getOutputStream()),  
  53.                         256);  
  54.   
  55.                     Log.i("Zygote", "Process: zygote socket opened");  
  56.   
  57.                     sPreviousZygoteOpenFailed = false;  
  58.                     break;  
  59.                 } catch (IOException ex) {  
  60.                     ......  
  61.                 }  
  62.         }  
  63.   
  64.         ......  
  65.     }  
  66.   
  67.     ......  
  68. }  

        這個Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit類在runSelectLoopMode函數偵聽的。
        Step 5. ZygoteInit.runSelectLoopMode
        這個函數定義在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  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接口發送出去後,就會下面這個語句:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  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文件中:

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  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. }  

         真正建立進程的地方就是在這裏了:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,  
  2.     parsedArgs.gids, parsedArgs.debugFlags, rlimits);  

        有Linux開發經驗的讀者很容易看懂這個函數調用,這個函數會建立一個進程,並且有兩個返回值,一個是在當前進程中返回的,一個是在新建立的進程中返回,即在當前進程的子進程中返回,在當前進程中的返回值就是新建立的子進程的pid值,而在子進程中的返回值是0。由於咱們只關心建立的新進程的狀況,所以,咱們沿着子進程的執行路徑繼續看下去:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  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文件中:

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  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文件中:

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  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 在CODE上查看代碼片 派生到個人代碼片
 
  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 在CODE上查看代碼片 派生到個人代碼片
 
  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 在CODE上查看代碼片 派生到個人代碼片
 
  1. static AndroidRuntime* gCurRuntime = NULL;  

        這裏能夠看出,它的類型爲AndroidRuntime,它是在AndroidRuntime類的構造函數中初始化的,AndroidRuntime類的構造函數也是定義在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

 

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  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 在CODE上查看代碼片 派生到個人代碼片
 
  1. int main(int argc, const char* const argv[])  
  2. {  
  3.     ......  
  4.   
  5.     AppRuntime runtime;  
  6.       
  7.     ......  
  8. }  

        而AppRuntime類繼續了AndroidRuntime類,它也是定義在frameworks/base/cmds/app_process/app_main.cpp文件中:

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. class AppRuntime : public AndroidRuntime  
  2. {  
  3.     ......  
  4.   
  5. };  

        所以,在前面的com_android_internal_os_RuntimeInit_zygoteInit函數,實際是執行了AppRuntime類的onZygoteInit函數。

 

        Step 10. AppRuntime.onZygoteInit
        這個函數定義在frameworks/base/cmds/app_process/app_main.cpp文件中:

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. class AppRuntime : public AndroidRuntime  
  2. {  
  3.     ......  
  4.   
  5.     virtual void onZygoteInit()  
  6.     {  
  7.         sp<ProcessState> proc = ProcessState::self();  
  8.         if (proc->supportsProcesses()) {  
  9.             LOGV("App process: starting thread pool.\n");  
  10.             proc->startThreadPool();  
  11.         }  
  12.     }  
  13.   
  14.     ......  
  15. };  

        這裏它就是調用ProcessState::startThreadPool啓動線程池了,這個線程池中的線程就是用來和Binder驅動程序進行交互的了。
        Step 11. ProcessState.startThreadPool
        這個函數定義在frameworks/base/libs/binder/ProcessState.cpp文件中:

 

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. void ProcessState::startThreadPool()  
  2. {  
  3.     AutoMutex _l(mLock);  
  4.     if (!mThreadPoolStarted) {  
  5.         mThreadPoolStarted = true;  
  6.         spawnPooledThread(true);  
  7.     }  
  8. }  

        ProcessState類是Binder進程間通訊機制的一個基礎組件,它的做用能夠參考淺談Android系統進程間通訊(IPC)機制Binder中的Server和Client得到Service Manager接口之路Android系統進程間通訊(IPC)機制Binder中的Server啓動過程源代碼分析Android系統進程間通訊(IPC)機制Binder中的Client得到Server遠程接口過程源代碼分析這三篇文章。這裏它調用spawnPooledThread函數進一步處理。

 

        Step 12. ProcessState.spawnPooledThread

        這個函數定義在frameworks/base/libs/binder/ProcessState.cpp文件中:

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. void ProcessState::spawnPooledThread(bool isMain)  
  2. {  
  3.     if (mThreadPoolStarted) {  
  4.         int32_t s = android_atomic_add(1, &mThreadPoolSeq);  
  5.         char buf[32];  
  6.         sprintf(buf, "Binder Thread #%d", s);  
  7.         LOGV("Spawning new pooled thread, name=%s\n", buf);  
  8.         sp<Thread> t = new PoolThread(isMain);  
  9.         t->run(buf);  
  10.     }  
  11. }  

        這裏它會建立一個PoolThread線程類,而後執行它的run函數,最終就會執行PoolThread類的threadLoop函數了。

 

        Step 13. PoolThread.threadLoop

        這個函數定義在frameworks/base/libs/binder/ProcessState.cpp文件中:

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. class PoolThread : public Thread  
  2. {  
  3. public:  
  4.     PoolThread(bool isMain)  
  5.         : mIsMain(isMain)  
  6.     {  
  7.     }  
  8.   
  9. protected:  
  10.     virtual bool threadLoop()  
  11.     {  
  12.         IPCThreadState::self()->joinThreadPool(mIsMain);  
  13.         return false;  
  14.     }  
  15.   
  16.     const bool mIsMain;  
  17. };  

        這裏它執行了IPCThreadState::joinThreadPool函數進一步處理。IPCThreadState也是Binder進程間通訊機制的一個基礎組件,它的做用能夠參考淺談Android系統進程間通訊(IPC)機制Binder中的Server和Client得到Service Manager接口之路Android系統進程間通訊(IPC)機制Binder中的Server啓動過程源代碼分析Android系統進程間通訊(IPC)機制Binder中的Client得到Server遠程接口過程源代碼分析這三篇文章。

 

        Step 14. IPCThreadState.joinThreadPool

        這個函數定義在frameworks/base/libs/binder/IPCThreadState.cpp文件中:

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. void IPCThreadState::joinThreadPool(bool isMain)  
  2. {  
  3.     ......  
  4.   
  5.     mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);  
  6.   
  7.     ......  
  8.   
  9.     status_t result;  
  10.     do {  
  11.         int32_t cmd;  
  12.   
  13.         ......  
  14.   
  15.         // now get the next command to be processed, waiting if necessary  
  16.         result = talkWithDriver();  
  17.         if (result >= NO_ERROR) {  
  18.             size_t IN = mIn.dataAvail();  
  19.             if (IN < sizeof(int32_t)) continue;  
  20.             cmd = mIn.readInt32();  
  21.             ......  
  22.   
  23.             result = executeCommand(cmd);  
  24.         }  
  25.   
  26.         ......  
  27.     } while (result != -ECONNREFUSED && result != -EBADF);  
  28.   
  29.     ......  
  30.       
  31.     mOut.writeInt32(BC_EXIT_LOOPER);  
  32.     talkWithDriver(false);  
  33. }  

        這個函數首先告訴Binder驅動程序,這條線程要進入循環了:

 

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);  

        而後在中間的while循環中經過talkWithDriver不斷與Binder驅動程序進行交互,以便得到Client端的進程間調用:

 

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. result = talkWithDriver();  

        得到了Client端的進程間調用後,就調用excuteCommand函數來處理這個請求:

 

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. result = executeCommand(cmd);  

        最後,線程退出時,也會告訴Binder驅動程序,它退出了,這樣Binder驅動程序就不會再在Client端的進程間調用分發給它了:

 

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. mOut.writeInt32(BC_EXIT_LOOPER);  
  2. talkWithDriver(false);  

        咱們再來看看talkWithDriver函數的實現。

 

        Step 15. talkWithDriver

        這個函數定義在frameworks/base/libs/binder/IPCThreadState.cpp文件中:

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. status_t IPCThreadState::talkWithDriver(bool doReceive)  
  2. {  
  3.     ......  
  4.   
  5.     binder_write_read bwr;  
  6.   
  7.     // Is the read buffer empty?  
  8.     const bool needRead = mIn.dataPosition() >= mIn.dataSize();  
  9.   
  10.     // We don't want to write anything if we are still reading  
  11.     // from data left in the input buffer and the caller  
  12.     // has requested to read the next data.  
  13.     const size_t outAvail = (!doReceive || needRead) ? mOut.dataSize() : 0;  
  14.   
  15.     bwr.write_size = outAvail;  
  16.     bwr.write_buffer = (long unsigned int)mOut.data();  
  17.   
  18.     // This is what we'll read.  
  19.     if (doReceive && needRead) {  
  20.         bwr.read_size = mIn.dataCapacity();  
  21.         bwr.read_buffer = (long unsigned int)mIn.data();  
  22.     } else {  
  23.         bwr.read_size = 0;  
  24.     }  
  25.   
  26.     ......  
  27.   
  28.     // Return immediately if there is nothing to do.  
  29.     if ((bwr.write_size == 0) && (bwr.read_size == 0)) return NO_ERROR;  
  30.   
  31.     bwr.write_consumed = 0;  
  32.     bwr.read_consumed = 0;  
  33.     status_t err;  
  34.     do {  
  35.         ......  
  36. #if defined(HAVE_ANDROID_OS)  
  37.         if (ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr) >= 0)  
  38.             err = NO_ERROR;  
  39.         else  
  40.             err = -errno;  
  41. #else  
  42.         err = INVALID_OPERATION;  
  43. #endif  
  44.         ......  
  45.         }  
  46.     } while (err == -EINTR);  
  47.   
  48.     ....  
  49.   
  50.     if (err >= NO_ERROR) {  
  51.         if (bwr..write_consumed > 0) {  
  52.             if (bwr.write_consumed < (ssize_t)mOut.dataSize())  
  53.                 mOut.remove(0, bwr.write_consumed);  
  54.             else  
  55.                 mOut.setDataSize(0);  
  56.         }  
  57.         if (bwr.read_consumed > 0) {  
  58.             mIn.setDataSize(bwr.read_consumed);  
  59.             mIn.setDataPosition(0);  
  60.         }  
  61.         ......  
  62.         return NO_ERROR;  
  63.     }  
  64.   
  65.     return err;  
  66. }  

        這個函數的具體做用能夠參考Android系統進程間通訊(IPC)機制Binder中的Server啓動過程源代碼分析一文,它只要就是經過ioctl文件操做函數來和Binder驅動程序交互的了:

 

 

[cpp]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. ioctl(mProcess->mDriverFD, BINDER_WRITE_READ, &bwr)  

        有了這個線程池以後,咱們在開發Android應用程序的時候,當咱們要和其它進程中進行通訊時,只要定義本身的Binder對象,而後把這個Binder對象的遠程接口經過其它途徑傳給其它進程後,其它進程就能夠經過這個Binder對象的遠程接口來調用咱們的應用程序進程的函數了,它不像咱們在C++層實現Binder進程間通訊機制的Server時,必需要手動調用IPCThreadState.joinThreadPool函數來進入一個無限循環中與Binder驅動程序交互以便得到Client端的請求,這樣就實現了咱們在文章開頭處說的Android應用程序進程自然地支持Binder進程間通訊機制。

 

        細心的讀者可能會發現,從Step 1到Step 9,都是在Android應用程序框架層運行的,而從Step 10到Step 15,都是在Android系統運行時庫層運行的,這兩個層次中的Binder進程間通訊機制的接口一個是用Java來實現的,而別一個是用C++來實現的,這二者是如何協做的呢?這就是經過JNI層來實現的了,具體能夠參考Android系統進程間通訊Binder機制在應用程序框架層的Java接口源代碼分析一文。

        回到Step 8中的RuntimeInit.zygoteInit函數中,在初始化完成Binder進程間通訊機制的基礎設施後,它接着就要進入進程的入口函數了。

        Step 16. RuntimeInit.invokeStaticMain

        這個函數定義在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. public class ZygoteInit {  
  2.     ......  
  3.   
  4.     static void invokeStaticMain(ClassLoader loader,  
  5.             String className, String[] argv)  
  6.             throws ZygoteInit.MethodAndArgsCaller {  
  7.         Class<?> cl;  
  8.   
  9.         try {  
  10.             cl = loader.loadClass(className);  
  11.         } catch (ClassNotFoundException ex) {  
  12.             ......  
  13.         }  
  14.   
  15.         Method m;  
  16.         try {  
  17.             m = cl.getMethod("main", new Class[] { String[].class });  
  18.         } catch (NoSuchMethodException ex) {  
  19.             ......  
  20.         } catch (SecurityException ex) {  
  21.             ......  
  22.         }  
  23.   
  24.         int modifiers = m.getModifiers();  
  25.         ......  
  26.   
  27.         /* 
  28.         * This throw gets caught in ZygoteInit.main(), which responds 
  29.         * by invoking the exception's run() method. This arrangement 
  30.         * clears up all the stack frames that were required in setting 
  31.         * up the process. 
  32.         */  
  33.         throw new ZygoteInit.MethodAndArgsCaller(m, argv);  
  34.     }  
  35.   
  36.     ......  
  37. }  

        前面咱們說過,這裏傳進來的參數className字符串值爲"android.app.ActivityThread",這裏就通ClassLoader.loadClass函數將它加載到進程中:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. cl = loader.loadClass(className);  

        而後得到它的靜態成員函數main:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. m = cl.getMethod("main", new Class[] { String[].class });  

        函數最後並無直接調用這個靜態成員函數main,而是經過拋出一個異常ZygoteInit.MethodAndArgsCaller,而後讓ZygoteInit.main函數在捕獲這個異常的時候再調用android.app.ActivityThread類的main函數。爲何要這樣作呢?註釋裏面已經講得很清楚了,它是爲了清理堆棧的,這樣就會讓android.app.ActivityThread類的main函數以爲本身是進程的入口函數,而事實上,在執行android.app.ActivityThread類的main函數以前,已經作了大量的工做了。

 

        咱們看看ZygoteInit.main函數在捕獲到這個異常的時候作了什麼事:

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. public class ZygoteInit {  
  2.     ......  
  3.   
  4.     public static void main(String argv[]) {  
  5.         try {  
  6.             ......  
  7.         } catch (MethodAndArgsCaller caller) {  
  8.             caller.run();  
  9.         } catch (RuntimeException ex) {  
  10.             ......  
  11.         }  
  12.     }  
  13.   
  14.     ......  
  15. }  

        它執行MethodAndArgsCaller的run函數:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. public class ZygoteInit {  
  2.     ......  
  3.   
  4.     public static class MethodAndArgsCaller extends Exception  
  5.             implements Runnable {  
  6.         /** method to call */  
  7.         private final Method mMethod;  
  8.   
  9.         /** argument array */  
  10.         private final String[] mArgs;  
  11.   
  12.         public MethodAndArgsCaller(Method method, String[] args) {  
  13.             mMethod = method;  
  14.             mArgs = args;  
  15.         }  
  16.   
  17.         public void run() {  
  18.             try {  
  19.                 mMethod.invoke(null, new Object[] { mArgs });  
  20.             } catch (IllegalAccessException ex) {  
  21.                 ......  
  22.             } catch (InvocationTargetException ex) {  
  23.                 ......  
  24.             }  
  25.         }  
  26.     }  
  27.   
  28.     ......  
  29. }  

        這裏的成員變量mMethod和mArgs都是在前面構造異常對象時傳進來的,這裏的mMethod就對應android.app.ActivityThread類的main函數了,因而最後就經過下面語句執行這個函數:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. mMethod.invoke(null, new Object[] { mArgs });  

        這樣,android.app.ActivityThread類的main函數就被執行了。

 

        Step 17. ActivityThread.main

        這個函數定義在frameworks/base/core/java/android/app/ActivityThread.java文件中:

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. public final class ActivityThread {  
  2.     ......  
  3.   
  4.     public static final void main(String[] args) {  
  5.         SamplingProfilerIntegration.start();  
  6.   
  7.         Process.setArgV0("<pre-initialized>");  
  8.   
  9.         Looper.prepareMainLooper();  
  10.         if (sMainThreadHandler == null) {  
  11.             sMainThreadHandler = new Handler();  
  12.         }  
  13.   
  14.         ActivityThread thread = new ActivityThread();  
  15.         thread.attach(false);  
  16.   
  17.         if (false) {  
  18.             Looper.myLooper().setMessageLogging(new  
  19.                 LogPrinter(Log.DEBUG, "ActivityThread"));  
  20.         }  
  21.         Looper.loop();  
  22.   
  23.         if (Process.supportsProcesses()) {  
  24.             throw new RuntimeException("Main thread loop unexpectedly exited");  
  25.         }  
  26.   
  27.         thread.detach();  
  28.         String name = (thread.mInitialApplication != null)  
  29.             ? thread.mInitialApplication.getPackageName()  
  30.             : "<unknown>";  
  31.         Slog.i(TAG, "Main thread of " + name + " is now exiting");  
  32.     }  
  33.   
  34.     ......  
  35. }  

        從這裏咱們能夠看出,這個函數首先會在進程中建立一個ActivityThread對象:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. ActivityThread thread = new ActivityThread();  

        而後進入消息循環中:

 

 

[java]  view plain copy 在CODE上查看代碼片 派生到個人代碼片
 
  1. Looper.loop();  

        這樣,咱們之後就能夠在這個進程中啓動Activity或者Service了。

 

        至此,Android應用程序進程啓動過程的源代碼就分析完成了,它除了指定新的進程的入口函數是ActivityThread的main函數以外,還爲進程內的Binder對象提供了Binder進程間通訊機制的基礎設施,因而可知,Binder進程間通訊機制在Android系統中是何等的重要,並且是無處不在,想進一步學習Android系統的Binder進程間通訊機制,請參考Android進程間通訊(IPC)機制Binder簡要介紹和學習計劃一文。

相關文章
相關標籤/搜索