Android应用程序进程启动过程的源代码分析.docx
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文件中:view plain1. 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 这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:view plain1. 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文件中:view plain1. jboolean android_os_Process_supportsProcesses(JNIEnv* env, jobject clazz) 2. 3. return ProcessState:self()->supportsProcesses(); 4. ProcessState:supportsProcesses函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:view plain1. 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文件中:view plain1. 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(gidsi); 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文件中:view plain1. 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函数打开的:view plain1. 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文件中:view plain1. 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 FileDescriptor4; 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接口发送出去后,就会下面这个语句:view plain1. done = peers.get(index).runOnce(); 这里从peers.get(index)得到的是一个ZygoteConnection对象,表示一个Socket连接,因此,接下来就是调用ZygoteConnection.runOnce函数