Android 应用程序进程启动过程源码分析

 

Android 应用程序进程启动过程源码分析

分类: 【Android 系统分析】   246人阅读  评论(0)  收藏  举报

目录(?)[+]

application process startup,  activity native thread will call activitmanagerservice to attach application.

在Zygote进程启动过程的源代码分析一文中介绍到,Zygote是java世界的开创者,所有的java应用进程都是通过Zygote孵化出来的。我们知道在Android应用程序框架层中,ActivityManagerService组件负责管理Android应用程序的创建,ActivityManagerService也是运行在独立的进程SystemServer中,SystemServer进程启动过程源码分析中介绍了SystemServer进程是如果通过开启线程来启动各种服务,ActivityManagerService也是System Server启动的服务之一。


ActivityManagerService请求创建应用程序进程


当系统决定要在一个新的进程中启动一个Activity或者Service时,它就会创建一个新的进程,ActivityManagerService通过调用startProcessLocked函数来为应用程序启动新的进程。

frameworks\base\services\java\com\android\server\am\ActivityManagerService.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. final ProcessRecord startProcessLocked(String processName,  
  2.         ApplicationInfo info, boolean knownToBeDead, int intentFlags,  
  3.         String hostingType, ComponentName hostingName, boolean allowWhileBooting,  
  4.         boolean isolated) {  
  5.     ProcessRecord app;  
  6.     //是否在现有进程中启动  
  7.     if (!isolated) {  
  8.         //从现有进程表mProcessNames中查找相应的进程描述符ProcessRecord  
  9.         app = getProcessRecordLocked(processName, info.uid);  
  10.     } else {  
  11.         // If this is an isolated process, it can't re-use an existing process.  
  12.         app = null;  
  13.     }  
  14.     // We don't have to do anything more if:  
  15.     // (1) There is an existing application record; and  
  16.     // (2) The caller doesn't think it is dead, OR there is no thread  
  17.     //     object attached to it so we know it couldn't have crashed; and  
  18.     // (3) There is a pid assigned to it, so it is either starting or  
  19.     //     already running.  
  20.     if (DEBUG_PROCESSES) Slog.v(TAG, "startProcess: name=" + processName  
  21.             + " app=" + app + " knownToBeDead=" + knownToBeDead  
  22.             + " thread=" + (app != null ? app.thread : null)  
  23.             + " pid=" + (app != null ? app.pid : -1));  
  24.     if (app != null && app.pid > 0) {  
  25.         if (!knownToBeDead || app.thread == null) {  
  26.             // We already have the app running, or are waiting for it to  
  27.             // come up (we have a pid but not yet its thread), so keep it.  
  28.             if (DEBUG_PROCESSES) Slog.v(TAG, "App already running: " + app);  
  29.             // If this is a new package in the process, add the package to the list  
  30.             app.addPackage(info.packageName);  
  31.             return app;  
  32.         } else {  
  33.             // An application record is attached to a previous process,  
  34.             // clean it up now.  
  35.             if (DEBUG_PROCESSES) Slog.v(TAG, "App died: " + app);  
  36.             handleAppDiedLocked(app, truetrue);  
  37.         }  
  38.     }  
  39.     String hostingNameStr = hostingName != null  
  40.             ? hostingName.flattenToShortString() : null;  
  41.     if (!isolated) {  
  42.         if ((intentFlags&Intent.FLAG_FROM_BACKGROUND) != 0) {  
  43.             // If we are in the background, then check to see if this process  
  44.             // is bad.  If so, we will just silently fail.  
  45.             if (mBadProcesses.get(info.processName, info.uid) != null) {  
  46.                 if (DEBUG_PROCESSES) Slog.v(TAG, "Bad process: " + info.uid  
  47.                         + "/" + info.processName);  
  48.                 return null;  
  49.             }  
  50.         } else {  
  51.             // When the user is explicitly starting a process, then clear its  
  52.             // crash count so that we won't make it bad until they see at  
  53.             // least one crash dialog again, and make the process good again  
  54.             // if it had been bad.  
  55.             if (DEBUG_PROCESSES) Slog.v(TAG, "Clearing bad process: " + info.uid  
  56.                     + "/" + info.processName);  
  57.             mProcessCrashTimes.remove(info.processName, info.uid);  
  58.             if (mBadProcesses.get(info.processName, info.uid) != null) {  
  59.                 EventLog.writeEvent(EventLogTags.AM_PROC_GOOD, info.uid,info.processName);  
  60.                 mBadProcesses.remove(info.processName, info.uid);  
  61.                 if (app != null) {  
  62.                     app.bad = false;  
  63.                 }  
  64.             }  
  65.         }  
  66.     }  
  67.   
  68.     if (app == null) {  
  69.         //在ActivityManagerService中为新进程创建一个ProcessRecord实例  
  70.         app = newProcessRecordLocked(null, info, processName, isolated);  
  71.         if (app == null) {  
  72.             Slog.w(TAG, "Failed making new process record for "  
  73.                     + processName + "/" + info.uid + " isolated=" + isolated);  
  74.             return null;  
  75.         }  
  76.         //添加到进程列表中  
  77.         mProcessNames.put(processName, app.uid, app);  
  78.         //如果当前服务运行在独立进程中,添加到独立进程表mIsolatedProcesses中  
  79.         /** 
  80.          * SparseArray<ProcessRecord> mIsolatedProcesses = new SparseArray<ProcessRecord>(); 
  81.          * The currently running isolated processes. 
  82.          */  
  83.         if (isolated) {  
  84.             mIsolatedProcesses.put(app.uid, app);  
  85.         }  
  86.     } else {  
  87.         // If this is a new package in the process, add the package to the list  
  88.         app.addPackage(info.packageName);  
  89.     }  
  90.     // If the system is not ready yet, then hold off on starting this  
  91.     // process until it is.  
  92.     if (!mProcessesReady && !isAllowedWhileBooting(info) && !allowWhileBooting) {  
  93.         /** 
  94.          * final ArrayList<ProcessRecord> mProcessesOnHold = new ArrayList<ProcessRecord>(); 
  95.          * List of records for processes that someone had tried to start before the 
  96.          * system was ready.  We don't start them at that point, but ensure they 
  97.          * are started by the time booting is complete. 
  98.          */  
  99.         if (!mProcessesOnHold.contains(app)) {  
  100.             mProcessesOnHold.add(app);  
  101.         }  
  102.         if (DEBUG_PROCESSES) Slog.v(TAG, "System not ready, putting on hold: " + app);  
  103.         return app;  
  104.     }  
  105.     //调用startProcessLocked启动新的应用程序进程  
  106.     startProcessLocked(app, hostingType, hostingNameStr);  
  107.     return (app.pid != 0) ? app : null;  
  108. }  
在该函数里,首先在ActivityManagerService中为即将创建的新应用程序进程创建一个ProcessRecord对象,并保存到mProcessNames进程列表中,然后调用另一个重载函数startProcessLocked来请求创建一个新的应用程序进程。

frameworks\base\services\java\com\android\server\am\ActivityManagerService.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private final void startProcessLocked(ProcessRecord app,  
  2.         String hostingType, String hostingNameStr) {  
  3.     if (app.pid > 0 && app.pid != MY_PID) {  
  4.         synchronized (mPidsSelfLocked) {  
  5.             mPidsSelfLocked.remove(app.pid);  
  6.             mHandler.removeMessages(PROC_START_TIMEOUT_MSG, app);  
  7.         }  
  8.         app.pid = 0;  
  9.     }  
  10.     //系统准备好了,马上启动服务,因此如果mProcessesOnHold列表中包含当前启动的服务,则需移除  
  11.     if (DEBUG_PROCESSES && mProcessesOnHold.contains(app)) Slog.v(TAG,  
  12.             "startProcessLocked removing on hold: " + app);  
  13.     mProcessesOnHold.remove(app);  
  14.     //唤醒进程信息收集线程  
  15.     updateCpuStats();  
  16.     System.arraycopy(mProcDeaths, 0, mProcDeaths, 1, mProcDeaths.length-1);  
  17.     mProcDeaths[0] = 0;  
  18.     try {  
  19.         int uid = app.uid;  
  20.         int[] gids = null;  
  21.         if (!app.isolated) {  
  22.             try {  
  23.                 gids = mContext.getPackageManager().getPackageGids(  
  24.                         app.info.packageName);  
  25.             } catch (PackageManager.NameNotFoundException e) {  
  26.                 Slog.w(TAG, "Unable to retrieve gids", e);  
  27.             }  
  28.         }  
  29.         if (mFactoryTest != SystemServer.FACTORY_TEST_OFF) {  
  30.             if (mFactoryTest == SystemServer.FACTORY_TEST_LOW_LEVEL  
  31.                     && mTopComponent != null  
  32.                     && app.processName.equals(mTopComponent.getPackageName())) {  
  33.                 uid = 0;  
  34.             }  
  35.             if (mFactoryTest == SystemServer.FACTORY_TEST_HIGH_LEVEL  
  36.                     && (app.info.flags&ApplicationInfo.FLAG_FACTORY_TEST) != 0) {  
  37.                 uid = 0;  
  38.             }  
  39.         }  
  40.         //设置应用程序进程创建方式  
  41.         int debugFlags = 0;  
  42.         if ((app.info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0) {  
  43.             debugFlags |= Zygote.DEBUG_ENABLE_DEBUGGER;  
  44.             // Also turn on CheckJNI for debuggable apps. It's quite  
  45.             // awkward to turn on otherwise.  
  46.             debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;  
  47.         }  
  48.         // Run the app in safe mode if its manifest requests so or the  
  49.         // system is booted in safe mode.  
  50.         if ((app.info.flags & ApplicationInfo.FLAG_VM_SAFE_MODE) != 0 ||  
  51.             Zygote.systemInSafeMode == true) {  
  52.             debugFlags |= Zygote.DEBUG_ENABLE_SAFEMODE;  
  53.         }  
  54.         if ("1".equals(SystemProperties.get("debug.checkjni"))) {  
  55.             debugFlags |= Zygote.DEBUG_ENABLE_CHECKJNI;  
  56.         }  
  57.         if ("1".equals(SystemProperties.get("debug.jni.logging"))) {  
  58.             debugFlags |= Zygote.DEBUG_ENABLE_JNI_LOGGING;  
  59.         }  
  60.         if ("1".equals(SystemProperties.get("debug.assert"))) {  
  61.             debugFlags |= Zygote.DEBUG_ENABLE_ASSERT;  
  62.         }  
  63.         //它调用了Process.start函数开始为应用程序创建新的进程,  
  64.         //它传入一个第一个参数为"android.app.ActivityThread",这就是进程初始化时要加载的Java类了,  
  65.         //把这个类加载到进程之后,就会把它里面的静态成员函数main作为进程的入口点,  
  66.         Process.ProcessStartResult startResult = Process.start("android.app.ActivityThread",  
  67.                 app.processName, uid, uid, gids, debugFlags,  
  68.                 app.info.targetSdkVersion, null);  
  69.         BatteryStatsImpl bs = app.batteryStats.getBatteryStats();  
  70.         synchronized (bs) {  
  71.             if (bs.isOnBattery()) {  
  72.                 app.batteryStats.incStartsLocked();  
  73.             }  
  74.         }  
  75.         EventLog.writeEvent(EventLogTags.AM_PROC_START, startResult.pid, uid,  
  76.                 app.processName, hostingType,  
  77.                 hostingNameStr != null ? hostingNameStr : "");  
  78.         //如果启动的进程是一个持久进程,则添加到Watchdog中监控  
  79.         if (app.persistent) {  
  80.             Watchdog.getInstance().processStarted(app.processName, startResult.pid);  
  81.         }  
  82.         StringBuilder buf = mStringBuilder;  
  83.         buf.setLength(0);  
  84.         buf.append("Start proc ");  
  85.         buf.append(app.processName);  
  86.         buf.append(" for ");  
  87.         buf.append(hostingType);  
  88.         if (hostingNameStr != null) {  
  89.             buf.append(" ");  
  90.             buf.append(hostingNameStr);  
  91.         }  
  92.         buf.append(": pid=");  
  93.         buf.append(startResult.pid);  
  94.         buf.append(" uid=");  
  95.         buf.append(uid);  
  96.         buf.append(" gids={");  
  97.         if (gids != null) {  
  98.             for (int gi=0; gi<gids.length; gi++) {  
  99.                 if (gi != 0) buf.append(", ");  
  100.                 buf.append(gids[gi]);  
  101.   
  102.             }  
  103.         }  
  104.         buf.append("}");  
  105.         Slog.i(TAG, buf.toString());  
  106.         app.pid = startResult.pid;  
  107.         app.usingWrapper = startResult.usingWrapper;  
  108.         app.removed = false;  
  109.         //将新创建的进程描述符ProcessRecord保存到mPidsSelfLocked链表中  
  110.         /** 
  111.         * final SparseArray<ProcessRecord> mPidsSelfLocked = new SparseArray<ProcessRecord>(); 
  112.         * All of the processes we currently have running organized by pid. 
  113.         * The keys are the pid running the application. 
  114.         */  
  115.         synchronized (mPidsSelfLocked) {  
  116.             this.mPidsSelfLocked.put(startResult.pid, app);  
  117.             Message msg = mHandler.obtainMessage(PROC_START_TIMEOUT_MSG);  
  118.             msg.obj = app;  
  119.             mHandler.sendMessageDelayed(msg, startResult.usingWrapper  
  120.                     ? PROC_START_TIMEOUT_WITH_WRAPPER : PROC_START_TIMEOUT);  
  121.         }  
  122.     } catch (RuntimeException e) {  
  123.         // XXX do better error recovery.  
  124.         app.pid = 0;  
  125.         Slog.e(TAG, "Failure starting process " + app.processName, e);  
  126.     }  
  127.     if (LC_RAM_SUPPORT  
  128.             && ((app.info.flags & (ApplicationInfo.FLAG_SYSTEM)) == (ApplicationInfo.FLAG_SYSTEM))  
  129.             && (CONTACTS_PROCESS_NAME.equals(app.processName))) {  
  130.         app.isContactsProcess = true;  
  131.     }  
  132.     if (LC_RAM_SUPPORT && fixAdjList.containsKey(app.processName)) {  
  133.         app.fixAdj = fixAdjList.get(app.processName);  
  134.         Slog.v(TAG, "app[" + app.processName + "] has fix adj:" + app.fixAdj);  
  135.     }  
  136. }  
在该函数里,首先获取即将创建的应用程序的gid和uid,并设置应用程序进程创建方式,然后调用Process类的start()函数来创建一个新的应用程序进程,同时指定新进程执行的入口为ActivityThread类的main函数。
frameworks\base\core\java\android\os\Process.java
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static final ProcessStartResult start(final String processClass,  
  2.                               final String niceName,  
  3.                               int uid, int gid, int[] gids,  
  4.                               int debugFlags, int targetSdkVersion,  
  5.                               String[] zygoteArgs) {  
  6.     try {  
  7.         return startViaZygote(processClass, niceName, uid, gid, gids,  
  8.                 debugFlags, targetSdkVersion, zygoteArgs);  
  9.     } catch (ZygoteStartFailedEx ex) {  
  10.         Log.e(LOG_TAG,"Starting VM process through Zygote failed");  
  11.         throw new RuntimeException("Starting VM process through Zygote failed", ex);  
  12.     }  
  13. }  
该函数直接调用startViaZygote()函数来创建一个新的应用程序进程。

frameworks\base\core\java\android\os\Process.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private static ProcessStartResult startViaZygote(final String processClass,  
  2.                               final String niceName,  
  3.                               final int uid, final int gid,  
  4.                               final int[] gids,  
  5.                               int debugFlags, int targetSdkVersion,  
  6.                               String[] extraArgs)  
  7.                               throws ZygoteStartFailedEx {  
  8.     synchronized(Process.class) {  
  9.         ArrayList<String> argsForZygote = new ArrayList<String>();  
  10.         // --runtime-init, --setuid=, --setgid=,  
  11.         // and --setgroups= must go first  
  12.         argsForZygote.add("--runtime-init");  
  13.         argsForZygote.add("--setuid=" + uid);  
  14.         argsForZygote.add("--setgid=" + gid);  
  15.         if ((debugFlags & Zygote.DEBUG_ENABLE_JNI_LOGGING) != 0) {  
  16.             argsForZygote.add("--enable-jni-logging");  
  17.         }  
  18.         if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {  
  19.             argsForZygote.add("--enable-safemode");  
  20.         }  
  21.         if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {  
  22.             argsForZygote.add("--enable-debugger");  
  23.         }  
  24.         if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {  
  25.             argsForZygote.add("--enable-checkjni");  
  26.         }  
  27.         if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {  
  28.             argsForZygote.add("--enable-assert");  
  29.         }  
  30.         argsForZygote.add("--target-sdk-version=" + targetSdkVersion);  
  31.         //TODO optionally enable debuger  
  32.         //argsForZygote.add("--enable-debugger");  
  33.         // --setgroups is a comma-separated list  
  34.         if (gids != null && gids.length > 0) {  
  35.             StringBuilder sb = new StringBuilder();  
  36.             sb.append("--setgroups=");  
  37.             int sz = gids.length;  
  38.             for (int i = 0; i < sz; i++) {  
  39.                 if (i != 0) {  
  40.                     sb.append(',');  
  41.                 }  
  42.                 sb.append(gids[i]);  
  43.             }  
  44.             argsForZygote.add(sb.toString());  
  45.         }  
  46.         if (niceName != null) {  
  47.             argsForZygote.add("--nice-name=" + niceName);  
  48.         }  
  49.         argsForZygote.add(processClass);  
  50.         if (extraArgs != null) {  
  51.             for (String arg : extraArgs) {  
  52.                 argsForZygote.add(arg);  
  53.             }  
  54.         }  
  55.         //将通过Socket方式将参数列表发送给Zygote进程  
  56.         return zygoteSendArgsAndGetResult(argsForZygote);  
  57.     }  
  58. }  
在该函数里,首先将新的应用程序进程启动参数保存到argsForZygote列表中,然后调用zygoteSendArgsAndGetPid将应用程序进程启动参数发送到Zygote进程。
frameworks\base\core\java\android\os\Process.java
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private static ProcessStartResult zygoteSendArgsAndGetResult(ArrayList<String> args)  
  2.         throws ZygoteStartFailedEx {  
  3.     //创建一个客户端Socket,并连接到Zygote进程的Socket服务端  
  4.     openZygoteSocketIfNeeded();  
  5.     try {  
  6.         /** 
  7.          * See com.android.internal.os.ZygoteInit.readArgumentList() 
  8.          * Presently the wire format to the zygote process is: 
  9.          * a) a count of arguments (argc, in essence) 
  10.          * b) a number of newline-separated argument strings equal to count 
  11.          * 
  12.          * After the zygote process reads these it will write the pid of 
  13.          * the child or -1 on failure, followed by boolean to 
  14.          * indicate whether a wrapper process was used. 
  15.          */  
  16.         //将应用程序启动参数列表写入到Socket  
  17.         sZygoteWriter.write(Integer.toString(args.size()));  
  18.         sZygoteWriter.newLine();  
  19.         int sz = args.size();  
  20.         for (int i = 0; i < sz; i++) {  
  21.             String arg = args.get(i);  
  22.             if (arg.indexOf('\n') >= 0) {  
  23.                 throw new ZygoteStartFailedEx(  
  24.                         "embedded newlines not allowed");  
  25.             }  
  26.             sZygoteWriter.write(arg);  
  27.             sZygoteWriter.newLine();  
  28.         }  
  29.         sZygoteWriter.flush();  
  30.         //读取Zygote进程返回来的结果  
  31.         ProcessStartResult result = new ProcessStartResult();  
  32.         result.pid = sZygoteInputStream.readInt();  
  33.         if (result.pid < 0) {  
  34.             throw new ZygoteStartFailedEx("fork() failed");  
  35.         }  
  36.         result.usingWrapper = sZygoteInputStream.readBoolean();  
  37.         return result;  
  38.     } catch (IOException ex) {  
  39.         try {  
  40.             if (sZygoteSocket != null) {  
  41.                 sZygoteSocket.close();  
  42.             }  
  43.         } catch (IOException ex2) {  
  44.             // we're going to fail anyway  
  45.             Log.e(LOG_TAG,"I/O exception on routine close", ex2);  
  46.         }  
  47.         sZygoteSocket = null;  
  48.         throw new ZygoteStartFailedEx(ex);  
  49.     }  
  50. }  
该函数首先在SystemServer进程中创建一个客户端LocalSocket,并连接到Zygote进程的名为"zygote"的服务端Socket

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private static void openZygoteSocketIfNeeded()   
  2.         throws ZygoteStartFailedEx {  
  3.     int retryCount;  
  4.     if (sPreviousZygoteOpenFailed) {  
  5.         /* 
  6.          * If we've failed before, expect that we'll fail again and 
  7.          * don't pause for retries. 
  8.          */  
  9.         retryCount = 0;  
  10.     } else {  
  11.         retryCount = 10;              
  12.     }  
  13.   
  14.     /* 
  15.      * See bug #811181: Sometimes runtime can make it up before zygote. 
  16.      * Really, we'd like to do something better to avoid this condition, 
  17.      * but for now just wait a bit... 
  18.      */  
  19.     for (int retry = 0; (sZygoteSocket == null) && (retry < (retryCount + 1)); retry++ ) {  
  20.         if (retry > 0) {  
  21.             try {  
  22.                 Log.i("Zygote""Zygote not up yet, sleeping...");  
  23.                 Thread.sleep(ZYGOTE_RETRY_MILLIS);  
  24.             } catch (InterruptedException ex) {  
  25.                 // should never happen  
  26.             }  
  27.         }  
  28.         try {  
  29.             sZygoteSocket = new LocalSocket();  
  30.             //连接到Zygote进程的服务端zygote Socket  
  31.             sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET, LocalSocketAddress.Namespace.RESERVED));  
  32.             sZygoteInputStream = new DataInputStream(sZygoteSocket.getInputStream());  
  33.             sZygoteWriter = new BufferedWriter(new OutputStreamWriter(  
  34.                                 sZygoteSocket.getOutputStream()),256);  
  35.             Log.i("Zygote""Process: zygote socket opened");  
  36.             sPreviousZygoteOpenFailed = false;  
  37.             break;  
  38.         } catch (IOException ex) {  
  39.             //Socket操作失败,关闭该Socket  
  40.             if (sZygoteSocket != null) {  
  41.                 try {  
  42.                     sZygoteSocket.close();  
  43.                 } catch (IOException ex2) {  
  44.                     Log.e(LOG_TAG,"I/O exception on close after exception",ex2);  
  45.                 }  
  46.             }  
  47.             sZygoteSocket = null;  
  48.         }  
  49.     }  
  50.   
  51.     if (sZygoteSocket == null) {  
  52.         sPreviousZygoteOpenFailed = true;  
  53.         throw new ZygoteStartFailedEx("connect failed");                   
  54.     }  
  55. }  
最后将参数列表写入到创建的客户端Socket中,从而将应用程序启动参数发送给Zygote进程,启动参数包括:

"--runtime-init"
"--setuid=x"
"--setgid=x"
"--enable-safemode"
"--enable-debugger"
"--enable-checkjni"
"--enable-assert"
"--setgroups=x"
"--nice-name=x"
"android.app.ActivityThread"
要启动一个新的应用程序进程,应用程序不能直接请求Zygote来fork出新进程,而是要通过SystemServer进程中的ActivityManagerService服务来请求Zygote进程。

Zygote进程孵化应用程序进程


ActivityManagerService通过Socket方式将请求参数发送给Zygote,此时Zygote正在runSelectLoopMode()函数中监听Socket连接。

frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private static void runSelectLoopMode() throws MethodAndArgsCaller {  
  2.     ArrayList<FileDescriptor> fds = new ArrayList();  
  3.     ArrayList<ZygoteConnection> peers = new ArrayList();  
  4.     FileDescriptor[] fdArray = new FileDescriptor[4];  
  5.       
  6.     fds.add(sServerSocket.getFileDescriptor());  
  7.     peers.add(null);  
  8.   
  9.     int loopCount = GC_LOOP_COUNT;  
  10.     while (true) {  
  11.         int index;  
  12.         /* 
  13.          * Call gc() before we block in select(). 
  14.          * It's work that has to be done anyway, and it's better 
  15.          * to avoid making every child do it.  It will also 
  16.          * madvise() any free memory as a side-effect. 
  17.          * 
  18.          * Don't call it every time, because walking the entire 
  19.          * heap is a lot of overhead to free a few hundred bytes. 
  20.          */  
  21.         if (loopCount <= 0) {  
  22.             gc();  
  23.             loopCount = GC_LOOP_COUNT;  
  24.         } else {  
  25.             loopCount--;  
  26.         }  
  27.         try {  
  28.             fdArray = fds.toArray(fdArray);  
  29.             //监听zygote Socket是否有客户端连接  
  30.             index = selectReadable(fdArray);  
  31.         } catch (IOException ex) {  
  32.             throw new RuntimeException("Error in select()", ex);  
  33.         }  
  34.         if (index < 0) {  
  35.             throw new RuntimeException("Error in select()");  
  36.         //zygote socket句柄中有事件到来,表示有客户端的socket连接  
  37.         } else if (index == 0) {  
  38.             //接收客户端连接请求,并将客户端请求添加到句柄池中监控  
  39.             ZygoteConnection newPeer = acceptCommandPeer();  
  40.             peers.add(newPeer);  
  41.             fds.add(newPeer.getFileDesciptor());  
  42.         //客户端连接Socket有事件到来,表示SystemServer进程正在发送应用程序启动参数  
  43.         } else {  
  44.             boolean done;  
  45.             //孵化一个新的应用程序进程  
  46.             done = peers.get(index).runOnce();  
  47.             //从socket句柄池中移除客户连接socket句柄  
  48.             if (done) {  
  49.                 peers.remove(index);  
  50.                 fds.remove(index);  
  51.             }  
  52.         }  
  53.     }  
  54. }  
当接收到新的客户端socket连接请求时,函数从selectReadable中返回,并为该客户端连接创建一个ZygoteConnection实例;当Zygote接收到SystemServer进程发送过来的应用程序进程启动参数时,就会调用相应ZygoteConnection实例的runOnce()函数来启动一个新的进程。

frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {  
  2.   
  3.     String args[];  
  4.     Arguments parsedArgs = null;  
  5.     FileDescriptor[] descriptors;  
  6.     try {  
  7.         //读取参数  
  8.         args = readArgumentList();  
  9.         descriptors = mSocket.getAncillaryFileDescriptors();  
  10.     } catch (IOException ex) {  
  11.         Log.w(TAG, "IOException on command socket " + ex.getMessage());  
  12.         closeSocket();  
  13.         return true;  
  14.     }  
  15.     if (args == null) {  
  16.         // EOF reached.  
  17.         closeSocket();  
  18.         return true;  
  19.     }  
  20.     /** the stderr of the most recent request, if avail */  
  21.     PrintStream newStderr = null;  
  22.   
  23.     if (descriptors != null && descriptors.length >= 3) {  
  24.         newStderr = new PrintStream(new FileOutputStream(descriptors[2]));  
  25.     }  
  26.     int pid = -1;  
  27.     FileDescriptor childPipeFd = null;  
  28.     FileDescriptor serverPipeFd = null;  
  29.     try {  
  30.         parsedArgs = new Arguments(args);  
  31.         applyUidSecurityPolicy(parsedArgs, peer);  
  32.         applyRlimitSecurityPolicy(parsedArgs, peer);  
  33.         applyCapabilitiesSecurityPolicy(parsedArgs, peer);  
  34.         applyInvokeWithSecurityPolicy(parsedArgs, peer);  
  35.         applyDebuggerSystemProperty(parsedArgs);  
  36.         applyInvokeWithSystemProperty(parsedArgs);  
  37.         int[][] rlimits = null;  
  38.   
  39.         if (parsedArgs.rlimits != null) {  
  40.             rlimits = parsedArgs.rlimits.toArray(intArray2d);  
  41.         }  
  42.   
  43.         if (parsedArgs.runtimeInit && parsedArgs.invokeWith != null) {  
  44.             FileDescriptor[] pipeFds = Libcore.os.pipe();  
  45.             childPipeFd = pipeFds[1];  
  46.             serverPipeFd = pipeFds[0];  
  47.             ZygoteInit.setCloseOnExec(serverPipeFd, true);  
  48.         }  
  49.         //创建子进程,而且有两个返回值,一个是在当前进程中返回的,一个是在新创建的进程中返回,  
  50.         //即在当前进程的子进程中返回,在当前进程中的返回值就是新创建的子进程的pid值,而在子进程中的返回值是0。  
  51.         pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,  
  52.                 parsedArgs.gids, parsedArgs.debugFlags, rlimits);  
  53.     } catch (IOException ex) {  
  54.         logAndPrintError(newStderr, "Exception creating pipe", ex);  
  55.     } catch (ErrnoException ex) {  
  56.         logAndPrintError(newStderr, "Exception creating pipe", ex);  
  57.     } catch (IllegalArgumentException ex) {  
  58.         logAndPrintError(newStderr, "Invalid zygote arguments", ex);  
  59.     } catch (ZygoteSecurityException ex) {  
  60.         logAndPrintError(newStderr,  
  61.                 "Zygote security policy prevents request: ", ex);  
  62.     }  
  63.     try {  
  64.         //父子进程运行分界线  
  65.         if (pid == 0) {  
  66.             //子进程执行过程  
  67.             IoUtils.closeQuietly(serverPipeFd);  
  68.             serverPipeFd = null;  
  69.             handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);  
  70.             // should never get here, the child is expected to either  
  71.             // throw ZygoteInit.MethodAndArgsCaller or exec().  
  72.             return true;  
  73.         } else {  
  74.             //父进程,也就是Zygote进程执行过程  
  75.             IoUtils.closeQuietly(childPipeFd);  
  76.             childPipeFd = null;  
  77.             return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);  
  78.         }  
  79.     } finally {  
  80.         IoUtils.closeQuietly(childPipeFd);  
  81.         IoUtils.closeQuietly(serverPipeFd);  
  82.     }  
  83. }  
函数首先调用readArgumentList读取ActivityManagerService发送过来的应用程序启动参数,接着根据参数调用forkAndSpecialize函数fork一个新的应用程序进程,就是复制一份Zygote进程地址空间,当返回的pid=0时,表示当前是新创建的应用程序进程,否则为Zygote进程的函数执行返回。首先来分析Zygote进程返回后执行的工作:

frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private boolean handleParentProc(int pid,  
  2.         FileDescriptor[] descriptors, FileDescriptor pipeFd, Arguments parsedArgs) {  
  3.     if (pid > 0) {  
  4.         setChildPgid(pid);  
  5.     }  
  6.     if (descriptors != null) {  
  7.         for (FileDescriptor fd: descriptors) {  
  8.             IoUtils.closeQuietly(fd);  
  9.         }  
  10.     }  
  11.     boolean usingWrapper = false;  
  12.     if (pipeFd != null && pid > 0) {  
  13.         DataInputStream is = new DataInputStream(new FileInputStream(pipeFd));  
  14.         int innerPid = -1;  
  15.         try {  
  16.             innerPid = is.readInt();  
  17.         } catch (IOException ex) {  
  18.             Log.w(TAG, "Error reading pid from wrapped process, child may have died", ex);  
  19.         } finally {  
  20.             try {  
  21.                 is.close();  
  22.             } catch (IOException ex) {  
  23.             }  
  24.         }  
  25.         // Ensure that the pid reported by the wrapped process is either the  
  26.         // child process that we forked, or a descendant of it.  
  27.         if (innerPid > 0) {  
  28.             int parentPid = innerPid;  
  29.             while (parentPid > 0 && parentPid != pid) {  
  30.                 parentPid = Process.getParentPid(parentPid);  
  31.             }  
  32.             if (parentPid > 0) {  
  33.                 Log.i(TAG, "Wrapped process has pid " + innerPid);  
  34.                 pid = innerPid;  
  35.                 usingWrapper = true;  
  36.             } else {  
  37.                 Log.w(TAG, "Wrapped process reported a pid that is not a child of "  
  38.                         + "the process that we forked: childPid=" + pid  
  39.                         + " innerPid=" + innerPid);  
  40.             }  
  41.         }  
  42.     }  
  43.     //将创建的应用程序进程ID返回给SystemServer进程的ActivityManagerService服务  
  44.     try {  
  45.         mSocketOutStream.writeInt(pid);  
  46.         mSocketOutStream.writeBoolean(usingWrapper);  
  47.     } catch (IOException ex) {  
  48.         Log.e(TAG, "Error reading from command socket", ex);  
  49.         return true;  
  50.     }  
  51.     /* 
  52.      * If the peer wants to use the socket to wait on the 
  53.      * newly spawned process, then we're all done. 
  54.      */  
  55.     if (parsedArgs.peerWait) {  
  56.         try {  
  57.             mSocket.close();  
  58.         } catch (IOException ex) {  
  59.             Log.e(TAG, "Zygote: error closing sockets", ex);  
  60.         }  
  61.         return true;  
  62.     }  
  63.     return false;  
  64. }  
Zygote进程将新创建的应用程序进程写回到SystemServer进程后,从函数handleParentProc一路返回到runSelectLoopMode(),继续监听客户端进程的Socket连接请求。


Zygote孵化出新的应用程序进程后,新的应用程序进程将执行handleChildProc函数,从此与其父进程Zygote分道扬镳。

frameworks\base\core\java\com\android\internal\os\ZygoteConnection.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private void handleChildProc(Arguments parsedArgs,  
  2.         FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)  
  3.         throws ZygoteInit.MethodAndArgsCaller {  
  4.     /* 
  5.      * Close the socket, unless we're in "peer wait" mode, in which 
  6.      * case it's used to track the liveness of this process. 
  7.      */  
  8.   
  9.     if (parsedArgs.peerWait) {  
  10.         try {  
  11.             ZygoteInit.setCloseOnExec(mSocket.getFileDescriptor(), true);  
  12.             sPeerWaitSocket = mSocket;  
  13.         } catch (IOException ex) {  
  14.             Log.e(TAG, "Zygote Child: error setting peer wait "  
  15.                     + "socket to be close-on-exec", ex);  
  16.         }  
  17.     } else {//关闭从Zygote进程复制过来的Socket连接  
  18.         closeSocket();  
  19.         ZygoteInit.closeServerSocket();  
  20.     }  
  21.     if (descriptors != null) {  
  22.         try {  
  23.             //为新创建的应用程序进程重新打开标准输入输出控制台  
  24.             ZygoteInit.reopenStdio(descriptors[0],descriptors[1], descriptors[2]);  
  25.             for (FileDescriptor fd: descriptors) {  
  26.                 IoUtils.closeQuietly(fd);  
  27.             }  
  28.             newStderr = System.err;  
  29.         } catch (IOException ex) {  
  30.             Log.e(TAG, "Error reopening stdio", ex);  
  31.         }  
  32.     }  
  33.     //设置新进程名称  
  34.     if (parsedArgs.niceName != null) {  
  35.         Process.setArgV0(parsedArgs.niceName);  
  36.     }  
  37.     //重新初始化Runtime  
  38.     if (parsedArgs.runtimeInit) {  
  39.         if (parsedArgs.invokeWith != null) {  
  40.             WrapperInit.execApplication(parsedArgs.invokeWith,  
  41.                     parsedArgs.niceName, parsedArgs.targetSdkVersion,  
  42.                     pipeFd, parsedArgs.remainingArgs);  
  43.         } else {  
  44.             //为应用程序进程启动Binder线程池  
  45.             RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,parsedArgs.remainingArgs);  
  46.         }  
  47.     } else {  
  48.         String className;  
  49.         try {  
  50.             //读取新进程执行的类名,在Process.start()函数中,传过来的类名为:"android.app.ActivityThread"  
  51.             className = parsedArgs.remainingArgs[0];  
  52.         } catch (ArrayIndexOutOfBoundsException ex) {  
  53.             logAndPrintError(newStderr,"Missing required class name argument"null);  
  54.             return;  
  55.         }  
  56.         String[] mainArgs = new String[parsedArgs.remainingArgs.length - 1];  
  57.         System.arraycopy(parsedArgs.remainingArgs, 1,mainArgs, 0, mainArgs.length);  
  58.         if (parsedArgs.invokeWith != null) {  
  59.             WrapperInit.execStandalone(parsedArgs.invokeWith,parsedArgs.classpath, className, mainArgs);  
  60.         } else {  
  61.             //获取类加载器  
  62.             ClassLoader cloader;  
  63.             if (parsedArgs.classpath != null) {  
  64.                 cloader = new PathClassLoader(parsedArgs.classpath,ClassLoader.getSystemClassLoader());  
  65.             } else {  
  66.                 cloader = ClassLoader.getSystemClassLoader();  
  67.             }  
  68.             //加载并执行"android.app.ActivityThread"类  
  69.             try {  
  70.                 ZygoteInit.invokeStaticMain(cloader, className, mainArgs);  
  71.             } catch (RuntimeException ex) {  
  72.                 logAndPrintError(newStderr, "Error starting.", ex);  
  73.             }  
  74.         }  
  75.     }  
  76. }  
由于应用程序启动参数中已经设置了"--runtime-init"标志位,因此新创建的应用程序进程将调用RuntimeInit.zygoteInit()函数来初始化运行时库,为应用程序启动Binder线程池,完成这些准备工作后,调用应用程序进程的入口函数ActivityThread.main()为应用程序进程创建消息循环。

frameworks\base\core\java\com\android\internal\os\RuntimeInit.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static final void zygoteInit(int targetSdkVersion, String[] argv)  
  2.         throws ZygoteInit.MethodAndArgsCaller {  
  3.     if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote");  
  4.     //重定向Log输出流  
  5.     redirectLogStreams();  
  6.     //初始化运行环境  
  7.     commonInit();  
  8.     //启动Binder线程池  
  9.     nativeZygoteInit();  
  10.     //调用程序入口函数  
  11.     applicationInit(targetSdkVersion, argv);  
  12. }  
1. 初始化Log输出流

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. /** 
  2.  * Redirect System.out and System.err to the Android log. 
  3.  */  
  4. public static void redirectLogStreams() {  
  5.     System.out.close();  
  6.     System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));  
  7.     System.err.close();  
  8.     System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));  
  9. }  

2.初始化运行环境

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. private static final void commonInit() {  
  2.     if (DEBUG) Slog.d(TAG, "Entered RuntimeInit!");  
  3.   
  4.     /* set default handler; this applies to all threads in the VM */  
  5.     Thread.setDefaultUncaughtExceptionHandler(new UncaughtHandler());  
  6.   
  7.     /* 
  8.      * Install a TimezoneGetter subclass for ZoneInfo.db 
  9.      */  
  10.     TimezoneGetter.setInstance(new TimezoneGetter() {  
  11.         @Override  
  12.         public String getId() {  
  13.             return SystemProperties.get("persist.sys.timezone");  
  14.         }  
  15.     });  
  16.     TimeZone.setDefault(null);  
  17.   
  18.     /* 
  19.      * Sets handler for java.util.logging to use Android log facilities. 
  20.      * The odd "new instance-and-then-throw-away" is a mirror of how 
  21.      * the "java.util.logging.config.class" system property works. We 
  22.      * can't use the system property here since the logger has almost 
  23.      * certainly already been initialized. 
  24.      */  
  25.     LogManager.getLogManager().reset();  
  26.     new AndroidConfig();  
  27.   
  28.     /* 
  29.      * Sets the default HTTP User-Agent used by HttpURLConnection. 
  30.      */  
  31.     String userAgent = getDefaultUserAgent();  
  32.     System.setProperty("http.agent", userAgent);  
  33.   
  34.     /* 
  35.      * Wire socket tagging to traffic stats. 
  36.      */  
  37.     NetworkManagementSocketTagger.install();  
  38.   
  39.     /* 
  40.      * If we're running in an emulator launched with "-trace", put the 
  41.      * VM into emulator trace profiling mode so that the user can hit 
  42.      * F9/F10 at any time to capture traces.  This has performance 
  43.      * consequences, so it's not something you want to do always. 
  44.      */  
  45.     String trace = SystemProperties.get("ro.kernel.android.tracing");  
  46.     if (trace.equals("1")) {  
  47.         Slog.i(TAG, "NOTE: emulator trace profiling enabled");  
  48.         Debug.enableEmulatorTraceOutput();  
  49.     }  
  50.   
  51.     initialized = true;  
  52. }  

3.启动Binder线程池

关于Binder线程池的启动过程请参考Android应用程序启动Binder线程源码分析


4.调用进程入口函数

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. static void invokeStaticMain(ClassLoader loader,  
  2.         String className, String[] argv)  
  3.         throws ZygoteInit.MethodAndArgsCaller {  
  4.     //加载"android.app.ActivityThread"类  
  5.     Class<?> cl;  
  6.     try {  
  7.         cl = loader.loadClass(className);  
  8.     } catch (ClassNotFoundException ex) {  
  9.         throw new RuntimeException("Missing class when invoking static main " + className,  
  10.                 ex);  
  11.     }  
  12.     //通过类反射机制查找ActivityThread类中的main函数  
  13.     Method m;  
  14.     try {  
  15.         m = cl.getMethod("main"new Class[] { String[].class });  
  16.     } catch (NoSuchMethodException ex) {  
  17.         throw new RuntimeException("Missing static main on " + className, ex);  
  18.     } catch (SecurityException ex) {  
  19.         throw new RuntimeException("Problem getting static main on " + className, ex);  
  20.     }  
  21.     //获取main函数的修饰符  
  22.     int modifiers = m.getModifiers();  
  23.     //进程入口函数必须为静态Public类型  
  24.     if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {  
  25.         throw new RuntimeException("Main method is not public and static on " + className);  
  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. }  

抛出MethodAndArgsCaller异常,并在ZygoteInit.main()函数中捕获该异常,这样就可以清除应用程序进程创建过程的调用栈,将应用程序启动的入口函数设置为ActivityThread.main()
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String argv[]) {  
  2.     try {  
  3.         ...  
  4.     //捕获MethodAndArgsCaller异常  
  5.     } catch (MethodAndArgsCaller caller) {  
  6.         caller.run();  
  7.     } catch (RuntimeException ex) {  
  8.         Log.e(TAG, "Zygote died with exception", ex);  
  9.         closeServerSocket();  
  10.         throw ex;  
  11.     }  
  12. }  
在该函数里,捕获了MethodAndArgsCaller异常,并调用MethodAndArgsCaller类的run()方法来处理异常:
[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static class MethodAndArgsCaller extends Exception implements Runnable {  
  2.     public void run() {  
  3.         try {  
  4.             mMethod.invoke(nullnew Object[] { mArgs });  
  5.         } catch (IllegalAccessException ex) {  
  6.             throw new RuntimeException(ex);  
  7.         } catch (InvocationTargetException ex) {  
  8.             Throwable cause = ex.getCause();  
  9.             if (cause instanceof RuntimeException) {  
  10.                 throw (RuntimeException) cause;  
  11.             } else if (cause instanceof Error) {  
  12.                 throw (Error) cause;  
  13.             }  
  14.             throw new RuntimeException(ex);  
  15.         }  
  16.     }  
  17. }  
这里通过反射机制调用ActivityThread类的main函数,到此新的应用程序进程就创建完毕,同时新的应用程序从ActivityThread.main()函数中开始运行。

frameworks\base\core\java\android\app\ActivityThread.java

[java]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. public static void main(String[] args) {  
  2.     SamplingProfilerIntegration.start();  
  3.     // CloseGuard defaults to true and can be quite spammy.  We  
  4.     // disable it here, but selectively enable it later (via  
  5.     // StrictMode) on debug builds, but using DropBox, not logs.  
  6.     CloseGuard.setEnabled(false);  
  7.     Process.setArgV0("<pre-initialized>");  
  8.     //为新的应用程序创建消息队列  
  9.     Looper.prepareMainLooper();  
  10.     if (sMainThreadHandler == null) {  
  11.         sMainThreadHandler = new Handler();  
  12.     }  
  13.     //创建一个ActivityThread对象,初始化应用程序运行环境,每一个进程对应一个ActivityThread实例  
  14.     ActivityThread thread = new ActivityThread();  
  15.     //建立与ActivityManagerService之间的Binder通信通道  
  16.     thread.attach(false);  
  17.     AsyncTask.init();  
  18.       
  19.     if (false) {  
  20.         Looper.myLooper().setMessageLogging(newLogPrinter(Log.DEBUG, "ActivityThread"));  
  21.     }  
  22.     //为新的应用程序进程启动消息循环,这个消息循环就是应用程序主线程消息循环  
  23.     Looper.loop();  
  24.     throw new RuntimeException("Main thread loop unexpectedly exited");  
  25. }  

至此,Android应用程序进程启动过程的源代码就分析完成了,以下是android应用进程的启动过程的时序图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值