Android系统进程Zygote启动过程的源代码分析

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

Android应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信机制;这两个特点都是在进程的初始化过程中实现的,本文将详细分析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组件。

在Android应用程序框架层中,是由ActivityManagerService组件负责为Android应用程序创建新的进程的,它本来也是运行在一个独立的进程之中,不过这个进程是在系统启动的过程中创建的。ActivityManagerService组件一般会在什么情况下会为应用程序创建一个新的进程呢?当系统决定要在一个新的进程中启动一个Activity或者Service时,它就会创建一个新的进程了,然后在这个新的进程中启动这个Activity或者Service,具体可以参考Android系统在新进程中启动自定义服务过程(startService)的原理分析Android应用程序启动过程源代码分析Android应用程序在新的进程中启动新的Activity的方法和过程分析这三篇文章。

ActivityManagerService启动新的进程是从其成员函数startProcessLocked开始的,在深入分析这个过程之前,我们先来看一下进程创建过程的序列图,然后再详细分析每一个步骤。

点击查看大图

Step 1. ActivityManagerService.startProcessLocked

这个函数定义在frameworks/base/services/java/com/android/server/am/ActivityManagerService.java文件中:

[java] view plaincopy

  1. public final class ActivityManagerService extends ActivityManagerNative
  2. implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
  3. ......
  4. private final void startProcessLocked(ProcessRecord app,
  5. String hostingType, String hostingNameStr) {
  6. ......
  7. try {
  8. int uid = app.info.uid;
  9. int[] gids = null;
  10. try {
  11. gids = mContext.getPackageManager().getPackageGids(
  12. app.info.packageName);
  13. } catch (PackageManager.NameNotFoundException e) {
  14. ......
  15. }
  16. ......
  17. int debugFlags = 0;
  18. ......
  19. int pid = Process.start("android.app.ActivityThread",
  20. mSimpleProcessManagement ? app.processName : null, uid, uid,
  21. gids, debugFlags, null);
  22. ......
  23. } catch (RuntimeException e) {
  24. ......
  25. }
  26. }
  27. ......
  28. }

它调用了Process.start函数开始为应用程序创建新的进程,注意,它传入一个第一个参数为"android.app.ActivityThread",这就是进程初始化时要加载的Java类了,把这个类加载到进程之后,就会把它里面的静态成员函数main作为进程的入口点,后面我们会看到。

Step 2. Process.start

这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:

[java] view plaincopy

  1. public class Process {
  2. ......
  3. public static final int start(final String processClass,
  4. final String niceName,
  5. int uid, int gid, int[] gids,
  6. int debugFlags,
  7. String[] zygoteArgs)
  8. {
  9. if (supportsProcesses()) {
  10. try {
  11. return startViaZygote(processClass, niceName, uid, gid, gids,
  12. debugFlags, zygoteArgs);
  13. } catch (ZygoteStartFailedEx ex) {
  14. ......
  15. }
  16. } else {
  17. ......
  18. return 0;
  19. }
  20. }
  21. ......
  22. }

这里的supportsProcesses函数返回值为true,它是一个Native函数,实现在frameworks/base/core/jni/android_util_Process.cpp文件中:

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

  1. public class Process {
  2. ......
  3. private static int startViaZygote(final String processClass,
  4. final String niceName,
  5. final int uid, final int gid,
  6. final int[] gids,
  7. int debugFlags,
  8. String[] extraArgs)
  9. throws ZygoteStartFailedEx {
  10. int pid;
  11. synchronized(Process.class) {
  12. ArrayList<String> argsForZygote = new ArrayList<String>();
  13. // --runtime-init, --setuid=, --setgid=,
  14. // and --setgroups= must go first
  15. argsForZygote.add("--runtime-init");
  16. argsForZygote.add("--setuid=" + uid);
  17. argsForZygote.add("--setgid=" + gid);
  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. //TODO optionally enable debuger
  31. //argsForZygote.add("--enable-debugger");
  32. // --setgroups is a comma-separated list
  33. if (gids != null && gids.length > 0) {
  34. StringBuilder sb = new StringBuilder();
  35. sb.append("--setgroups=");
  36. int sz = gids.length;
  37. for (int i = 0; i < sz; i++) {
  38. if (i != 0) {
  39. sb.append(‘,‘);
  40. }
  41. sb.append(gids[i]);
  42. }
  43. argsForZygote.add(sb.toString());
  44. }
  45. if (niceName != null) {
  46. argsForZygote.add("--nice-name=" + niceName);
  47. }
  48. argsForZygote.add(processClass);
  49. if (extraArgs != null) {
  50. for (String arg : extraArgs) {
  51. argsForZygote.add(arg);
  52. }
  53. }
  54. pid = zygoteSendArgsAndGetPid(argsForZygote);
  55. }
  56. }
  57. ......
  58. }

这个函数将创建进程的参数放到argsForZygote列表中去,如参数"--runtime-init"表示要为新创建的进程初始化运行时库,然后调用zygoteSendAndGetPid函数进一步操作。

Step 4. Process.zygoteSendAndGetPid

这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:

[java] view plaincopy

  1. public class Process {
  2. ......
  3. private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
  4. throws ZygoteStartFailedEx {
  5. int pid;
  6. openZygoteSocketIfNeeded();
  7. try {
  8. /**
  9. * See com.android.internal.os.ZygoteInit.readArgumentList()
  10. * Presently the wire format to the zygote process is:
  11. * a) a count of arguments (argc, in essence)
  12. * b) a number of newline-separated argument strings equal to count
  13. *
  14. * After the zygote process reads these it will write the pid of
  15. * the child or -1 on failure.
  16. */
  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. // Should there be a timeout on this?
  31. pid = sZygoteInputStream.readInt();
  32. if (pid < 0) {
  33. throw new ZygoteStartFailedEx("fork() failed");
  34. }
  35. } catch (IOException ex) {
  36. ......
  37. }
  38. return pid;
  39. }
  40. ......
  41. }

这里的sZygoteWriter是一个Socket写入流,是由openZygoteSocketIfNeeded函数打开的:

[java] view plaincopy

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

这个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 plaincopy

  1. public class ZygoteInit {
  2. ......
  3. /**
  4. * Runs the zygote process‘s select loop. Accepts new connections as
  5. * they happen, and reads commands from connections one spawn-request‘s
  6. * worth at a time.
  7. *
  8. * @throws MethodAndArgsCaller in a child process when a main() should
  9. * be executed.
  10. */
  11. private static void runSelectLoopMode() throws MethodAndArgsCaller {
  12. ArrayList<FileDescriptor> fds = new ArrayList();
  13. ArrayList<ZygoteConnection> peers = new ArrayList();
  14. FileDescriptor[] fdArray = new FileDescriptor[4];
  15. fds.add(sServerSocket.getFileDescriptor());
  16. peers.add(null);
  17. int loopCount = GC_LOOP_COUNT;
  18. while (true) {
  19. int index;
  20. /*
  21. * Call gc() before we block in select().
  22. * It‘s work that has to be done anyway, and it‘s better
  23. * to avoid making every child do it.  It will also
  24. * madvise() any free memory as a side-effect.
  25. *
  26. * Don‘t call it every time, because walking the entire
  27. * heap is a lot of overhead to free a few hundred bytes.
  28. */
  29. if (loopCount <= 0) {
  30. gc();
  31. loopCount = GC_LOOP_COUNT;
  32. } else {
  33. loopCount--;
  34. }
  35. try {
  36. fdArray = fds.toArray(fdArray);
  37. index = selectReadable(fdArray);
  38. } catch (IOException ex) {
  39. throw new RuntimeException("Error in select()", ex);
  40. }
  41. if (index < 0) {
  42. throw new RuntimeException("Error in select()");
  43. } else if (index == 0) {
  44. ZygoteConnection newPeer = acceptCommandPeer();
  45. peers.add(newPeer);
  46. fds.add(newPeer.getFileDesciptor());
  47. } else {
  48. boolean done;
  49. done = peers.get(index).runOnce();
  50. if (done) {
  51. peers.remove(index);
  52. fds.remove(index);
  53. }
  54. }
  55. }
  56. }
  57. ......
  58. }

当Step 4将数据通过Socket接口发送出去后,就会下面这个语句:

[java] view plaincopy

  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 plaincopy

  1. class ZygoteConnection {
  2. ......
  3. boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {
  4. String args[];
  5. Arguments parsedArgs = null;
  6. FileDescriptor[] descriptors;
  7. try {
  8. args = readArgumentList();
  9. descriptors = mSocket.getAncillaryFileDescriptors();
  10. } catch (IOException ex) {
  11. ......
  12. return true;
  13. }
  14. ......
  15. /** the stderr of the most recent request, if avail */
  16. PrintStream newStderr = null;
  17. if (descriptors != null && descriptors.length >= 3) {
  18. newStderr = new PrintStream(
  19. new FileOutputStream(descriptors[2]));
  20. }
  21. int pid;
  22. try {
  23. parsedArgs = new Arguments(args);
  24. applyUidSecurityPolicy(parsedArgs, peer);
  25. applyDebuggerSecurityPolicy(parsedArgs);
  26. applyRlimitSecurityPolicy(parsedArgs, peer);
  27. applyCapabilitiesSecurityPolicy(parsedArgs, peer);
  28. int[][] rlimits = null;
  29. if (parsedArgs.rlimits != null) {
  30. rlimits = parsedArgs.rlimits.toArray(intArray2d);
  31. }
  32. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
  33. parsedArgs.gids, parsedArgs.debugFlags, rlimits);
  34. } catch (IllegalArgumentException ex) {
  35. ......
  36. } catch (ZygoteSecurityException ex) {
  37. ......
  38. }
  39. if (pid == 0) {
  40. // in child
  41. handleChildProc(parsedArgs, descriptors, newStderr);
  42. // should never happen
  43. return true;
  44. } else { /* pid != 0 */
  45. // in parent...pid of < 0 means failure
  46. return handleParentProc(pid, descriptors, parsedArgs);
  47. }
  48. }
  49. ......
  50. }

真正创建进程的地方就是在这里了:

[java] view plaincopy

  1. pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid,
  2. parsedArgs.gids, parsedArgs.debugFlags, rlimits);

有Linux开发经验的读者很容易看懂这个函数调用,这个函数会创建一个进程,而且有两个返回值,一个是在当前进程中返回的,一个是在新创建的进程中返回,即在当前进程的子进程中返回,在当前进程中的返回值就是新创建的子进程的pid值,而在子进程中的返回值是0。因为我们只关心创建的新进程的情况,因此,我们沿着子进程的执行路径继续看下去:

[java] view plaincopy

  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 plaincopy

  1. class ZygoteConnection {
  2. ......
  3. private void handleChildProc(Arguments parsedArgs,
  4. FileDescriptor[] descriptors, PrintStream newStderr)
  5. throws ZygoteInit.MethodAndArgsCaller {
  6. ......
  7. if (parsedArgs.runtimeInit) {
  8. RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
  9. } else {
  10. ......
  11. }
  12. }
  13. ......
  14. }

由于在前面的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 plaincopy

  1. public class RuntimeInit {
  2. ......
  3. public static final void zygoteInit(String[] argv)
  4. throws ZygoteInit.MethodAndArgsCaller {
  5. // TODO: Doing this here works, but it seems kind of arbitrary. Find
  6. // a better place. The goal is to set it up for applications, but not
  7. // tools like am.
  8. System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
  9. System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
  10. commonInit();
  11. zygoteInitNative();
  12. int curArg = 0;
  13. for ( /* curArg */ ; curArg < argv.length; curArg++) {
  14. String arg = argv[curArg];
  15. if (arg.equals("--")) {
  16. curArg++;
  17. break;
  18. } else if (!arg.startsWith("--")) {
  19. break;
  20. } else if (arg.startsWith("--nice-name=")) {
  21. String niceName = arg.substring(arg.indexOf(‘=‘) + 1);
  22. Process.setArgV0(niceName);
  23. }
  24. }
  25. if (curArg == argv.length) {
  26. Slog.e(TAG, "Missing classname argument to RuntimeInit!");
  27. // let the process exit
  28. return;
  29. }
  30. // Remaining arguments are passed to the start class‘s static main
  31. String startClass = argv[curArg++];
  32. String[] startArgs = new String[argv.length - curArg];
  33. System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
  34. invokeStaticMain(startClass, startArgs);
  35. }
  36. ......
  37. }

这里有两个关键的函数调用,一个是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 plaincopy

  1. public class RuntimeInit {
  2. ......
  3. public static final native void zygoteInitNative();
  4. ......
  5. }

这里可以看出,函数zygoteInitNative是一个Native函数,实现在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

[cpp] view plaincopy

  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 plaincopy

  1. static AndroidRuntime* gCurRuntime = NULL;

这里可以看出,它的类型为AndroidRuntime,它是在AndroidRuntime类的构造函数中初始化的,AndroidRuntime类的构造函数也是定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

[cpp] view plaincopy

  1. AndroidRuntime::AndroidRuntime()
  2. {
  3. ......
  4. assert(gCurRuntime == NULL);        // one per process
  5. gCurRuntime = this;
  6. }

那么这个AndroidRuntime类的构造函数又是什么时候被调用的呢?AndroidRuntime类的声明在frameworks/base/include/android_runtime/AndroidRuntime.h文件中,如果我们打开这个文件会看到,它是一个虚拟类,也就是我们不能直接创建一个AndroidRuntime对象,只能用一个AndroidRuntime类的指针来指向它的某一个子类,这个子类就是AppRuntime了,它定义在frameworks/base/cmds/app_process/app_main.cpp文件中:

[cpp] view plaincopy

  1. int main(int argc, const char* const argv[])
  2. {
  3. ......
  4. AppRuntime runtime;
  5. ......
  6. }

而AppRuntime类继续了AndroidRuntime类,它也是定义在frameworks/base/cmds/app_process/app_main.cpp文件中:

[cpp] view plaincopy

  1. class AppRuntime : public AndroidRuntime
  2. {
  3. ......
  4. };

因此,在前面的com_android_internal_os_RuntimeInit_zygoteInit函数,实际是执行了AppRuntime类的onZygoteInit函数。

Step 10. AppRuntime.onZygoteInit
        这个函数定义在frameworks/base/cmds/app_process/app_main.cpp文件中:

[cpp] view plaincopy

  1. class AppRuntime : public AndroidRuntime
  2. {
  3. ......
  4. virtual void onZygoteInit()
  5. {
  6. sp<ProcessState> proc = ProcessState::self();
  7. if (proc->supportsProcesses()) {
  8. LOGV("App process: starting thread pool.\n");
  9. proc->startThreadPool();
  10. }
  11. }
  12. ......
  13. };

这里它就是调用ProcessState::startThreadPool启动线程池了,这个线程池中的线程就是用来和Binder驱动程序进行交互的了。
        Step 11. ProcessState.startThreadPool
        这个函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:

[cpp] view plaincopy

  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 plaincopy

  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 plaincopy

  1. class PoolThread : public Thread
  2. {
  3. public:
  4. PoolThread(bool isMain)
  5. : mIsMain(isMain)
  6. {
  7. }
  8. protected:
  9. virtual bool threadLoop()
  10. {
  11. IPCThreadState::self()->joinThreadPool(mIsMain);
  12. return false;
  13. }
  14. const bool mIsMain;
  15. };

这里它执行了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 plaincopy

  1. void IPCThreadState::joinThreadPool(bool isMain)
  2. {
  3. ......
  4. mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);
  5. ......
  6. status_t result;
  7. do {
  8. int32_t cmd;
  9. ......
  10. // now get the next command to be processed, waiting if necessary
  11. result = talkWithDriver();
  12. if (result >= NO_ERROR) {
  13. size_t IN = mIn.dataAvail();
  14. if (IN < sizeof(int32_t)) continue;
  15. cmd = mIn.readInt32();
  16. ......
  17. result = executeCommand(cmd);
  18. }
  19. ......
  20. } while (result != -ECONNREFUSED && result != -EBADF);
  21. ......
  22. mOut.writeInt32(BC_EXIT_LOOPER);
  23. talkWithDriver(false);
  24. }

这个函数首先告诉Binder驱动程序,这条线程要进入循环了:

[cpp] view plaincopy

  1. mOut.writeInt32(isMain ? BC_ENTER_LOOPER : BC_REGISTER_LOOPER);

然后在中间的while循环中通过talkWithDriver不断与Binder驱动程序进行交互,以便获得Client端的进程间调用:

[cpp] view plaincopy

  1. result = talkWithDriver();

获得了Client端的进程间调用后,就调用excuteCommand函数来处理这个请求:

[cpp] view plaincopy

  1. result = executeCommand(cmd);

最后,线程退出时,也会告诉Binder驱动程序,它退出了,这样Binder驱动程序就不会再在Client端的进程间调用分发给它了:

[cpp] view plaincopy

  1. mOut.writeInt32(BC_EXIT_LOOPER);
  2. talkWithDriver(false);

我们再来看看talkWithDriver函数的实现。

Step 15. talkWithDriver

这个函数定义在frameworks/base/libs/binder/IPCThreadState.cpp文件中:

[cpp] view plaincopy

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

这个函数的具体作用可以参考Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析一文,它只要就是通过ioctl文件操作函数来和Binder驱动程序交互的了:

[cpp] view plaincopy

  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 plaincopy

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

前面我们说过,这里传进来的参数className字符串值为"android.app.ActivityThread",这里就通ClassLoader.loadClass函数将它加载到进程中:

[java] view plaincopy

  1. cl = loader.loadClass(className);

然后获得它的静态成员函数main:

[java] view plaincopy

  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 plaincopy

  1. public class ZygoteInit {
  2. ......
  3. public static void main(String argv[]) {
  4. try {
  5. ......
  6. } catch (MethodAndArgsCaller caller) {
  7. caller.run();
  8. } catch (RuntimeException ex) {
  9. ......
  10. }
  11. }
  12. ......
  13. }

它执行MethodAndArgsCaller的run函数:

[java] view plaincopy

  1. public class ZygoteInit {
  2. ......
  3. public static class MethodAndArgsCaller extends Exception
  4. implements Runnable {
  5. /** method to call */
  6. private final Method mMethod;
  7. /** argument array */
  8. private final String[] mArgs;
  9. public MethodAndArgsCaller(Method method, String[] args) {
  10. mMethod = method;
  11. mArgs = args;
  12. }
  13. public void run() {
  14. try {
  15. mMethod.invoke(null, new Object[] { mArgs });
  16. } catch (IllegalAccessException ex) {
  17. ......
  18. } catch (InvocationTargetException ex) {
  19. ......
  20. }
  21. }
  22. }
  23. ......
  24. }

这里的成员变量mMethod和mArgs都是在前面构造异常对象时传进来的,这里的mMethod就对应android.app.ActivityThread类的main函数了,于是最后就通过下面语句执行这个函数:

[java] view plaincopy

  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 plaincopy

  1. public final class ActivityThread {
  2. ......
  3. public static final void main(String[] args) {
  4. SamplingProfilerIntegration.start();
  5. Process.setArgV0("<pre-initialized>");
  6. Looper.prepareMainLooper();
  7. if (sMainThreadHandler == null) {
  8. sMainThreadHandler = new Handler();
  9. }
  10. ActivityThread thread = new ActivityThread();
  11. thread.attach(false);
  12. if (false) {
  13. Looper.myLooper().setMessageLogging(new
  14. LogPrinter(Log.DEBUG, "ActivityThread"));
  15. }
  16. Looper.loop();
  17. if (Process.supportsProcesses()) {
  18. throw new RuntimeException("Main thread loop unexpectedly exited");
  19. }
  20. thread.detach();
  21. String name = (thread.mInitialApplication != null)
  22. ? thread.mInitialApplication.getPackageName()
  23. : "<unknown>";
  24. Slog.i(TAG, "Main thread of " + name + " is now exiting");
  25. }
  26. ......
  27. }

从这里我们可以看出,这个函数首先会在进程中创建一个ActivityThread对象:

[java] view plaincopy

  1. ActivityThread thread = new ActivityThread();

然后进入消息循环中:

[java] view plaincopy

  1. Looper.loop();

这样,我们以后就可以在这个进程中启动Activity或者Service了。

至此,Android应用程序进程启动过程的源代码就分析完成了,它除了指定新的进程的入口函数是ActivityThread的main函数之外,还为进程内的Binder对象提供了Binder进程间通信机制的基础设施,由此可见,Binder进程间通信机制在Android系统中是何等的重要,而且是无处不在,想进一步学习Android系统的Binder进程间通信机制,请参考Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。

时间: 2024-10-10 07:56:02

Android系统进程Zygote启动过程的源代码分析的相关文章

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

文章转载至CSDN社区罗升阳的安卓之旅,原文地址: http://blog.csdn.net/luoshengyang/article/details/6747696 Android 应用程序框架层创建的应用程序进程具有两个特点,一是进程的入口函数是ActivityThread.main,二是进程天然支持Binder进程间通信 机制:这两个特点都是在进程的初始化过程中实现的,本文将详细分析Android应用程序进程创建过程中是如何实现这两个特点的. Android应用程序框架层创建的应用程序进程

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

当我们在Launcher界面单击一个应用程序图标时就会启动一个程序,那这一个过程究竟发生了些哪样呢?让我们跟踪Launcher源码来分析一下吧. 先上流程图: step1.追踪Launcher  从源码中我们可以发现Launcher其实也是一个程序,它继承于Activity.找到该文件中的onCreate()方法,代码片段如下: protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceSta

Android内核开发:图解Android系统的启动过程

本文是<Android内核开发>系列的第六篇文章,前面的几篇文章介绍了Android内核开发相关的基础知识,包括:Android源码的下载.版本和分支介绍.编译和烧写等等,从本文起就要开始真正地进行Android内核的学习及实战了. 学习任何软硬件系统,研究系统启动过程都是一种非常有效地起步手段,搞Android内核开发也不例外.网上有很多文章对Android启动相关代码进行分析和走读,大家可以先搜索阅读一下,我个人更喜欢更加直观的方式去理解未知的东西,包括图.表.系统输出的log信息等等,因

Android之Zygote启动详解

我们知道Android系统是基于Linux内核的,在Linux系统中所有的进程都是init进程的子进程.Zygote也一样它是在系统启动的过程中由init进程创建的,在系统启动脚本init.rc中: <span style="font-size:14px;">@init.rc service zygote /syste/bin/app_process -Xzygote /system/bin -zygote --start-system-server class main

Android 中View的绘制机制源代码分析 三

到眼下为止,measure过程已经解说完了,今天開始我们就来学习layout过程.只是在学习layout过程之前.大家有没有发现我换了编辑器,哈哈.最终下定决心从Html编辑器切换为markdown编辑器.这里之所以使用"下定决心"这个词.是由于毕竟Html编辑器使用好几年了.非常多习惯都已经养成了,要改变多年的习惯确实不易.相信这也是还有非常多人坚持使用Html编辑器的原因. 这也反应了一个现象.当人对某一事物非常熟悉时,一旦出现了新的事物想代替老的事物时,人们都有一种抵触的情绪,做

Android系统的启动过程

当我们拿到一台Android的智能手机,从打开开关,到我们可以使用其中的app时,这个启动过程到底是怎么样的? 系统上电 当给Android系统上电,CPU复位之后,程序指针会指向启动地址,从该地址读取启动程序的可执行代码直接运行,或者将可执行代码与数据载入CPU内置的RAM中再运行. CPU复位,其实就是在电源接通的瞬间,CPU内的寄存器和各引脚均会被置为初始状态,并将程序指针指向引导程序的位置. 这一段代码,放在PC中,叫做BIOS,而在Android等嵌入式系统中就叫做Bootloader

quick cocos2d x 手机(Android端)启动过程学习

简要学习下quick cocos2d x 在安卓端启动的过程. 首先需要了解一点:quick cocos2d x是依托于Android的activity和GLSurfaceView(继承自SurfaceView)的环境来显示quick层的游戏界面. (1)首先quick类的android游戏从AndroidManifest.xml文件指定的activity(假设AC)启动. (2)AC继承父类的Cocos2dxActivity. (3)调用静态初始化块,加载cocos2dx的动态库.也就是一些C

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

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6689748 前文简要介绍了Android应用程序的Activity的启动过程.在Android系统中,应用程序是由Activity组成的,因此,应用程 序的启动过程实际上就是应用程序中的默认Activity的启动过程,本文将详细分析应用程序框架层的源代码,了解Android应用程序的启动过程. 在上一篇文章Android应用程序的Activit

Android Phone进程启动过程详解

之前解决一个开机搜网慢的问题时,发现由于Phone进程起来以后才会主动连接RILD,因而在一定程度上Phone进程启动的时间会影响网络状态注册的快慢.适当的将Phone进程提前,可以将网络注册时间提前一点,让状态栏中信号显示的时间提前.那么,Android中作为系统的核心进程之一,Phone进程是如何启动的了? RIL运行机制请参考: http://blog.csdn.net/jason_wzn/article/details/53232022 Telephony最开始创建的是PhoneFact