赞
踩
在Android系统中,所有的应用程序进程都是有Zygote进程创建的。那么,到底是如何创建出来的呢?本节来分析一下这个创建流程。
在Android初始化流程中,init进程创建了zygote进程,(通过init.rc中的指令),而且,在zygote这个进程中,注册了zygote socket, 而且,会根据是否是ZYGOTE_FORK_MODE模式,去执行zygote的创建,或进入selectLoop监听循环中,代码在ZygoteInit.java中,如下:
- public static void main(String argv[]) {
-
- ......
-
- registerZygoteSocket();
-
- ......
-
- if (argv[1].equals("start-system-server")) {
- startSystemServer();
- } else if (!argv[1].equals("")) {
- throw new RuntimeException(argv[0] + USAGE_STRING);
- }
- if (ZYGOTE_FORK_MODE) {
- runForkMode();
- } else {
- runSelectLoopMode();
- }
-
-
- }

ZYGOTE_FORK_MODE的定义:
private static final boolean ZYGOTE_FORK_MODE = false;
所以,会执行到runSelectLoopMode,即在创建了SystemServer进程之后,就进入了这个runSelectLoopMode方法的执行。
从runSelectLoopMode开始分析:
- 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);
- }
- }
- }
- }

分析:
1)通过前面注册的socket来获取文件描述符,通过这个描述符来处理来自外部的请求;这个描述符什么时候创建的呢?看下面的代码(ZygoteInit.java的registerZygoteSocket方法:
- private static void registerZygoteSocket() {
- if (sServerSocket == null) {
- int fileDesc;
- try {
- String env = System.getenv(ANDROID_SOCKET_ENV);
- fileDesc = Integer.parseInt(env);
- } catch (RuntimeException ex) {
- throw new RuntimeException(
- ANDROID_SOCKET_ENV + " unset or invalid", ex);
- }
-
- try {
- sServerSocket = new LocalServerSocket(
- createFileDescriptor(fileDesc));
- } catch (IOException ex) {
- throw new RuntimeException(
- "Error binding to local socket '" + fileDesc + "'", ex);
- }
- }
- }

这里的
sServerSocket = new LocalServerSocket(
createFileDescriptor(fileDesc));
在初始化sServerSocket的时候,创建了FileDescriptor,即
ANDROID_SOCKET_ENV
环境变量对应的文件描述符,ANDROID_SOCKET_ENV的定义:
private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote";
2)selectReadable:这是一个native方法,用于监视文件描述符,如果文件描述符中有相关的事件,则返回文件描述符在数组中的索引index。其实就是找到有事件发生的文件描述符。那么,如何监听呢?答案就是通过Linux系统调用select函数来实现;
3)根据index去创建ZygoteConnection,并且保存起来;
4)执行ZygoteConnection实例的runOnce方法。这是个关键函数,是创建应用程序进程的入口。
整个流程涉及到java和native,时序图如下(分为java层和native层)如下:
java层时序图:
select函数的功能:
它可以同时监听多个socket描述符,并且知道哪一个socket描述符已经可以读取数据了,哪个描述符可以 写入数据,以及哪个socket出现了错误。这里的socket描述符也是文件的一种。
Native层时序图:
从java的forkAndSpecialize()调用到native层的forkAndSpecializeCommon()方法中,而在这个方法中,最终,通过fork系统调用创建了一个新的进程,这个进程就是用用程序进程。
forkAndSpecializeCommon()的fork:
在forkAndSpecializeCommon()中,fork的调用如下:
- static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer)
- {
- pid_t pid;
-
- ......
-
- pid = fork();
-
- if (pid == 0) {
-
- /* The child process */
-
- ......
- } else if (pid > 0) {
- /* the parent process */
- }
-
- return pid;
- }

可见,典型的pid处理方式:如果pid == 0,即当前处于子进程;如果pid>0,即处于父进程。
再看一下主要代码文件列表:
1)相关代码文件:
Java代码:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java
libcore/dalvik/src/main/java/dalvik/system/Zygote.javaNative代码:
frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp
dalvik/vm/native/dalvik_system_Zygote.cpp
代码目录结构:
2)ZygoteInit中jni方法的注册:
frameworks/base/core/jni/com_android_internal_os_ZygoteInit.cpp中,
- static JNINativeMethod gMethods[] = {
- /* name, signature, funcPtr */
- { "setreuid", "(II)I",
- (void*) com_android_internal_os_ZygoteInit_setreuid },
- { "setregid", "(II)I",
- (void*) com_android_internal_os_ZygoteInit_setregid },
- { "setpgid", "(II)I",
- (void *) com_android_internal_os_ZygoteInit_setpgid },
- { "getpgid", "(I)I",
- (void *) com_android_internal_os_ZygoteInit_getpgid },
- { "reopenStdio",
- "(Ljava/io/FileDescriptor;Ljava/io/FileDescriptor;"
- "Ljava/io/FileDescriptor;)V",
- (void *) com_android_internal_os_ZygoteInit_reopenStdio},
- { "setCloseOnExec", "(Ljava/io/FileDescriptor;Z)V",
- (void *) com_android_internal_os_ZygoteInit_setCloseOnExec},
- { "setCapabilities", "(JJ)V",
- (void *) com_android_internal_os_ZygoteInit_setCapabilities },
- { "capgetPermitted", "(I)J",
- (void *) com_android_internal_os_ZygoteInit_capgetPermitted },
- { "selectReadable", "([Ljava/io/FileDescriptor;)I",
- (void *) com_android_internal_os_ZygoteInit_selectReadable },
- { "createFileDescriptor", "(I)Ljava/io/FileDescriptor;",
- (void *) com_android_internal_os_ZygoteInit_createFileDescriptor }
- };
- int register_com_android_internal_os_ZygoteInit(JNIEnv* env)
- {
- return AndroidRuntime::registerNativeMethods(env,
- "com/android/internal/os/ZygoteInit", gMethods, NELEM(gMethods));
- }

3)Zygote的jni方法的注册;
dalvik/vm/native/dalvik_system_Zygote.cpp中,
- const DalvikNativeMethod dvm_dalvik_system_Zygote[] = {
- { "nativeFork", "()I",
- Dalvik_dalvik_system_Zygote_fork },
- { "nativeForkAndSpecialize", "(II[II[[I)I",
- Dalvik_dalvik_system_Zygote_forkAndSpecialize },
- { "nativeForkSystemServer", "(II[II[[IJJ)I",
- Dalvik_dalvik_system_Zygote_forkSystemServer },
- { "nativeExecShell", "(Ljava/lang/String;)V",
- Dalvik_dalvik_system_Zygote_execShell },
- { NULL, NULL, NULL },
- };
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。