赞
踩
在 Android 系统中,所有的应用程序以及系统服务进程 SystemService 都是由 zygote 进程孕育 (fork)出来的。zygote 进程的作用可以概括为以下三点:
我们知道 Android 系统是基于 Linux 内核的,而在 Linux 系统中,所有的进程都是 init 进程的子进程,zygote 进程也不例外,它是由 init 进程创建的。
File:system/core/rootdir/init.rc
import /init.${ro.zygote}.rc
File:system/core/rootdir/init.zygote32.rc service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server 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/tasks
而进程 app_process 的源码位置在:platform/frameworks/base/cmds/app_process/app_main.cpp
这个函数由两种启动模式:
两者最终都是调用 AppRuntime 对象的 start 函数,加载 ZygoteInit 或 RuntimeInit 两个Java类,并将之前整理的参数传入进去。
由于本篇讲的是zygote进程启动流程,因此接下来我只讲解ZygoteInit的加载.
int main(int argc, char* const argv[]) { ... // 构建 AppRuntime 对象,并将参数 (-Xzygote) 传递进去 AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0] argc--; argv++; // 所有在"--"后面或者非"-"开头的参数都会被传入vm // 所谓一个特例,在 spaced_commands 变量中定义的参数会被传入vm const char* spaced_commands[] = { "-cp", "-classpath" }; // Allow "spaced commands" to be succeeded by exactly 1 argument (regardless of -s). bool known_command = false; ... 省略代码 通过 runtime.addOption 初始化参数集合 这边直接跳过 ... // Parse runtime arguments. Stop at first unrecognized option. bool zygote = false; bool startSystemServer = false; bool application = false; String8 niceName; String8 className; // 跳过一个参数,之前跳过了 -Xzygote,这里继续跳过 /system/bin,就是所谓的 parent dir ++i; // Skip unused "parent dir" argument. while (i < argc) { const char* arg = argv[i++]; if (strcmp(arg, "--zygote") == 0) { // 表示是 zygote 启动模式 zygote = true; niceName = ZYGOTE_NICE_NAME; // 根据平台可能是 zygote64 或 zygote } else if (strcmp(arg, "--start-system-server") == 0) { // 是否开启 SystemService startSystemServer = true; } else if (strcmp(arg, "--application") == 0) { // application 启动模式 application = true; } else if (strncmp(arg, "--nice-name=", 12) == 0) { // 进程别名 niceName.setTo(arg + 12); } else if (strncmp(arg, "--", 2) != 0) { // application启动的class className.setTo(arg); break; } else { --i; break; } } Vector<String8> args; if (!className.isEmpty()) { // className 不为空表示是 application 启动模式 // 这里不做分析 ... } else { // 表示处在 zygote 启动模式 // 新建Dalvik的缓存目录. maybeCreateDalvikCache(); if (startSystemServer) { args.add(String8("start-system-server")); } //加入--abi-list=参数 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. for (; i < argc; ++i) { args.add(String8(argv[i])); } } // 设置进程别名 if (!niceName.isEmpty()) { runtime.setArgv0(niceName.string(), true /* setProcName */); } if (zygote) { //如果是zygote启动模式,则加载ZygoteInit 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(); LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied."); }
我们看到,在最后调用的是 runtime.start 函数,这个就是要启动虚拟机了,接下来我们分析 start 函数
AppRuntime 类的声明和实现均在 app_main.cpp 中,它是由 AndroidRuntime 类派生出来的,AppRuntime 重载了 onStart、onZygoteInit、onExit 等一些重要的方法。
前面调用的 start 方法实现在基类 AndroidRuntime 中,前半部分主要是初始化JNI,然后创建虚拟机,注册一些JNI函数
File:platform/frameworks/base/core/jni/AndroidRuntime.cpp void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ... // 日志打印,获取ANDROID_ROOT环境变量 /* start the virtual machine */ JniInvocation jni_invocation; jni_invocation.Init(NULL); JNIEnv* env; // ① 创建虚拟机 if (startVm(&mJavaVM, &env, zygote) != 0) { return; } onVmCreated(env); //表示虚拟创建完成时回调的方法 /* * Register android functions. */ // ② 注册 JNI 函数 if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } ... //③ JNI 方式调用 ZygoteInit 类的 main 函数 }
上面的分析中,关键点①、②、③共同组成了 Android 系统中 Java 世界的三部曲。
这个函数没有特别之处,就是调用JNI的虚拟机创建函数,但是创建虚拟机时的一些参数是在 startVm 中确定的,其实就是从各种系统属性中读取一些参数,然后通过 addOption 设置到 AndroidRuntime 的 mOptions 数组中存起来,代码如下:
File:platform/frameworks/base/core/jni/AndroidRuntime.cpp
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote)
{
// 调用 JNI_CreateJavaVM 创建虚拟机,pEnv 返回当前线程的 JniEnv 变量
if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
ALOGE("JNI_CreateJavaVM failed\n");
return -1;
}
return 0;
}
前面是如何创建虚拟机,下一步需要给虚拟机注册一些 JNI 函数,正式因为后续 Java 世界用到的一些函数时采用 native 方法实现的,所以才必须提前注册这些函数
File:platform/frameworks/base/core/jni/AndroidRuntime.cpp /*static*/ int AndroidRuntime::startReg(JNIEnv* env) { ATRACE_NAME("RegisterAndroidNatives"); // 设置 Thread 类的线程创建函数为 javaCreateThreadEtc androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc); ALOGV("--- registering native functions ---\n"); // 创建一个 200 容量的局部引用作用域 env->PushLocalFrame(200); // 注册 Jni 函数 if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) { env->PopLocalFrame(NULL); return -1; } env->PopLocalFrame(NULL); //释放局部引用作用域 //createJavaThread("fubar", quickTest, (void*) "hello"); return 0; }
register_jni_procs是主要的 JNI 注册函数
static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
for (size_t i = 0; i < count; i++) {
if (array[i].mProc(env) < 0) {
#ifndef NDEBUG
ALOGD("----------!!! %s failed to load\n", array[i].mName);
#endif
return -1;
}
}
return 0;
}
mProc 就是为 Java 类注册了 JNI 函数
虚拟机已创建好,JNI函数也已注册,下一步就是通过CallStaticVoidMethod了,通过这个函数真正进入 Java 世界。
这个 Java 世界的入口就是 CallStaticVoidMethod 最终调用的 com.android.internal.os.ZygoteInit 的 main 函数。
public static void main(String argv[]) { ZygoteServer zygoteServer = new ZygoteServer(); ... // ① 创建 Socket,通过这个 Socket 与 ActivityManagerService 通信 zygoteServer.registerServerSocket(socketName); ... // ② 预加载资源 preload(bootTimingsTraceLog); ... if (startSystemServer) { // ③ fork 出 SystemService 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; } } ...... zygoteServer.runSelectLoop(abiList); ...... }
先分析主体的框架,首先创建了一个 ZygoteServer 类,并 registerServerSocket 创建一个 Socket,这个Socket 将 listen 并 accept Client
它将作为服务端来和客户端的 ActivityManagerService 进行通信来 fork 出子进程。
首先看 preloadClass
File:ZygoteInit.java private static void preloadClasses() { final VMRuntime runtime = VMRuntime.getRuntime(); InputStream is; try { // 预加载类的信息存储在 PRELOADED_CLASSED 中(/system/etc/preloaded-classes) is = new FileInputStream(PRELOADED_CLASSES); } catch (FileNotFoundException e) { Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + "."); return; } ... // 统计工作 try { BufferedReader br = new BufferedReader(new InputStreamReader(is), 256); int count = 0; String line; while ((line = br.readLine()) != null) { // Skip comments and blank lines. line = line.trim(); if (line.startsWith("#") || line.equals("")) { continue; } Trace.traceBegin(Trace.TRACE_TAG_DALVIK, line); try { if (false) { Log.v(TAG, "Preloading " + line + "..."); } // Load and explicitly initialize the given class. Use // Class.forName(String, boolean, ClassLoader) to avoid repeated stack lookups // (to derive the caller's class-loader). Use true to force initialization, and // null for the boot classpath class-loader (could as well cache the // 通过 JAVA 反射来加载类 // class-loader of this class in a variable). Class.forName(line, true, null); count++; } catch (ClassNotFoundException e) { } } Log.i(TAG, "...preloaded " + count + " classes in " + (SystemClock.uptimeMillis()-startTime) + "ms."); } catch (IOException e) { Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e); } finally { ... // 扫尾工作 } }
preload_class 文件由 framework/base/tools/preload 工具生成,它判断每个类加载的时间是否大于1250微秒,超过就写入 preload_class 文件,最后由 zygote 进行预加载。
preloadClass 执行的时间比较长,这也是andorid启动慢的原因,可以在此进行开机速度优化
preloadResource 预加载的原理很简单,就是在 zygote 进程启动后将资源读取出来,保存到 Resources 一个全局静态变量中,下次读取系统资源的时候优先从静态变量中查找
第三个关键点是 startSystemService,这个函数会创建 Java 世界中传统 Service 所驻留的进程 system_service,该进程是 framework 的核心。
private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) { ... // 设置参数 /* 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,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); /* Request to fork the system server process */ // fork 出一个子进程,这个子进程就是 systemSevice pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) { // fork 成功,开启一些预备工作 if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } zygoteServer.closeServerSocket(); return handleSystemServerProcess(parsedArgs); } return null; }
Zygote.forkSystemServer() 创建一个系统服务进程,进程创建成功后返回 pid 为 0,由于此处生成的新进程和 Zygote 进程一模一样,也就是说这个新进程中同样包含了刚才创建的 Socket,但是该 Socket 在此处无效,因此要将其关闭。接下来调用 handleSystemServerProcess() 处理刚才新建的进程即 SystemServer 进程,需要注意此时已经工作在 SystemServe r进程中
前面一个关键点是 registZygotSocket 注册了一个用于 IPC 的 Socket,它的用途在这个函数中能体现出来,这个函数监听客户端的请求
/** * Runs the zygote process's select loop. Accepts new connections as * they happen, and reads commands from connections one spawn-request's * worth at a time. */ 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) { // 新客户端连接请求,充当服务端 Socket 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); } } } catch (Exception e) { ... } } } } }
zygote 是 Android系统中创建 Java 世界的盘古,它创建第一个 Java 虚拟机,同时它又是女娲,繁殖了 framework 的核心 system_server 进程
以后的日子里,zygote 随时守护在我们周围,当接收子孙后代的请求后,它会随时醒来为它们工作。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。