本节是本系列文章的第二篇,将分析Zygote进程的启动过程。
第一篇文章:Android系统启动分析(一)
第三篇文章:Android系统启动分析(三)
二、Zygote进程启动
上节分析了Init进程的启动流程。本节将进入到framework层,分析Zygote进程的启动流程。
本节涉及到的文件有:
文件 |
路径 |
app_main.cpp |
framework/cmds/app_process/app_main.cpp |
AndroidRuntime.cpp |
frameworks/base/core/jni/AndroidRuntime.cpp |
ZygoteInit.java |
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java |
ZygoteServer.java |
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java |
2.1 app_main.main()
大家都知道Zygote进程相当于是Android的根进程,后面所有进程都是该进程fork出来的,而Zygote进程则是由Init进程fork而来。先看看Zygote进程是如何启动的。
进入到app_main的main()函数
framework/cmds/app_process/app_main.cpp |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| int main(int argc, char* const argv[]) { …… AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); …… 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; } } …… if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); …… } }
|
- 注释1处:将解析传进来的参数,由init.zygote64_32.rc文件可知,传进来的参数为:“-Xzygote /system/bin –zygote –start-system-server –socket-name=zygote”,因此argv[]数组大小为4,执行过注释1处的while循环后,zygote = true,startSystemServer = true
- 注释2处:将执行runtime.start(“com.android.internal.os.ZygoteInit”, args, zygote)
2.2 AppRuntime.start
framework/cmds/app_process/app_main.cpp |
AppRuntime定义在app_main.cpp中
1 2 3 4
| class AppRuntime : public AndroidRuntime { …… }
|
其父类为AndroidRuntime类,AppRuntime并没有实现start方法,因此前面的调用将会进入到AndroidRuntime的start()函数。
frameworks/base/core/jni/AndroidRuntime.cpp |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
| void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { …… const char* rootDir = getenv("ANDROID_ROOT"); if (rootDir == NULL) { rootDir = "/system"; if (!hasDir("/system")) { LOG_FATAL("No root directory specified, and /android does not exist."); return; } setenv("ANDROID_ROOT", rootDir, 1); }
JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; if (startVm(&mJavaVM, &env, zygote) != 0) { return; } onVmCreated(env);
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 { jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { …… } else { env->CallStaticVoidMethod(startClass, startMeth, strArray); } } free(slashClassName); if (mJavaVM->DetachCurrentThread() != JNI_OK) ALOGW("Warning: unable to detach main thread\n"); if (mJavaVM->DestroyJavaVM() != 0) ALOGW("Warning: VM did not shut down cleanly\n"); }
|
注释1处:jni_invocation.Init(NULL)初始化JNI,调用startVm() 创建Java虚拟机
注释2处:通过startReg()注册JNI函数,定义Android创建线程的函数:javaCreateThreadEtc
注释3处:toSlashClassName()将classname的”.”替换为”/“
注释4、5:通过JNI调用ZygoteInit.main()函数,至此,Zygote进程来到了Java代码。
2.3 ZygoteInit.main()
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
| public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer(); …… final Runnable caller; RuntimeInit.enableDdms();
boolean startSystemServer = false; String socketName = "zygote"; String abiList = null; boolean enableLazyPreload = false; for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if ("--enable-lazy-preload".equals(argv[i])) { enableLazyPreload = true; } else if (argv[i].startsWith(ABI_LIST_ARG)) { abiList = argv[i].substring(ABI_LIST_ARG.length()); } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { socketName = argv[i].substring(SOCKET_NAME_ARG.length()); } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } …… zygoteServer.registerServerSocket(socketName); if (!enableLazyPreload) { preload(bootTimingsTraceLog); } else { Zygote.resetNicePriority(); }
Zygote.nativeUnmountStorageOnInit(); ZygoteHooks.stopZygoteNoThreadCreation(); if (startSystemServer) { Runnable r = forkSystemServer(abiList, socketName, zygoteServer); if (r != null) { r.run(); return; } } caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { zygoteServer.closeServerSocket(); } if (caller != null) { caller.run(); } }
|
注释1处:设置DDMS可用,DDMS在Zygote进程刚刚开始启动时便已设置
注释2处:创建一个值为”zygote”的Socket服务端,可以看到这里Zygote作为Server端,处理客户端的请求
注释3处:初始化Zygote中需要的Class类,初始化各类系统资源和库
注释4处:fork一个SystemServer进程
注释5处:调用ZygoteServer的runSelectLoop方法等待客户端(AMS)的创建新进程的请求点我跳转
2.3.1 registerServerSocket
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| void registerServerSocket(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); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } }
|
2.3.2 预加载类和资源 preload()
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| static void preload(TimingsTraceLog bootTimingsTraceLog) { preloadClasses(); preloadResources(); nativePreloadAppProcessHALs(); preloadOpenGL(); preloadSharedLibraries(); preloadTextResources(); WebViewFactory.prepareWebViewInZygote(); warmUpJcaProviders(); }
|
2.3.3 forkSystemServer()
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) { …… String args[] = { "--setuid=1000", "--setgid=1000", "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,1023,1032,3001,3002,3003,3006,3007,3009,3010", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } if (pid == 0) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } zygoteServer.closeServerSocket(); return handleSystemServerProcess(parsedArgs); } return null; }
|
注释1处:准备一些SystemServer进程的启动参数,类名为:com.android.server.SystemServer
注释2处:将启动参数封装到ZygoteConnection.Arguments中,具体在ZygoteConnection#parseArgs(),这里不再详细分析。
注释3处:调用Zygote.forkSystemServer(),可以看到SystemServer进程是被Zygote进程fork而来。最后会通过native方法nativeForkSystemServer()创建新进程。关于nativeForkSystemServer()的实现,可见frameworks/base/core/jni/com_android_internal_os_Zygote.cpp
注释4处:如果注释3处返回的pid == 0,则此时代码逻辑运行在子进程中,这里会调用handleSystemServerProcess()来处理SystemServer进程。
关于SysetmServer进程,将在第三节分析。点我跳转
2.3.4 runSelectLoop()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
| 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; } try { Os.poll(pollFds, -1); } catch (ErrnoException ex) { throw new RuntimeException("poll failed", ex); } for (int i = pollFds.length - 1; i >= 0; --i) { if ((pollFds[i].revents & POLLIN) == 0) { continue; }
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) { …… return command; } } catch (Exception e) { …… } } } } }
|
注释1处:添加服务端的文件描述符到fds集合中,文件描述符是在ZygoteServer.registerServerSocket()中创建,并封装给LocalServerSocket
注释2处:该处语句会阻塞,若fd发生变化,则解除阻塞状态
注释3处:若注释2处的语句解除阻塞,则会执行该处的for循环
注释4处: i==0时,意味着有客户端连接请求,创建新连接并处理请求
注释5处: i>0,说明客户端(AMS)向Zygote发送了一个创建应用进程的请求,processOneCommand()方法会调用Zygote.forkAndSpecialize() fork一个新的VM实例,最终会进入到com_android_internal_os_Zygote.nativeForkAndSpecialize()函数。由于篇幅限制,这里不做过多介绍,感兴趣的读者可以自己去看。
2.4 Zygote进程启动总结
Zygote进程启动过程中主要做了以下几件事:
- 调用AppRuntime.start()方法创建Java虚拟机,注册JNI函数
- 通过JNI调用ZygoteInit.main()方法
- 创建一个值为”zygote”的Socket服务端
- 预加载类和资源
- 创建SystemServer进程,并通过runSelectLoop()进入死循环监听Socket消息
Zygote进程的启动分析到这里结束。下一节将介绍SystemServer进程的启动过程。
Android系统启动分析(三)