简介:
在Android系统中,所有的应用程序进程都是有Zygote进程创建的。那么,到底是如何创建出来的呢?本节来分析一下这个创建流程。
ZygoteInit代码回顾:
在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 },
};