博客同步至github博客:Zygote进程启动流程
使用到的相关源码:https://github.com/JesusYoung/AndroidResourceCode9.0/tree/master
基于Android 9.0
Zygote是在init进程启动时创建的,它又称为孵化器,它可以通过fork(复制进程)的形式来创建应用程序进程和SystemServer进程,并且,Zygote进程在启动的时候会创建DVM或者ART,因此通过fork而创建的应用程序进程和SystemServer进程可以在内部获取一个DVM或者ART的实例副本;
Init进程启动之后,解析init.rc配置文件,执行其配置,其中有启动Zygote进程的参数配置,在app_main.cpp的main()方法中,先解析参数,例如在前面解析.rc文件时添加的参数“–zygote、----start-system-server”等,初始化各种标识位;
int main(int argc, char* const argv[]) {
...
++i; // Skip unused "parent dir" argument.
while (i < argc) {
const char* arg = argv[i++];
if (strcmp(arg, "--zygote") == 0) {
zygote = true;
niceName = ZYGOTE_NICE_NAME;
} else if (strcmp(arg, "--start-system-server") == 0) {
startSystemServer = true;
} else if (strcmp(arg, "--application") == 0) {
application = true;
} else if (strncmp(arg, "--nice-name=", 12) == 0) {
niceName.setTo(arg + 12);
} else if (strncmp(arg, "--", 2) != 0) {
className.setTo(arg);
break;
} else {
--i;
break;
}
}
...
}
接着判断className是否为空,在Zygote模式下,调用maybeCreateDalvikCache()函数创建Dalvik虚拟机缓存,添加启动systemServer的参数标识;
int main(int argc, char* const argv[]) {
...
if (!className.isEmpty()) {
...
} else {
// We're in zygote mode.
maybeCreateDalvikCache();
if (startSystemServer) {
args.add(String8("start-system-server"));
}
char prop[PROP_VALUE_MAX];
if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.", ABI_LIST_PROPERTY);
return 11;
}
String8 abiFlag("--abi-list=");
abiFlag.append(prop);
args.add(abiFlag);
// In zygote mode, pass all remaining arguments to the zygote main() method.
// 在Zygote模式下,将剩余的参数全部传递过去
for (; i < argc; ++i) {
args.add(String8(argv[i]));
}
...
}
在main()函数中创建了AppRunTime对象,AppRunTime对象继承自AndroidRunTime类;
int main(int argc, char* const argv[]) {
...
AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
...
}
class AppRuntime : public AndroidRuntime {
public:
AppRuntime(char* argBlockStart, const size_t argBlockLength)
: AndroidRuntime(argBlockStart, argBlockLength) , mClass(NULL) {
}
...
}
随后调用AppRunTime类的start()方法来启动Zygote进程,在前面判断中得知zygote参数为true;
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
} else if (className) {
runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
} else {
...
}
AppRunTime类继承自AndroidRunTime类,AppRunTime类并没有重载start()方法,所以这里执行的是AndroidRunnTime类的start()方法;
首先会初始化一些环境rootDir等,然后会启动虚拟机,调用startReg()函数向虚拟机注册Android Native方法;
拿到前面传入的类名,即com.android.internal.os.ZygoteInit,通过JNI调用其main()方法,因为此处为C代码,而ZygoteInit为Java类,所以调用时需要使用JNI方式去调用,此时,正式从C层进入Java层;
class AppRuntime : public AndroidRuntime {}
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) {
...
// 启动虚拟机
if (startVm(&mJavaVM, &env, zygote) != 0) {
return;
}
...
// 向虚拟机注册Android Native方法
if (startReg(env) < 0) {
ALOGE("Unable to register all android natives\n");
return;
}
...
char* slashClassName = toSlashClassName(className != NULL ? className : "");
jclass startClass = env->FindClass(slashClassName);
if (startClass == NULL) {
...
} else {
// 找到main()方法
jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
if (startMeth == NULL) {
...
} else {
// 调用ZygoteInit类的main()方法
env->CallStaticVoidMethod(startClass, startMeth, strArray);
#if 0
if (env->ExceptionCheck())
threadExitUncaughtException(env);
#endif
}
}
...
}
Zygote进程启动,在ZygoteInit的main()方法中,通过调用ZygoteHooks类的startZygoteNoThreadCreation()函数来抛出异常,标识Zygote进程已经启动;
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
// Mark zygote start. This ensures that thread creation will throw
// an error.
ZygoteHooks.startZygoteNoThreadCreation();
...
}
在ZygoteInit的main()函数中,创建了ZygoteServer对象,作为Zygote进程的socket通信的服务端,名为zygote,用来接收SystemServer进程向Zygote进程发来的请求,例如AMS向Zygote进程请求创建新应用等,接着调用runSelectLoop()来等待SystemServer进程发来的请求;
public static void main(String argv[]) {
ZygoteServer zygoteServer = new ZygoteServer();
...
try {
...
zygoteServer.registerServerSocketFromEnv(socketName);
...
caller = zygoteServer.runSelectLoop(abiList);
}
...
if (caller != null) {
caller.run();
}
}
// ZygoteServer
void registerServerSocketFromEnv(String socketName) {
if (mServerSocket == null) {
int fileDesc;
final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
try {
String env = System.getenv(fullSocketName);
fileDesc = Integer.parseInt(env);
} catch (RuntimeException ex) {
throw new RuntimeException(fullSocketName + " unset or invalid", ex);
}
try {
FileDescriptor fd = new FileDescriptor();
fd.setInt$(fileDesc);
mServerSocket = new LocalServerSocket(fd);
mCloseSocketFd = true;
} catch (IOException ex) {
throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);
}
}
}
轮询客户端Socket消息,当客户端有新消息到来时,创建一个新的连接去执行客户端发来的请求,例如AMS请求创建新的进程;
新建一个peers列表,用于存储每个客户端的连接,将fd数据转存到poolFds中,遍历,当i=0时表示有客户端与服务端连接成功,此时执行acceptCommandPeer()方法拿到新的连接,并将其存入到peers集合中,当i>0时,表示客户端在向服务端传输数据,从peers中拿出与客户端的连接,执行processOneCommand()函数得到一个Runnable对象,如果是fork子进程并且任务不为null则返回该Runnable对象,在main()函数中,如果该对象不为空,就去执行其run()方法;
Runnable runSelectLoop(String abiList) {
ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
fds.add(mServerSocket.getFileDescriptor());
peers.add(null);
while (true) {
StructPollfd[] pollFds = new StructPollfd[fds.size()];
for (int i = 0; i < pollFds.length; ++i) {
pollFds[i] = new StructPollfd();
pollFds[i].fd = fds.get(i);
pollFds[i].events = (short) POLLIN;
}
...
for (int i = pollFds.length - 1; i >= 0; --i) {
...
if (i == 0) {
ZygoteConnection newPeer = acceptCommandPeer(abiList);
peers.add(newPeer);
fds.add(newPeer.getFileDesciptor());
} else {
try {
ZygoteConnection connection = peers.get(i);
final Runnable command = connection.processOneCommand(this);
if (mIsForkChild) {
// We're in the child. We should always have a command to run at this
// stage if processOneCommand hasn't called "exec".
if (command == null) {
throw new IllegalStateException("command == null");
}
return command;
} else {
// We're in the server - we should never have any commands to run.
if (command != null) {
throw new IllegalStateException("command != null");
}
// We don't know whether the remote side of the socket was closed or
// not until we attempt to read from it from processOneCommand. This shows up as
// a regular POLLIN event in our regular processing loop.
if (connection.isClosedByPeer()) {
connection.closeSocket();
peers.remove(i);
fds.remove(i);
}
}
}
...
}
}
}
}
执行processOneCommand()方法时,创建fork子进程的Runnable对象,如果是在父进程中,则返回null,子进程中则会返回fork子进程的Runnable对象,去执行fork操作,并且清除掉fork过来的父进程中的socket信息;
Runnable processOneCommand(ZygoteServer zygoteServer) {
...
pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids,
parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal,
parsedArgs.seInfo, parsedArgs.niceName, fdsToClose,
fdsToIgnore, parsedArgs.startChildZygote,
parsedArgs.instructionSet, parsedArgs.appDataDir);
try {
if (pid == 0) {
// in child
zygoteServer.setForkChild();
zygoteServer.closeServerSocket();
IoUtils.closeQuietly(serverPipeFd);
serverPipeFd = null;
return handleChildProc(parsedArgs, descriptors, childPipeFd, parsedArgs.startChildZygote);
} else {
// In the parent. A pid < 0 indicates a failure and will be handled in
// handleParentProc.
IoUtils.closeQuietly(childPipeFd);
childPipeFd = null;
handleParentProc(pid, descriptors, serverPipeFd);
return null;
}
...
}
Zygote进程启动后,执行ZygoteInit类的main()方法,启动会调用forkSystemServer()方法去通过fork自身的方式去创建SystemServer进程;
public static void main(String argv[]) {
...
try {
...
if (startSystemServer) {
Runnable r = forkSystemServer(abiList, socketName, zygoteServer);
// {@code r == null} in the parent (zygote) process, and {@code r != null} in the
// child (system_server) process.
if (r != null) {
r.run();
return;
}
}
...
}
...
}