版权声明:本文为博主原创文章,未经博主允许不得转载。
在Android系统中,所有的应用程序进程以及系统服务进程SystemServer都是由Zygote进程孕育(fork)出来的,这也许就是为什么要把它称为Zygote(受精卵)的原因吧。由于Zygote进程在Android系统中有着如此重要的地位,本文将详细分析它的启动过程。
在前面一篇文章Android应用程序进程启动过程的源代码分析中,我们看到了,当ActivityManagerService启动一个应用程序的时候,就会通过Socket与Zygote进程进行通信,请求它fork一个子进程出来作为这个即将要启动的应用程序的进程;在前面两篇文章Android应用程序安装过程源代码分析和Android系统默认Home应用程序(Launcher)的启动过程源代码分析中,我们又看到了,系统中的两个重要服务PackageManagerService和ActivityManagerService,都是由SystemServer进程来负责启动的,而SystemServer进程本身是Zygote进程在启动的过程中fork出来的。
我们知道,Android系统是基于Linux内核的,而在Linux系统中,所有的进程都是init进程的子孙进程,也就是说,所有的进程都是直接或者间接地由init进程fork出来的。Zygote进程也不例外,它是在系统启动的过程,由init进程创建的。在系统启动脚本system/core/rootdir/init.rc文件中,我们可以看到启动Zygote进程的脚本命令:
- service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server
- socket zygote stream 666
- onrestart write /sys/android_power/request_state wake
- onrestart write /sys/power/state on
- onrestart restart media
- onrestart restart netd
接下来的socket关键字表示这个zygote进程需要一个名称为"zygote"的socket资源,这样,系统启动后,我们就可以在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来作本地进程间通信用的,具体可以参考前面一篇文章Android学习启动篇提到的一书《Linux内核源代码情景分析》的第七章--基于socket的进程间通信。前面我们说到的ActivityManagerService就是通这个socket来和zygote进程通信请求fork一个应用程序进程的了。
最后的一系列onrestart关键字表示这个zygote进程重启时需要执行的命令。
关于init.rc文件的更多信息,请参考system/core/init/readme.txt文件。
了解了这个信息之后,我们就知道Zygote进程要执行的程序便是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。在继续分析Zygote进程启动的过程之前,我们先来看看它的启动序列图:
下面我们就详细分析每一个步骤。
Step 1. app_process.main
这个函数定义在frameworks/base/cmds/app_process/app_main.cpp文件中:
- int main(int argc, const char* const argv[])
- {
- // These are global variables in ProcessState.cpp
- mArgC = argc;
- mArgV = argv;
- mArgLen = 0;
- for (int i=0; i<argc; i++) {
- mArgLen += strlen(argv[i]) + 1;
- }
- mArgLen--;
- AppRuntime runtime;
- const char *arg;
- argv0 = argv[0];
- // Process command line arguments
- // ignore argv[0]
- argc--;
- argv++;
- // Everything up to '--' or first non '-' arg goes to the vm
- int i = runtime.addVmArguments(argc, argv);
- // Next arg is parent directory
- if (i < argc) {
- runtime.mParentDir = argv[i++];
- }
- // Next arg is startup classname or "--zygote"
- if (i < argc) {
- arg = argv[i++];
- if (0 == strcmp("--zygote", arg)) {
- bool startSystemServer = (i < argc) ?
- strcmp(argv[i], "--start-system-server") == 0 : false;
- setArgv0(argv0, "zygote");
- set_process_name("zygote");
- runtime.start("com.android.internal.os.ZygoteInit",
- startSystemServer);
- } else {
- set_process_name(argv0);
- runtime.mClassName = arg;
- // Remainder of args get passed to startup class main()
- runtime.mArgC = argc-i;
- runtime.mArgV = argv+i;
- LOGV("App process is starting with pid=%d, class=%s.\n",
- getpid(), runtime.getClassName());
- runtime.start();
- }
- } else {
- LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
- fprintf(stderr, "Error: no class name or --zygote supplied.\n");
- app_usage();
- return 10;
- }
- }
- class AppRuntime : public AndroidRuntime
- {
- ......
- };
- ......
- static AndroidRuntime* gCurRuntime = NULL;
- ......
- AndroidRuntime::AndroidRuntime()
- {
- ......
- assert(gCurRuntime == NULL); // one per process
- gCurRuntime = this;
- }
- AndroidRuntime* AndroidRuntime::getRuntime()
- {
- return gCurRuntime;
- }
- runtime.start("com.android.internal.os.ZygoteInit",
- rtSystemServer);
Step 2. AndroidRuntime.start
这个函数定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:
- /*
- * Start the Android runtime. This involves starting the virtual machine
- * and calling the "static void main(String[] args)" method in the class
- * named by "className".
- */
- void AndroidRuntime::start(const char* className, const bool startSystemServer)
- {
- ......
- char* slashClassName = NULL;
- char* cp;
- JNIEnv* env;
- ......
- /* start the virtual machine */
- if (startVm(&mJavaVM, &env) != 0)
- goto bail;
- /*
- * Register android functions.
- */
- if (startReg(env) < 0) {
- LOGE("Unable to register all android natives\n");
- goto bail;
- }
- /*
- * We want to call main() with a String array with arguments in it.
- * At present we only have one argument, the class name. Create an
- * array to hold it.
- */
- jclass stringClass;
- jobjectArray strArray;
- jstring classNameStr;
- jstring startSystemServerStr;
- stringClass = env->FindClass("java/lang/String");
- assert(stringClass != NULL);
- strArray = env->NewObjectArray(2, stringClass, NULL);
- assert(strArray != NULL);
- classNameStr = env->NewStringUTF(className);
- assert(classNameStr != NULL);
- env->SetObjectArrayElement(strArray, 0, classNameStr);
- startSystemServerStr = env->NewStringUTF(startSystemServer ?
- "true" : "false");
- env->SetObjectArrayElement(strArray, 1, startSystemServerStr);
- /*
- * Start VM. This thread becomes the main thread of the VM, and will
- * not return until the VM exits.
- */
- jclass startClass;
- jmethodID startMeth;
- slashClassName = strdup(className);
- for (cp = slashClassName; *cp != '\0'; cp++)
- if (*cp == '.')
- *cp = '/';
- startClass = env->FindClass(slashClassName);
- if (startClass == NULL) {
- ......
- } else {
- startMeth = env->GetStaticMethodID(startClass, "main",
- "([Ljava/lang/String;)V");
- if (startMeth == NULL) {
- ......
- } else {
- env->CallStaticVoidMethod(startClass, startMeth, strArray);
- ......
- }
- }
- ......
- }
这个函数的作用是启动Android系统运行时库,它主要做了三件事情,一是调用函数startVM启动虚拟机,二是调用函数startReg注册JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。
Step 3. ZygoteInit.main
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
- public class ZygoteInit {
- ......
- public static void main(String argv[]) {
- try {
- ......
- registerZygoteSocket();
- ......
- ......
- if (argv[1].equals("true")) {
- startSystemServer();
- } else if (!argv[1].equals("false")) {
- ......
- }
- ......
- if (ZYGOTE_FORK_MODE) {
- ......
- } else {
- runSelectLoopMode();
- }
- ......
- } catch (MethodAndArgsCaller caller) {
- ......
- } catch (RuntimeException ex) {
- ......
- }
- }
- ......
- }
Step 4. ZygoteInit.registerZygoteSocket
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
- public class ZygoteInit {
- ......
- /**
- * Registers a server socket for zygote command connections
- *
- * @throws RuntimeException when open fails
- */
- private static void registerZygoteSocket() {
- if (sServerSocket == null) {
- int fileDesc;
- try {
- String env = System.getenv(ANDROID_SOCKET_ENV);
- fileDesc = Integer.parseInt(env);
- } catch (RuntimeException ex) {
- ......
- }
- try {
- sServerSocket = new LocalServerSocket(
- createFileDescriptor(fileDesc));
- } catch (IOException ex) {
- .......
- }
- }
- }
- ......
- }
- public class ZygoteInit {
- ......
- private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
- ......
- }
- void service_start(struct service *svc, const char *dynamic_args)
- {
- ......
- pid_t pid;
- ......
- pid = fork();
- if (pid == 0) {
- struct socketinfo *si;
- ......
- for (si = svc->sockets; si; si = si->next) {
- int socket_type = (
- !strcmp(si->type, "stream") ? SOCK_STREAM :
- (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET));
- int s = create_socket(si->name, socket_type,
- si->perm, si->uid, si->gid);
- if (s >= 0) {
- publish_socket(si->name, s);
- }
- }
- ......
- }
- ......
- }
- static void publish_socket(const char *name, int fd)
- {
- char key[64] = ANDROID_SOCKET_ENV_PREFIX;
- char val[64];
- strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1,
- name,
- sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX));
- snprintf(val, sizeof(val), "%d", fd);
- add_environment(key, val);
- /* make sure we don't close-on-exec */
- fcntl(fd, F_SETFD, 0);
- }
- #define ANDROID_SOCKET_ENV_PREFIX "ANDROID_SOCKET_"
- public class Process {
- ......
- private static void openZygoteSocketIfNeeded()
- throws ZygoteStartFailedEx {
- ......
- for (int retry = 0
- ; (sZygoteSocket == null) && (retry < (retryCount + 1))
- ; retry++ ) {
- ......
- 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);
- ......
- } catch (IOException ex) {
- ......
- }
- }
- ......
- }
- ......
- }
- public class Process {
- ......
- private static final String ZYGOTE_SOCKET = "zygote";
- ......
- }
Android系统中的socket机制和binder机制一样,都是可以用来进行进程间通信,读者可以自己对比一下这两者的不同之处,Binder进程间通信机制可以参考Android进程间通信(IPC)机制Binder简要介绍和学习计划一文。
Socket对象创建完成之后,回到Step 3中的ZygoteInit.main函数中,startSystemServer函数来启动SystemServer组件。
Step 5. ZygoteInit.startSystemServer
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
- public class ZygoteInit {
- ......
- private static boolean startSystemServer()
- throws MethodAndArgsCaller, RuntimeException {
- /* Hardcoded command line to start the system server */
- String args[] = {
- "--setuid=1000",
- "--setgid=1000",
- "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,3001,3002,3003",
- "--capabilities=130104352,130104352",
- "--runtime-init",
- "--nice-name=system_server",
- "com.android.server.SystemServer",
- };
- ZygoteConnection.Arguments parsedArgs = null;
- int pid;
- try {
- parsedArgs = new ZygoteConnection.Arguments(args);
- ......
- /* Request to fork the system server process */
- pid = Zygote.forkSystemServer(
- parsedArgs.uid, parsedArgs.gid,
- parsedArgs.gids, debugFlags, null,
- parsedArgs.permittedCapabilities,
- parsedArgs.effectiveCapabilities);
- } catch (IllegalArgumentException ex) {
- ......
- }
- /* For child process */
- if (pid == 0) {
- handleSystemServerProcess(parsedArgs);
- }
- return true;
- }
- ......
- }
Step 6. ZygoteInit.handleSystemServerProcess
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
- public class ZygoteInit {
- ......
- private static void handleSystemServerProcess(
- ZygoteConnection.Arguments parsedArgs)
- throws ZygoteInit.MethodAndArgsCaller {
- closeServerSocket();
- /*
- * Pass the remaining arguments to SystemServer.
- * "--nice-name=system_server com.android.server.SystemServer"
- */
- RuntimeInit.zygoteInit(parsedArgs.remainingArgs);
- /* should never reach here */
- }
- ......
- }
Step 7. RuntimeInit.zygoteInit
这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
- public class RuntimeInit {
- ......
- public static final void zygoteInit(String[] argv)
- throws ZygoteInit.MethodAndArgsCaller {
- ......
- zygoteInitNative();
- ......
- // Remaining arguments are passed to the start class's static main
- String startClass = argv[curArg++];
- String[] startArgs = new String[argv.length - curArg];
- System.arraycopy(argv, curArg, startArgs, 0, startArgs.length);
- invokeStaticMain(startClass, startArgs);
- }
- ......
- }
Step 8. RuntimeInit.zygoteInitNative
这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:
- public class RuntimeInit {
- ......
- public static final native void zygoteInitNative();
- ......
- }
回到Step 7中的RuntimeInit.zygoteInitNative函数,下一步它就要执行com.android.server.SystemServer类的main函数了。
Step 9. SystemServer.main
这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中:
- public class SystemServer
- {
- ......
- native public static void init1(String[] args);
- ......
- public static void main(String[] args) {
- ......
- init1(args);
- ......
- }
- public static final void init2() {
- Slog.i(TAG, "Entered the Android system server!");
- Thread thr = new ServerThread();
- thr.setName("android.server.ServerThread");
- thr.start();
- }
- ......
- }
这一步的具体执行过程可以参考 Android应用程序安装过程源代码分析 一文,这里就不再详述了。
这里执行完成后,层层返回,最后回到上面的Step 3中的ZygoteInit.main函数中,接下来它就要调用runSelectLoopMode函数进入一个无限循环在前面Step 4中创建的socket接口上等待ActivityManagerService请求创建新的应用程序进程了。
Step 10. ZygoteInit.runSelectLoopMode
这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:
- public class ZygoteInit {
- ......
- private static void runSelectLoopMode() throws MethodAndArgsCaller {
- ArrayList<FileDescriptor> fds = new ArrayList();
- ArrayList<ZygoteConnection> peers = new ArrayList();
- FileDescriptor[] fdArray = new FileDescriptor[4];
- fds.add(sServerSocket.getFileDescriptor());
- peers.add(null);
- int loopCount = GC_LOOP_COUNT;
- while (true) {
- int index;
- ......
- try {
- fdArray = fds.toArray(fdArray);
- index = selectReadable(fdArray);
- } catch (IOException ex) {
- throw new RuntimeException("Error in select()", ex);
- }
- if (index < 0) {
- throw new RuntimeException("Error in select()");
- } else if (index == 0) {
- ZygoteConnection newPeer = acceptCommandPeer();
- peers.add(newPeer);
- fds.add(newPeer.getFileDesciptor());
- } else {
- boolean done;
- done = peers.get(index).runOnce();
- if (done) {
- peers.remove(index);
- fds.remove(index);
- }
- }
- }
- }
- ......
- }
这样,Zygote进程就启动完成了,学习到这里,我们终于都对Android系统中的进程有了一个深刻的认识了,这里总结一下:
1. 系统启动时init进程会创建Zygote进程,Zygote进程负责后续Android应用程序框架层的其它进程的创建和启动工作。
2. Zygote进程会首先创建一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。
3. 当我们需要启动一个Android应用程序时,ActivityManagerService会通过Socket进程间通信机制,通知Zygote进程为这个应用程序创建一个新的进程。
老罗的新浪微博:http://weibo.com/shengyangluo,欢迎关注!