
本文共 34789 字,大约阅读时间需要 115 分钟。
一 概述
上一篇文章分析了 init 进程的整个启动流程。init 进程启动后,会解析 rc 文件,然后启动很多进程,其中很重要的一个进程就是 zygote 进程,zygote 进程又称受精卵进程, 所对应的可执行程序为 app_process,所对应的源文件是 app_main.cpp,进程名为 zygote,zygote 是 Android 系统创建的第一个 java 进程,它是所有 java 进程的父进程,zygote 进程最大意义是作为一个 Socket 的 Server 端,接收着来自四面八方的其它进程发出的进程创建请求,Android 中所有的应用进程的创建都是由一个应用进程通过 Binder 发送请求给 SystemServer 进程,SystemServer 进程再发送 Socket 消息给 zygote 进程,统一由 zygote 进程创建出来的。典型的 C/S 架构.下图为 zygote 进程在系统中的地位,其中图中红色标注为 Binder 通信方式,蓝色标注为 Socket 通信方式.
话说为什么 Android 系统采用这种架构呢,为什么所有进程的创建都是由 zygote 来做呢?原因有如下两点:
- zygote 进程在启动的时候会创建一个虚拟机实例,因此通过 zygote 这个父进程,创建的子进程都会继承这个虚拟机实例,app 中的 java 代码可以得到翻译执行。
- 进程与进程之间需要跨进程通信,由 zygote 进程作为父进程还可以获得一个 Binder 线程池,这样进程之间就可以使用 Binder 进行跨进程通信了。
基于以上两点,可以理解 zygote 进程为什么是所有应用进程的父进程的原因.
涉及到的源码路徑
/system/core/rootdir/init.rc/system/core/init/main.cpp/system/core/init/init.cpp/system/core/rootdir/init.zygote64_32.rc/frameworks/base/cmds/app_process/app_main.cpp/frameworks/base/core/jni/AndroidRuntime.cpp/libnativehelper/JniInvocation.cpp/frameworks/base/core/java/com/android/internal/os/Zygote.java/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java/frameworks/base/core/java/com/android/internal/os/ZygoteServer.java/frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java/frameworks/base/core/java/android/net/LocalServerSocket.java/system/core/libutils/Threads.cpp
二 zygote是如何被启动的
我们知道 init 进程启动后,会解析 init.rc 文件,然后创建和加载 service 字段指定的进程。zygote 进程就是以这种方式,被 init 进程加载并启动的。在 /system/core/rootdir/init.rc 中,通过如下引用来 load zygote 的 rc:
import /init.${ ro.zygote}.rc
其中 ${ro.zygote} 由各个厂家使用,现在的主流厂家基本使用 zygote64_32,因此,我们的 rc 文件为 init.zygote64_32.rc,我们来看这个文件:
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote class main priority -20 user root group root readproc socket zygote stream 660 root system onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on onrestart restart audioserver onrestart restart cameraserver onrestart restart media onrestart restart netd onrestart restart wificond writepid /dev/cpuset/foreground/tasksservice zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload class main priority -20 user root group root readproc socket zygote_secondary stream 660 root system onrestart restart zygote writepid /dev/cpuset/foreground/tasks
从这个 rc 文件中可以看到启动了二个进程,分别为 zygote 和 zygote_secondary,启动路徑为 /system/bin/app_process64 和 /system/bin/app_process32,对应的代码入口为:frameworks/base/cmds/app_process/app_main.cpp
三 zygote启动流程
3.1 zygote启动时序图
- init 进程通过解析 init.zygote64_32.rc 来启动位于 /system/bin/app_process64 的 zygote 进程,入口为 app_main.cpp
- 调用 AndroidRuntime 的 startVM() 方法创建虚拟机,再调用 startReg() 注册 JNI 函数
- 通过 JNI 方式调用 ZygoteInit.main(),第一次进入 Java 世界
- registerZygoteSocket() 建立 socket 通道,zygote 作为通信的服务端,用于响应客户端请求
- preload() 预加载通用类、drawable 和 color 资源、openGL 以及共享库以及 WebView,用于提高 app 启动效率
- zygote 完成大部分工作,接下来再通过 startSystemServer(),fork system_server 进程,它同时也是上层 framework 框架的运行载体
- zygote 任务完成,调用 runSelectLoop(),随时待命,当接收到创建新进程的请求时,立即唤醒并执行相应工作
3.2 zygote入口函数main
先来一张 zygote 在 native C 世界的代码调用图,如下:
frameworks/base/cmds/app_process/app_main.cpp
int main(int argc, char* const argv[]){ //zygote传入的参数argv为“-Xzygote /system/bin --zygote --start-system-server --socket-name=zygote” //zygote_secondary传入的参数argv为“-Xzygote /system/bin --zygote --socket-name=zygote_secondary” AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); ........ while (i < argc) { const char* arg = argv[i++]; if (strcmp(arg, "--zygote") == 0) { zygote = true; //对于64位系统nice_name为zygote64; 32位系统为zygote niceName = ZYGOTE_NICE_NAME; } else if (strcmp(arg, "--start-system-server") == 0) { //是否需要启动system server startSystemServer = true; } else if (strcmp(arg, "--application") == 0) { //启动进入独立的程序模式 application = true; } else if (strncmp(arg, "--nice-name=", 12) == 0) { //niceName 为当前进程别名,区别abi型号 niceName.setTo(arg + 12); } else if (strncmp(arg, "--", 2) != 0) { className.setTo(arg); break; } else { --i; break; } } ........ if (!className.isEmpty()) { //className不为空,说明是application启动模式 ........ } else { //进入zygote模式,新建Dalvik的缓存目录:/data/dalvik-cache maybeCreateDalvikCache(); if (startSystemServer) { //加入start-system-server参数 args.add(String8("start-system-server")); } String8 abiFlag("--abi-list="); abiFlag.append(prop); args.add(abiFlag); //加入--abi-list=参数 // In zygote mode, pass all remaining arguments to the zygote // main() method. for (; i < argc; ++i) { //将剩下的参数加入args args.add(String8(argv[i])); } } ........ if (!niceName.isEmpty()) { //设置一个“好听的昵称” zygote\zygote64,之前的名称是app_process runtime.setArgv0(niceName.string(), true /* setProcName */); } if (zygote) { //如果是zygote启动模式,则加载ZygoteInit runtime.start("com.android.internal.os.ZygoteInit", args, zygote); } else if (className) { //如果是application启动模式,则加载RuntimeInit runtime.start("com.android.internal.os.RuntimeInit", args, zygote); } else { //没有指定类名或zygote,参数错误 fprintf(stderr, "Error: no class name or --zygote supplied.\n"); app_usage(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); }}
zygote 本身是一个 Native 的应用程序,刚开始的进程名称为“app_process”,运行过程中,通过调用 setArgv0 将名字改为 zygote 或者 zygote64 (根据操作系统而来),最后通过 runtime 的 start() 方法来真正的加载虚拟机并进入 java 世界。
3.3 AndroidRuntime.start
frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){ ALOGD(">>>>>> START %s uid %d <<<<<<\n", className != NULL ? className : "(unknown)", getuid()); ........ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; //虚拟机创建,主要是关于虚拟机参数的设置 if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) { return; } ........ // 注册JNI方法 if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } jclass stringClass; jobjectArray strArray; jstring classNameStr; //等价 strArray= new String[options.size() + 1]; stringClass = env->FindClass("java/lang/String"); //等价 strArray[0] = "com.android.internal.os.ZygoteInit" strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL); classNameStr = env->NewStringUTF(className); env->SetObjectArrayElement(strArray, 0, classNameStr); //strArray[1] = "start-system-server"; //strArray[2] = "--abi-list=xxx"; //其中xxx为系统响应的cpu架构类型,比如arm64-v8a. for (size_t i = 0; i < options.size(); ++i) { jstring optionsStr = env->NewStringUTF(options.itemAt(i).string()); assert(optionsStr != NULL); env->SetObjectArrayElement(strArray, i + 1, optionsStr); } //将"com.android.internal.os.ZygoteInit"转换为"com/android/internal/os/ZygoteInit" char* slashClassName = toSlashClassName(className != NULL ? className : ""); jclass startClass = env->FindClass(slashClassName); //找到Zygoteinit类 if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); } else { //找到这个类后就继续找成员函数main方法的Mehtod ID jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); } else { // 通过反射调用ZygoteInit.main()方法 env->CallStaticVoidMethod(startClass, startMeth, strArray); } } //释放相应对象的内存空间 free(slashClassName); ALOGD("Shutting down VM\n"); 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");}
start() 函数主要做了三件事情,一调用 startVm 开启虚拟机,二调用 startReg 注册 JNI 方法,三就是使用 JNI 调用 ZygoteInit 从而进入 java 世界。
相关log:
01-10 11:20:31.369 722 722 D AndroidRuntime: >>>>>> START com.android.internal.os.ZygoteInit uid 0 <<<<<<
具体虚拟机的创建和 JNI 方法的注册本篇文章不再详细讨论,感兴趣的同学可以查看具体代码自行研究,接下来我们来分析进入 java世界的 ZygoteInit.
3.4 ZygoteInit.main
上节我们通过 JNI 调用 ZygoteInit 的 main 函数后,zygote 进程便进入了 Java 框架层,此前没有任何代码进入过 Java 框架层,换句换说zygote 开创了 Java 框架层。
frameworks\base\core\java\com\android\internal\os\ZygoteInit.java
public static void main(String argv[]) { // 1.创建ZygoteServer ZygoteServer zygoteServer = null; // 调用native函数,确保当前没有其它线程在运行 ZygoteHooks.startZygoteNoThreadCreation(); //设置pid为0,Zygote进入自己的进程组 Os.setpgid(0, 0); ........ Runnable caller; try { ........ //得到systrace的监控TAG String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing"; TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag, Trace.TRACE_TAG_DALVIK); //通过systradce来追踪 函数ZygoteInit, 可以通过systrace工具来进行分析 //traceBegin 和 traceEnd 要成对出现,而且需要使用同一个tag bootTimingsTraceLog.traceBegin("ZygoteInit"); //开启DDMS(Dalvik Debug Monitor Service)功能 //注册所有已知的Java VM的处理块的监听器。 //线程监听、内存监听、native 堆内存监听、debug模式监听等等 RuntimeInit.enableDdms(); boolean startSystemServer = false; String zygoteSocketName = "zygote"; String abiList = null; boolean enableLazyPreload = false; //2. 解析app_main.cpp - start()传入的参数 for (int i = 1; i < argv.length; i++) { if ("start-system-server".equals(argv[i])) { startSystemServer = true; //启动zygote时,才会传入参数:start-system-server } else if ("--enable-lazy-preload".equals(argv[i])) { enableLazyPreload = true; //启动zygote_secondary时,才会传入参数:enable-lazy-preload } else if (argv[i].startsWith(ABI_LIST_ARG)) { //通过属性ro.product.cpu.abilist64\ro.product.cpu.abilist32 从C空间传来的值 abiList = argv[i].substring(ABI_LIST_ARG.length()); } else if (argv[i].startsWith(SOCKET_NAME_ARG)) { zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length()); //会有两种值:zygote和zygote_secondary } else { throw new RuntimeException("Unknown command line argument: " + argv[i]); } } // 根据传入socket name来决定是创建socket还是zygote_secondary final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME); // 在第一次zygote启动时,enableLazyPreload为false,执行preload if (!enableLazyPreload) { //systrace 追踪 ZygotePreload bootTimingsTraceLog.traceBegin("ZygotePreload"); // 3.加载进程的资源和类,参考[4.2.2] preload(bootTimingsTraceLog); //systrae结束 ZygotePreload的追踪 bootTimingsTraceLog.traceEnd(); // ZygotePreload } else { // 延迟预加载, 变更Zygote进程优先级为NORMAL级别,第一次fork时才会preload Zygote.resetNicePriority(); } //结束ZygoteInit的systrace追踪 bootTimingsTraceLog.traceEnd(); // ZygoteInit //禁用systrace追踪,以便fork的进程不会从zygote继承过时的跟踪标记 Trace.setTracingEnabled(false, 0); // 4.调用ZygoteServer 构造函数,创建socket,会根据传入的参数, // 创建两个socket:/dev/socket/zygote 和 /dev/socket/zygote_secondary zygoteServer = new ZygoteServer(isPrimaryZygote); if (startSystemServer) { //5.fork出system server Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer); // 启动SystemServer if (r != null) { r.run(); return; } } // 6.zygote进程进入无限循环,处理请求 caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { if (zygoteServer != null) { zygoteServer.closeServerSocket(); } } // 7.在子进程中退出了选择循环。继续执行命令 if (caller != null) { caller.run(); } }
ZygoteInit 的 main 函数主要完成了以下工作:
- 调用 preload() 来预加载类和资源
- 调用 ZygoteServer() 创建了两个 Server 端的 Socket 分别为 /dev/socket/zygote 和 /dev/socket/zygote_secondary,Socket 用来等待 AMS 发送过来的请求,请求 zygote 进程创建新的应用程序进程。
- 调用 forkSystemServer 来启动 SystemServer 进程,这样系统的关键服务也会通过 SystemServer 进程启动起来。
- 最后调用 runSelectLoop 函数来等待客户端请求
下面我们来详细来分析这四件事情。
3.5 ZygoteInit.preload
static void preload(TimingsTraceLog bootTimingsTraceLog) { Log.d(TAG, "begin preload"); beginPreload(); // Pin ICU Data, 获取字符集转换资源等 //预加载类的列表---/system/etc/preloaded-classes //在版本:/frameworks/base/config/preloaded-classes 中,Android10.0中预计有7603左右个类 preloadClasses(); preloadResources(); //加载图片、颜色等资源文件 //部分定义在 /frameworks/base/core/res/res/values/arrays.xml中 ...... preloadSharedLibraries();// 加载 android、compiler_rt、jnigraphics等library preloadTextResources();//用于初始化文字资源 WebViewFactory.prepareWebViewInZygote();//用于初始化webview; endPreload();//预加载完成,可以查看下面的log warmUpJcaProviders(); Log.d(TAG, "end preload"); sPreloadComplete = true; }
什么是预加载?
预加载是指在 zygote 进程启动的时候就加载,这样系统只在 zygote 执行一次加载操作,所有 app 用到该资源不需要再重新加载,减少资源加载时间,加快了应用启动速度,一般情况下,系统中 app 共享的资源会被列为预加载资源。
zygote fork 子进程时,根据 fork 的 copy-on-write 机制可知,有些类如果不做改变,甚至都不用复制,子进程可以和父进程共享这部分数据,从而省去不少内存的占用。
预加载的原理
zygote 进程启动后将资源读取出来,保存到 Resources 一个全局静态变量中,下次读取系统资源的时候优先从静态变量中查找。
frameworks/base/config/preloaded-classes:
3.6 ZygoteServer
frameworks\base\core\java\com\android\internal\os\ZygoteServer.java
class ZygoteServer { private LocalServerSocket mZygoteSocket; private LocalServerSocket mUsapPoolSocket; private FileDescriptor mUsapPoolEventFD; //创建zygote的socket ZygoteServer(boolean isPrimaryZygote) { mUsapPoolEventFD = Zygote.getUsapPoolEventFD(); if (isPrimaryZygote) { //创建socket,并获取socket对象,socketname: zygote mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.PRIMARY_SOCKET_NAME); //创建socket,并获取socket对象,socketname:usap_pool_primary mUsapPoolSocket = Zygote.createManagedSocketFromInitSocket( Zygote.USAP_POOL_PRIMARY_SOCKET_NAME); } else { //创建socket,并获取socket对象,socketname: zygote_secondary mZygoteSocket = Zygote.createManagedSocketFromInitSocket(Zygote.SECONDARY_SOCKET_NAME); //创建socket,并获取socket对象,socketname: usap_pool_secondary mUsapPoolSocket = Zygote.createManagedSocketFromInitSocket( Zygote.USAP_POOL_SECONDARY_SOCKET_NAME); } fetchUsapPoolPolicyProps(); mUsapPoolSupported = true; }
frameworks/base/core/java/com/android/internal/os/Zygote.java
static LocalServerSocket createManagedSocketFromInitSocket(String socketName) { int fileDesc; // ANDROID_SOCKET_PREFIX为"ANDROID_SOCKET_" //加入传入参数为zygote,则fullSocketName:ANDROID_SOCKET_zygote final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; try { //init.zygote64_32.rc启动时,指定了4个socket: //分别是zygote、usap_pool_primary、zygote_secondary、usap_pool_secondary // 在进程被创建时,就会创建对应的文件描述符,并加入到环境变量中 // 这里取出对应的环境变量 String env = System.getenv(fullSocketName); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException("Socket unset or invalid: " + fullSocketName, ex); } try { FileDescriptor fd = new FileDescriptor(); fd.setInt$(fileDesc); // 获取zygote socket的文件描述符 return new LocalServerSocket(fd); // 创建Socket的本地服务端 } catch (IOException ex) { throw new RuntimeException( "Error building socket from file descriptor: " + fileDesc, ex); } }
frameworks\base\core\java\android\net\LocalServerSocket.java
public LocalServerSocket(FileDescriptor fd) throws IOException { impl = new LocalSocketImpl(fd); impl.listen(LISTEN_BACKLOG); localAddress = impl.getSockAddress(); }
ZygoteServer 构造函数初始化时,根据传入的参数,利用 LocalServerSocket 创建了4个本地服务端的 socket,用来建立连接。分别是:zygote、usap_pool_primary、zygote_secondary、usap_pool_secondary.
3.7 ZygoteInit.forkSystemServer
private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_IPC_LOCK, OsConstants.CAP_KILL, OsConstants.CAP_NET_ADMIN, OsConstants.CAP_NET_BIND_SERVICE, OsConstants.CAP_NET_BROADCAST, OsConstants.CAP_NET_RAW, OsConstants.CAP_SYS_MODULE, OsConstants.CAP_SYS_NICE, OsConstants.CAP_SYS_PTRACE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG, OsConstants.CAP_WAKE_ALARM, OsConstants.CAP_BLOCK_SUSPEND ); ........ //参数准备 /* 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,1021,1023," + "1024,1032,1065,3001,3002,3003,3006,3007,3009,3010", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT, "com.android.server.SystemServer", }; ZygoteArguments parsedArgs = null; int pid; try { //将上面准备的参数,按照ZygoteArguments的风格进行封装 parsedArgs = new ZygoteArguments(args); Zygote.applyDebuggerSystemProperty(parsedArgs); Zygote.applyInvokeWithSystemProperty(parsedArgs); boolean profileSystemServer = SystemProperties.getBoolean( "dalvik.vm.profilesystemserver", false); if (profileSystemServer) { parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER; } //通过fork"分裂"出子进程system_server /* Request to fork the system server process */ pid = Zygote.forkSystemServer( parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids, parsedArgs.mRuntimeFlags, null, parsedArgs.mPermittedCapabilities, parsedArgs.mEffectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } //进入子进程system_server /* For child process */ if (pid == 0) { // 处理32_64和64_32的情况 if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } // fork时会copy socket,system server需要主动关闭 zygoteServer.closeServerSocket(); // system server进程处理自己的工作 return handleSystemServerProcess(parsedArgs); } return null; }
forkSystemServer() 会在新 fork 出的子进程中调用 handleSystemServerProcess(),主要是返回 Runtime.java 中的 MethodAndArgsCaller 方法,然后通过 r.run() 启动 com.android.server.SystemServer 的 main 函数,这个我们会在后面的分析 SystemServer 的章节中进行详细介绍,我们先看下基本调用流程
handleSystemServerProcess代码流程:handleSystemServerProcess() | [ZygoteInit.java] zygoteInit() | [RuntimeInit.java] applicationInit() | findStaticMain() | MethodAndArgsCaller()
3.8 ZygoteServer.runSelectLoop
frameworks\base\core\java\com\android\internal\os\ZygoteServer.java
Runnable runSelectLoop(String abiList) { ArrayList<FileDescriptor> socketFDs = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); // 首先将server socket加入到fds socketFDs.add(mZygoteSocket.getFileDescriptor()); peers.add(null); //无限循环用来等待AMS请求zygote创建新的应用进程 while (true) { fetchUsapPoolPolicyPropsWithMinInterval(); int[] usapPipeFDs = null; StructPollfd[] pollFDs = null; // 每次循环,都重新创建需要监听的pollFds if (mUsapPoolEnabled) { usapPipeFDs = Zygote.getUsapPipeFDs(); pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length]; } else { pollFDs = new StructPollfd[socketFDs.size()]; } int pollIndex = 0; for (FileDescriptor socketFD : socketFDs) { // 关注事件到来 pollFDs[pollIndex] = new StructPollfd(); pollFDs[pollIndex].fd = socketFD; pollFDs[pollIndex].events = (short) POLLIN; ++pollIndex; } final int usapPoolEventFDIndex = pollIndex; if (mUsapPoolEnabled) { pollFDs[pollIndex] = new StructPollfd(); pollFDs[pollIndex].fd = mUsapPoolEventFD; pollFDs[pollIndex].events = (short) POLLIN; ++pollIndex; for (int usapPipeFD : usapPipeFDs) { FileDescriptor managedFd = new FileDescriptor(); managedFd.setInt$(usapPipeFD); pollFDs[pollIndex] = new StructPollfd(); pollFDs[pollIndex].fd = managedFd; pollFDs[pollIndex].events = (short) POLLIN; ++pollIndex; } } try { //查询轮训状态,当pollFdd有事件到来则往下执行,否则阻塞在这里 Os.poll(pollFDs, -1); } catch (ErrnoException ex) { throw new RuntimeException("poll failed", ex); } boolean usapPoolFDRead = false; //倒序处理,即优先处理已建立链接的信息,后处理新建链接的请求 while (--pollIndex >= 0) { if ((pollFDs[pollIndex].revents & POLLIN) == 0) { continue; } // server socket最先加入fds, 因此这里是server socket收到数据 if (pollIndex == 0) { // 收到新的建立通信的请求,调用server socket端的accpet函数建立通信连接 // zygote进程与system server进程建立了连接 ZygoteConnection newPeer = acceptCommandPeer(abiList); // 加入到peers和fds, 即下一次也开始监听 peers.add(newPeer); socketFDs.add(newPeer.getFileDescriptor()); } else if (pollIndex < usapPoolEventFDIndex) { //说明接收到AMS发送过来创建应用程序的请求,调用 //processOneCommand来创建新的应用程序进程 try { //有socket连接,创建ZygoteConnection对象,并添加到fds。 ZygoteConnection connection = peers.get(pollIndex); //处理连接(用于fork新的进程) final Runnable command = connection.processOneCommand(this); // TODO (chriswailes): Is this extra check necessary? if (mIsForkChild) { 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"); } if (connection.isClosedByPeer()) { connection.closeSocket(); peers.remove(pollIndex); socketFDs.remove(pollIndex);//处理完则从fds中移除该文件描述符 } } } catch (Exception e) { ...... } finally { mIsForkChild = false; } } else { //处理USAP pool的事件 long messagePayload = -1; try { byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES]; int readBytes = Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length); if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) { DataInputStream inputStream = new DataInputStream(new ByteArrayInputStream(buffer)); messagePayload = inputStream.readLong(); } else { continue; } } catch (Exception ex) { if (pollIndex == usapPoolEventFDIndex) { } else { } continue; } if (pollIndex > usapPoolEventFDIndex) { Zygote.removeUsapTableEntry((int) messagePayload); } usapPoolFDRead = true; } } // Check to see if the USAP pool needs to be refilled. if (usapPoolFDRead) { int[] sessionSocketRawFDs = socketFDs.subList(1, socketFDs.size()) .stream() .mapToInt(fd -> fd.getInt$()) .toArray(); final Runnable command = fillUsapPool(sessionSocketRawFDs); if (command != null) { return command; } } }}
执行 zygote 进程的循环。当来一个新的连接请求时,则建立连接,并在连接中读取请求的命令,runSelectLoop 主要分为三个部分:
- 监听 socket 事件
在 runSelectLoop 里面利用 while (true) 的死循环, Os.poll(pollFds, -1) 来轮询状态,如果有 pollFdd 事件来,则往下执行,否则便会阻塞在这里 - 接受连接请求
当 pollIndex 的值为 0 时,说明请求连接的事件来了,这时候调用 acceptCommandPeer() 来和客户端建立一个 socket 连接,然后把这个 socket 加入监听的数组中。等待这个 socket 上的命令的到来 - 处理连接请求
如果 pollIndex 小于 usapPoolEventFDIndex,说明是已经连接的 socket 上的命令来了。一旦接收到已和客户端连接的 socket 上传过来的命令,runSelectLoop() 方法会调用 ZygoteConnection 类 processOneCommand() 方法去处理命令。处理完后,就会断开与客户端的连接,并把用于连接的 socket 从监听表中移除。
小结:zygote 采用高效的 I/O 多路复用 epoll 机制,保证没有客户端连接请求或数据处理时休眠,否则响应客户端的请求。总体来说 runSelectLoop 方法的内部还是比较简单的,就是处理客户端的连接和请求,其中客户端在 zygote 进程中使用 ZygoteConnection 对象表示。客户端的请求由 ZygoteConnection 的 processOneCommand 来处理。
3.9 ZygoteConnection.processOneCommand
Runnable processOneCommand(ZygoteServer zygoteServer) { ... //fork子进程 pid = Zygote.forkAndSpecialize(parsedArgs.mUid, parsedArgs.mGid, parsedArgs.mGids, parsedArgs.mRuntimeFlags, rlimits, parsedArgs.mMountExternal, parsedArgs.mSeInfo, parsedArgs.mNiceName, fdsToClose, fdsToIgnore, parsedArgs.mStartChildZygote, parsedArgs.mInstructionSet, parsedArgs.mAppDataDir, parsedArgs.mTargetSdkVersion); if (pid == 0) { //子进程执行 zygoteServer.setForkChild(); //进入子进程流程 return handleChildProc(parsedArgs, descriptors, childPipeFd, parsedArgs.mStartChildZygote); } else { //父进程执行 // In the parent. A pid < 0 indicates a failure and will be handled in //handleParentProc. handleParentProc(pid, descriptors, serverPipeFd); return null; } ...}
可以看到在 processOneCommand 中调用了 fork 用来创建一个新的进程,然后进入子进程调用 handleChildProc 函数.
3.10 ZygoteConnection.handleChildProc
private Runnable handleChildProc(ZygoteArguments parsedArgs, FileDescriptor[] descriptors, FileDescriptor pipeFd, boolean isZygote) { ........ if (parsedArgs.mInvokeWith != null) { ........ throw new IllegalStateException("WrapperInit.execApplication unexpectedly returned"); } else { if (!isZygote) { // App进程将会调用到这里,执行目标类的main()方法 return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } else { return ZygoteInit.childZygoteInit(parsedArgs.mTargetSdkVersion, parsedArgs.mRemainingArgs, null /* classLoader */); } } }
3.11 ZygoteInit.zygoteInit
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { if (RuntimeInit.DEBUG) { Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote"); } Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit"); RuntimeInit.redirectLogStreams();//日志重定向 RuntimeInit.commonInit();//通用的初始化工作 ZygoteInit.nativeZygoteInit();//zygote初始化 return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader);//应用的初始化 }
需要重点介绍下 zygoteInit 这个函数,这个函数是在 fork 后的子进程中执行的,我们知道在 fork system server 进程后,会在子进程 system server 中执行 handleSystemServerProcess 这个方法,需要注意的是在这个方法中也会调用 zygoteInit 这个函数,接下来我们来看这个函数中主要做了那些工作,以致于如此重要.其中 redirectLogStreams 是日志的重定向,而 commonInit 是通用的初始化工作,在此不做详细介绍,重点介绍 ZygoteInit.nativeZygoteInit 和 RuntimeInit.applicationInit
3.11.1 ZygoteInit.nativeZygoteInit
private static final native void nativeZygoteInit();
它是一个 native 方法,对应的是 AndroidRuntime.cpp 的 com_android_internal_os_ZygoteInit_nativeZygoteInit,最终调用到 app_main.cpp 的 onZygoteInit 代码如下:
virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self();//创建ProcessState ALOGV("App process: starting thread pool.\n"); proc->startThreadPool();//开启线程池 }
从第一行代码中可以看到创建了 ProcessState 对象,我们之前分析 Binder 的过程中已经知道,在创建 ProcessState 的过程中会打开 Binder 设备并建立内存映射,第二行代码中调用了 ProcessState 的 startThreadPool 方法创建一个新的 Binder 线程,不断进行 talkWithDriver().这样我们在新的子进程中就建立了 Binder 通信机制了.这一点需要明白.
3.11.2 RuntimeInit.applicationInit
protected static Runnable applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) { //true代表应用程序退出时不调用AppRuntime.onExit(),否则会在退出前调用 nativeSetExitWithoutCleanup(true); //设置虚拟机的内存利用率参数值为0.75 VMRuntime.getRuntime().setTargetHeapUtilization(0.75f); VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion); final Arguments args = new Arguments(argv); // The end of of the RuntimeInit event (see #zygoteInit). Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER); //调用startClass的static方法 main() return findStaticMain(args.startClass, args.startArgs, classLoader); }
此处 findStaticMain 的参数 args.startClass 为 android.app.ActivityThread"
3.11.3 findStaticMain
protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) { Class<?> cl; try { cl = Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { throw new RuntimeException( "Missing class when invoking static main " + className, ex); } Method m; try { m = cl.getMethod("main", new Class[] { String[].class }); } catch (NoSuchMethodException ex) { throw new RuntimeException( "Missing static main on " + className, ex); } catch (SecurityException ex) { throw new RuntimeException( "Problem getting static main on " + className, ex); } int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException( "Main method is not public and static on " + className); } return new MethodAndArgsCaller(m, argv); }
static class MethodAndArgsCaller implements Runnable { /** method to call */ private final Method mMethod; /** argument array */ private final String[] mArgs; public MethodAndArgsCaller(Method method, String[] args) { mMethod = method; mArgs = args; } public void run() { try { mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { throw new RuntimeException(ex); } catch (InvocationTargetException ex) { Throwable cause = ex.getCause(); if (cause instanceof RuntimeException) { throw (RuntimeException) cause; } else if (cause instanceof Error) { throw (Error) cause; } throw new RuntimeException(ex); } } }
该方法最终返回一个 MethodAndArgsCaller,这是一个 Runnable,在这个 Runnable 中会通过反射调用 ActivityThread 的 main() 方法.这个 Runnable 会一路返回到 ZygoteInit 类的 main() 方法中,代码如下:
public static void main(String argv[]) { ........ Runnable caller; try { ........ if (startSystemServer) { Runnable r = forkSystemServer(abiList, zygoteSocketName, 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; } } ........ caller = zygoteServer.runSelectLoop(abiList); } catch (Throwable ex) { Log.e(TAG, "System zygote died with exception", ex); throw ex; } finally { if (zygoteServer != null) { zygoteServer.closeServerSocket(); } } // We're in the child process and have exited the select loop. Proceed to execute the // command. if (caller != null) { caller.run();//最终执行这个Runnable } }
最终会在子进程中通过 caller.run 来执行这个 Runnable,从而完成 ActivityThread main方法的执行.
四 总结
- 解析 init.zygote64_32.rc,创建 AppRuntime 对象,并且调用其 start 函数.zygote 的核心初始化都在 AppRuntime 中。
- 在 AndroidRuntime 的 start 方法中调用 startVm 创建 Java 虚拟机,然后调用 startReg 来注册 JNI 函数
- 通过 JNI 调用 com.android.internal.os.ZygoteInit 的 main 函数,从此进入了 Java 世界
- 通过 ZygoteServer 创建服务端 Socket,预加载常用的类、资源等
- 调用 forkSystemServer 函数 fork 一个 system_server 进程来为 Java 框架服务
- 调用 runSelectLoop 来让自己无限循环等待,等待 AMS 的进程创建请求
发表评论
最新留言
关于作者
