赞
踩
Zygpte 进程的启动脚本
Zygote 进程是在 init 进程启动时创建的,Zygote 的启动脚本在 system/core/rootdir 目录下,这里不详细说 init 进程启动过程了,它可以简单描述为解析 init.rc ,启动相应的脚本
init.zygote32.rc 代码
- #zygote配置文件相关init.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
init 进程会调用 app_main.cpp 的 main 函数,frameworks\base\cmds\app_process\app_main.cpp
- int main(int argc, char* const argv[])
- {
- //...
- AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
-
- // Parse runtime arguments. Stop at first unrecognized option.
- bool zygote = false;
- bool startSystemServer = false;
- bool application = false;
- String8 niceName;
- String8 className;
-
- ++i; // Skip unused "parent dir" argument.
- while (i < argc) {
- const char* arg = argv[i++];
- //判断参数 arg 是否包含了 --zygote
- if (strcmp(arg, "--zygote") == 0) {
- //如果当前运行在 Zygote 进程中,则将 zygote设置为true
- zygote = true;
- niceName = ZYGOTE_NICE_NAME;
- } else if (strcmp(arg, "--start-system-server") == 0) {
- //如果包含 --start-system-server 则将 startSystemServer 设置为true
- startSystemServer = true;
- //...
- --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();
- LOG_ALWAYS_FATAL("app_process: no class name or --zygote supplied.");
- }
- }

这段代码很简单,先对参数进行判断,之后由参数调用相对应的函数,这里 zygote 为 true,调到 runtime#start 方法
frameworks/base/core/jni/AndroidRuntime.cpp
- void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
- {
- //...
- /* start the virtual machine */
- JniInvocation jni_invocation;
- jni_invocation.Init(NULL);
- JNIEnv* env;
- //创建 Java 虚拟机
- if (startVm(&mJavaVM, &env, zygote) != 0) {
- return;
- }
- onVmCreated(env);
-
- /*
- * Register android functions.
- */
- //为 Java 虚拟机注册 JNI 方法
- if (startReg(env) < 0) {
- ALOGE("Unable to register all android natives\n");
- return;
- }
- //...
- jclass stringClass;
- jobjectArray strArray;
- jstring classNameStr;
-
- stringClass = env->FindClass("java/lang/String");
- assert(stringClass != NULL);
- strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
- assert(strArray != NULL);
- //className 为 com.android.internal.os.ZygoteInit
- classNameStr = env->NewStringUTF(className);
- assert(classNameStr != NULL);
- env->SetObjectArrayElement(strArray, 0, classNameStr);
- //将 className 的 “.” 替换为 “/” com/android/internal/os/ZygoteInit
- char* slashClassName = toSlashClassName(className != NULL ? className : "");
- //找到这个类
- jclass startClass = env->FindClass(slashClassName);
- if (startClass == NULL) {
- ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
- /* keep going */
- } else {
- //找到 main 方法
- jmethodID startMeth = env->GetStaticMethodID(startClass, "main",
- "([Ljava/lang/String;)V");
- if (startMeth == NULL) {
-
- } else {
- env->CallStaticVoidMethod(startClass, startMeth, strArray);
-
- #if 0
- if (env->ExceptionCheck())
- threadExitUncaughtException(env);
- #endif
- }
- }

AndroidRuntime#start 函数调用 ZygoteInit 中 main 方法。这里 CallStaticVoidMethod 方法是通过 JNI 调用 Java 中的方法。
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
- public static void main(String argv[]) {
- //创建 ZygoteServer
- ZygoteServer zygoteServer = new ZygoteServer();
- //...
-
- final Runnable caller;
- try {
- //...
- boolean startSystemServer = false;
- String socketName = "zygote";
- String abiList = null;
- boolean enableLazyPreload = false;
- //...
- //创建一个 Server 端的 Socket,socketName 的值为 "zygote"
- zygoteServer.registerServerSocket(socketName);
- // In some configurations, we avoid preloading resources and classes eagerly.
- // In such cases, we will preload things prior to our first fork.
- if (!enableLazyPreload) {
- bootTimingsTraceLog.traceBegin("ZygotePreload");
- EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
- SystemClock.uptimeMillis());
- //预加载资源和类
- preload(bootTimingsTraceLog);
- EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
- SystemClock.uptimeMillis());
- bootTimingsTraceLog.traceEnd(); // ZygotePreload
- } else {
- Zygote.resetNicePriority();
- }
-
- //...
- if (startSystemServer) {
- //fork SystenService进程
- 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) {
- //启动 SystemService 进程
- r.run();
- return;
- }
- }
- //等待 AMS 请求
- 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();
- }
- }

ZygoteInit#main 函数主要做了4件事情:创建一个 Server 端的 Socket,预加载类和资源,启动 SystemServer进程,等待 AMS 请求创建新的应用程序。
registerServerSocket
- void registerServerSocket(String socketName) {
- if (mServerSocket == null) {
- int fileDesc;
- //拼接 Socket 的名称
- final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;
- try {
- //得到 Socket 的环境变量
- String env = System.getenv(fullSocketName);
- //将 Socket 环境变量的值转换为文件描述符的参数
- fileDesc = Integer.parseInt(env);
- } catch (RuntimeException ex) {
- throw new RuntimeException(fullSocketName + " unset or invalid", ex);
- }
-
- try {
- //创建文件描述符
- FileDescriptor fd = new FileDescriptor();
- fd.setInt$(fileDesc);
- //创建 Socket 服务端
- mServerSocket = new LocalServerSocket(fd);
- } catch (IOException ex) {
- throw new RuntimeException(
- "Error binding to local socket '" + fileDesc + "'", ex);
- }
- }
- }

创建 LocalServerSocket,LocalServerSocket 的构造函数中创建 LocalSocketImpl 实现类,调用 create 方法
- public void create(int sockType) throws IOException {
- //...
- try {
- fd = Os.socket(OsConstants.AF_UNIX, osType, 0);
- mFdCreatedInternally = true;
- } catch (ErrnoException e) {
- e.rethrowAsIOException();
- }
- }
这里用到了 linux 中 socket 编程。
preload
- static void preload(TimingsTraceLog bootTimingsTraceLog) {
- bootTimingsTraceLog.traceBegin("PreloadClasses");
- //预加载 Class
- preloadClasses();
- //预加载资源
- preloadResources();
- //OpenGL
- preloadOpenGL();
- //三方库
- preloadSharedLibraries();
- //文本资源
- preloadTextResources();
-
- sPreloadComplete = true;
- }
由名字可以看出预加载的资源有大概情况。
forkSystemServer
- private static Runnable forkSystemServer(String abiList, String socketName,
- ZygoteServer zygoteServer) {
- //...
- /* Containers run without this capability, so avoid setting it in that case */
- if (!SystemProperties.getBoolean(PROPERTY_RUNNING_IN_CONTAINER, false)) {
- capabilities |= posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND);
- }
- //创建 aargs 数组,保存启动参数
- 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);
-
- 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;
- }

先准备启动参数 args 数组,之后将 args 封装成 ZygoteConnection.Arguments 对象,最后调用 Zygote#forkSystemServer 创建子进程。
- public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
- int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
- VM_HOOKS.preFork();
- // Resets nice priority for zygote process.
- resetNicePriority();
- int pid = nativeForkSystemServer(
- uid, gid, gids, debugFlags, rlimits, permittedCapabilities, effectiveCapabilities);
- // Enable tracing as soon as we enter the system_server.
- if (pid == 0) {
- Trace.setTracingEnabled(true, debugFlags);
- }
- VM_HOOKS.postForkCommon();
- return pid;
- }
-
- native private static int nativeForkSystemServer(int uid, int gid, int[] gids, int debugFlags,
- int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);

这里直接调用 native 层的 nativeForkSystemServer 创建,底层也是调用了 fork() 函数。
关于 fork()
fork() 函数通过系统调用创建一个与原来进程几乎完全相同的进程,也就是两个进程可以做完全相同的事,但如果初始参数或者传入的变量不同,两个进程也可以做不同的事。
一个进程调用 fork() 函数后,系统先给新的进程分配资源,例如存储数据和代码的空间。然后把原来的进程的所有值都复制到新的新进程中,只有少数值与原来的进程的值不同。相当于克隆了一个自己。
fork被调用一次,却能够返回两次,它可能有三种不同的返回值:
在父进程中,fork返回新创建子进程的进程ID;在子进程中,fork返回0;如果出现错误,fork返回一个负值;
runSelectLoop
- Runnable runSelectLoop(String abiList) {
- ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>();
- ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>();
- //添加到 fds 列表中
- fds.add(mServerSocket.getFileDescriptor());
- peers.add(null);
- //死循环
- while (true) {
- StructPollfd[] pollFds = new StructPollfd[fds.size()];
- //遍历 fds 将 fds 中信息转移到 pollFds 中
- 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);
- }
- //遍历 pollFds
- for (int i = pollFds.length - 1; i >= 0; --i) {
- if ((pollFds[i].revents & POLLIN) == 0) {
- continue;
- }
-
- if (i == 0) {
- //通过 acceptCommandPeer 方法得到 ZygoteConnection,并添加到 peers 连接列表中
- ZygoteConnection newPeer = acceptCommandPeer(abiList);
- peers.add(newPeer);
- fds.add(newPeer.getFileDesciptor());
- } else {
- //...
- }
- }
- }
- }

首先调用 registerServerSocket 函数创建的服务端 Socket 获取 此Socket 设置的 fd 字段,接着无限循环遍历,注意这里 i == 0 ,说明服务器端 Socket 与客户端连接上了,也就是 Zygote 进程与 AMS 建立了连接。
Zygote的启动流程就此结束。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。