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文件中:
- public final class ActivityManagerService extends ActivityManagerNative
- implements Watchdog.Monitor, BatteryStatsImpl.BatteryCallback {
- ......
- private final void startProcessLocked(Proce***ecord app,
- String hostingType, String hostingNameStr) {
- ......
- try {
- int uid = app.info.uid;
- int[] gids = null;
- try {
- gids = mContext.getPackageManager().getPackageGids(
- app.info.packageName);
- } catch (PackageManager.NameNotFoundException e) {
- ......
- }
- ......
- int debugFlags = 0;
- ......
- int pid = Process.start("android.app.ActivityThread",
- mSimpleProcessManagement ? app.processName : null, uid, uid,
- gids, debugFlags, null);
- ......
- } catch (RuntimeException e) {
- ......
- }
- }
- ......
- }
它调用了Process.start函数开始为应用程序创建新的进程,注意,它传入一个第一个参数为"android.app.ActivityThread",这就是进程初始化时要加载的Java类了,把这个类加载到进程之后,就会把它里面的静态成员函数main作为进程的入口点,后面我们会看到。
Step 2. Process.start
这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:
- public class Process {
- ......
- public static final int start(final String processClass,
- final String niceName,
- int uid, int gid, int[] gids,
- int debugFlags,
- String[] zygoteArgs)
- {
- if (supportsProcesses()) {
- try {
- return startViaZygote(processClass, niceName, uid, gid, gids,
- debugFlags, zygoteArgs);
- } catch (ZygoteStartFailedEx ex) {
- ......
- }
- } else {
- ......
- return 0;
- }
- }
- ......
- }
这里的supportsProcesses函数返回值为true,它是一个Native函数,实现在frameworks/base/core/jni/android_util_Process.cpp文件中:
- jboolean android_os_Process_supportsProcesses(JNIEnv* env, jobject clazz)
- {
- return ProcessState::self()->supportsProcesses();
- }
ProcessState::supportsProcesses函数定义在frameworks/base/libs/binder/ProcessState.cpp文件中:
- bool ProcessState::supportsProcesses() const
- {
- return mDriverFD >= 0;
- }
这里的mDriverFD是设备文件/dev/binder的打开描述符,如果成功打开了这个设备文件,那么它的值就会大于等于0,因此,它的返回值为true。
回到Process.start函数中,它调用startViaZygote函数进一步操作。
Step 3. Process.startViaZygote
这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:
- public class Process {
- ......
- private static int startViaZygote(final String processClass,
- final String niceName,
- final int uid, final int gid,
- final int[] gids,
- int debugFlags,
- String[] extraArgs)
- throws ZygoteStartFailedEx {
- int pid;
- synchronized(Process.class) {
- ArrayList<String> argsForZygote = new ArrayList<String>();
- // --runtime-init, --setuid=, --setgid=,
- // and --setgroups= must go first
- argsForZygote.add("--runtime-init");
- argsForZygote.add("--setuid=" + uid);
- argsForZygote.add("--setgid=" + gid);
- if ((debugFlags & Zygote.DEBUG_ENABLE_SAFEMODE) != 0) {
- argsForZygote.add("--enable-safemode");
- }
- if ((debugFlags & Zygote.DEBUG_ENABLE_DEBUGGER) != 0) {
- argsForZygote.add("--enable-debugger");
- }
- if ((debugFlags & Zygote.DEBUG_ENABLE_CHECKJNI) != 0) {
- argsForZygote.add("--enable-checkjni");
- }
- if ((debugFlags & Zygote.DEBUG_ENABLE_ASSERT) != 0) {
- argsForZygote.add("--enable-assert");
- }
- //TODO optionally enable debuger
- //argsForZygote.add("--enable-debugger");
- // --setgroups is a comma-separated list
- if (gids != null && gids.length > 0) {
- StringBuilder sb = new StringBuilder();
- sb.append("--setgroups=");
- int sz = gids.length;
- for (int i = 0; i < sz; i++) {
- if (i != 0) {
- sb.append(',');
- }
- sb.append(gids[i]);
- }
- argsForZygote.add(sb.toString());
- }
- if (niceName != null) {
- argsForZygote.add("--nice-name=" + niceName);
- }
- argsForZygote.add(processClass);
- if (extraArgs != null) {
- for (String arg : extraArgs) {
- argsForZygote.add(arg);
- }
- }
- pid = zygoteSendArgsAndGetPid(argsForZygote);
- }
- }
- ......
- }
这个函数将创建进程的参数放到argsForZygote列表中去,如参数"--runtime-init"表示要为新创建的进程初始化运行时库,然后调用zygoteSendAndGetPid函数进一步操作。
Step 4. Process.zygoteSendAndGetPid
这个函数定义在frameworks/base/core/java/android/os/Process.java文件中:
- public class Process {
- ......
- private static int zygoteSendArgsAndGetPid(ArrayList<String> args)
- throws ZygoteStartFailedEx {
- int pid;
- openZygoteSocketIfNeeded();
- try {
- /**
- * See com.android.internal.os.ZygoteInit.readArgumentList()
- * Presently the wire format to the zygote process is:
- * a) a count of arguments (argc, in essence)
- * b) a number of newline-separated argument strings equal to count
- *
- * After the zygote process reads these it will write the pid of
- * the child or -1 on failure.
- */
- sZygoteWriter.write(Integer.toString(args.size()));
- sZygoteWriter.newLine();
- int sz = args.size();
- for (int i = 0; i < sz; i++) {
- String arg = args.get(i);
- if (arg.indexOf('\n') >= 0) {
- throw new ZygoteStartFailedEx(
- "embedded newlines not allowed");
- }
- sZygoteWriter.write(arg);
- sZygoteWriter.newLine();
- }
- sZygoteWriter.flush();
- // Should there be a timeout on this?
- pid = sZygoteInputStream.readInt();
- if (pid < 0) {
- throw new ZygoteStartFailedEx("fork() failed");
- }
- } catch (IOException ex) {
- ......
- }
- return pid;
- }
- ......
- }
这里的sZygoteWriter是一个Socket写入流,是由openZygoteSocketIfNeeded函数打开的:
- public class Process {
- ......
- /**
- * Tries to open socket to Zygote process if not already open. If
- * already open, does nothing. May block and retry.
- */
- private static void openZygoteSocketIfNeeded()
- throws ZygoteStartFailedEx {
- int retryCount;
- if (sPreviousZygoteOpenFailed) {
- /*
- * If we've failed before, expect that we'll fail again and
- * don't pause for retries.
- */
- retryCount = 0;
- } else {
- retryCount = 10;
- }
- /*
- * See bug #811181: Sometimes runtime can make it up before zygote.
- * Really, we'd like to do something better to avoid this condition,
- * but for now just wait a bit...
- */
- for (int retry = 0
- ; (sZygoteSocket == null) && (retry < (retryCount + 1))
- ; retry++ ) {
- if (retry > 0) {
- try {
- Log.i("Zygote", "Zygote not up yet, sleeping...");
- Thread.sleep(ZYGOTE_RETRY_MILLIS);
- } catch (InterruptedException ex) {
- // should never happen
- }
- }
- try {
- sZygoteSocket = new LocalSocket();
- sZygoteSocket.connect(new LocalSocketAddress(ZYGOTE_SOCKET,
- LocalSocketAddress.Namespace.RESERVED));
- sZygoteInputStream
- = new DataInputStream(sZygoteSocket.getInputStream());
- sZygoteWriter =
- new BufferedWriter(
- new OutputStreamWriter(
- sZygoteSocket.getOutputStream()),
- 256);
- Log.i("Zygote", "Process: zygote socket opened");
- sPreviousZygoteOpenFailed = false;
- break;
- } catch (IOException ex) {
- ......
- }
- }
- ......
- }
- ......
- }
这个Socket由frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中的ZygoteInit类在runSelectLoopMode函数侦听的。