《深入理解Android卷 I》- 第四章 - Zygote - 读书笔记

1 综述

Android系统存在两个不同的世界:

  • Java世界,主要是Android的SDK,运行基于ART/Dalvik虚拟的Java程序
  • Native世界,c/c++开发的程序

2 Zygote分析

Zygote本身是一个Native的应用程序,和驱动、内核等均无关系。Zygote是由init进程根据init.rc的配置而创建的。根据上一章知道init进程通过fork/execve执行了zygote配置的可执行文件/system/bin/app_process,其对应的文件是frameworks/base/cmds/app_process/App_main.cpp

int main(int argc, char* const argv[]){
...//省略
     if (zygote) {
        //由AndroidRuntime来完成start
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) {
        runtime.start("com.android.internal.os.RuntimeInit", args, zygote);
    } else
    ... //省略
}

main函数比较简单,创建 AppRuntime对象。设置一些参数,设置进程名称等,主要操作还在集中在runtime.start(...)函数中。
AppRuntime继承了AndroidRuntime重载了onVmCreated(),onStarted(),onZygoteInit(),onExit()四个函数。main中调用的函数start()AndroidRuntime中实现

2.1 AppRuntime分析

framework/base/core/jni/AnroidRuntime.cpp

/*
 * Start the Android runtime.  This involves starting the virtual machine
 * and calling the "static void main(String[] args)" method in the class
 * named by "className".
 *
 * Passes the main function two arguments, the class name and the specified
 * options string.
 */
void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote){
//className的值是"com.android.internal.os.ZygoteInit"
...//省略
    //如果环境变量中没有ANDROID_ROOT,则新增该变量,并设置值为“/system"
    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
          ...        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }
    /* 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) {...//错误,退出}
    /*
     * We want to call main() with a String array with arguments in it.
     * At present we have two arguments, the class name and an option string.
     * Create an array to hold them.
     */
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);//创建String[]
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className); //把nativeString变成JString
    assert(classNameStr != NULL);
    //把className放在数据的0位置
    env->SetObjectArrayElement(strArray, 0, classNameStr);
    //把options中的数据放入数组中
    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);
    }
    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
     //把 '.'替换为'/',在native中'.'有特殊含义
    char* slashClassName = toSlashClassName(className); 
   //拿到com.android.internal.os.ZygoteInit的class对象
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
    ...
    } else {
        //获取 main函数的jmeothodID对象
        jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V");
        if (startMeth == NULL) {...}
         else {
         //执行main函数
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        ...//省略,异常检测
        }
    }
    free(slashClassName);
    //Zygote退出,在正常情况下,Zygote不需要退出。
    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");
}

通过分析AndroidRuntime::start(...)可知,其中有三个关键点:

  • 创建VM,重点代码 AndroidRuntime::startVm(...)
  • 注册JNI函数,重点代码AndroidRuntime::startReg(env)
  • 进入Java世界

2.1.1 创建虚拟机-startVm

framewors/base/core/jni/AnroidRuntime.cpp

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote){
    ....//一大片设置vm参数代码
    /*
     * The default starting and maximum size of the heap.  Larger
     * values should be specified in a product property override.
     */
     //只有看到这个最亲切了 - ^ - 
    parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");
    parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");
    ...//一大片设置参数代码
     /*
     * Initialize the VM.
     *
     * The JavaVM* is essentially per-process, and the JNIEnv* is per-thread.
     * If this call succeeds, the VM is ready, and we can start issuing
     * JNI calls.
     */
     // 调用JNI_CreateJavaVM创建虚拟机,pEnv返回当前线程的JNIEnv变量
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
    ...    }

    return 0;
}

2.1.2 注册JNI函数-startReg

给虚拟机注册一些JNI函数,因为Java世界中需要调用一些native方式实现的函数。
frameworks/base/core/jni/AnroidRuntime.cpp

int AndroidRuntime::startReg(JNIEnv* env){
    ATRACE_NAME("RegisterAndroidNatives");
    /*
     * This hook causes all future threads created in this process to be
     * attached to the JavaVM.  (This needs to go away in favor of JNI
     * Attach calls.)
     */
     //设置Thread类的线程创建函数为javaCreateThreadEtc (第五章详解)
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

    /*
     * Every "register" function calls one or more things that return
     * a local reference (e.g. FindClass).  Because we haven't really
     * started the VM yet, they're all getting stored in the base frame
     * and never released.  Use Push/Pop to manage the storage.
     */
    env->PushLocalFrame(200);
    //注册jni函数,gRegJNI是一个全局数组。
    if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {
     ...}
    env->PopLocalFrame(NULL);
    return 0;
}

static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env)
{
    for (size_t i = 0; i < count; i++) {
        //调用数组元素的mProc函数
        if (array[i].mProc(env) < 0) {
        ...    }
    }
    return 0;
}
//保存的是一个函数
static const RegJNIRec gRegJNI[] = {
    REG_JNI(register_com_android_internal_os_RuntimeInit),
    REG_JNI(register_android_os_SystemClock),
    ...
    }
//JNI注册函数对应的结构体
#define REG_JNI(name)      { name, #name }
    struct RegJNIRec {
        int (*mProc)(JNIEnv*);
        const char* mName;
    };

register_jni_procs()中调用每项的mProc(...)函数,实际实行的就是每项的的函数指针,进行对应当中的JNI函数注册,例:
frameworks/base/core/jni/AnroidRuntime.cpp

int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
{
    return jniRegisterNativeMethods(env,
     "com/android/internal/os/RuntimeInit",gMethods, NELEM(gMethods));
}

2.2 进入Java世界

vm已经创建好了,JNI函数也注册好了,接下来就是执行CallStaticVoidMethod(...)调用执行com.android.internal.os.ZygoteInit::main(...)函数了
frameworks/base/core/java/com/android/internal/os/Zygote.java

public static void main(String argv[]) {
    //创建ZygoteServer,一些Zygote的socket操作已经放到了ZygoteServer中
    ZygoteServer zygoteServer = new ZygoteServer();
    /** 没理解 - start **/
    // Mark zygote start. This ensures that thread creation will throw an error.
        //???通知vm?
        ZygoteHooks.startZygoteNoThreadCreation(); 
  /** 没理解 - end **/
    // Zygote goes into its own process group.
        try {
            //设置groupID,好像之前的版本都没有这个设置
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {...}
   }
    try {
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygoteInit");
            RuntimeInit.enableDdms();//开启DDMS功能
            // Start profiling the zygote initialization.
            SamplingProfilerIntegration.start();

            boolean startSystemServer = false;
            String socketName = "zygote";
            String abiList = null;
            for (int i = 1; i < argv.length; i++) {
                if ("start-system-server".equals(argv[i])) {
                    startSystemServer = 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]);
                }
            }
        ...//省略
            //为Zygote注册sokect
            zygoteServer.registerServerSocket(socketName);
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "ZygotePreload");
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                SystemClock.uptimeMillis());
            preload(); //预加载类和资源
            EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                SystemClock.uptimeMillis());
            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

            // Finish profiling the zygote initialization.
            SamplingProfilerIntegration.writeZygoteSnapshot();

            // Do an initial gc to clean up after startup
            Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PostZygoteInitGC");
            gcAndFinalize();//强制GC一次
            Trace.traceEnd(Trace.TRACE_TAG_DALVIK);

            // Disable tracing so that forked processes do not inherit stale tracing tags from Zygote.
            Trace.setTracingEnabled(false);
            // Zygote process unmounts root storage spaces.
            Zygote.nativeUnmountStorageOnInit();
            ZygoteHooks.stopZygoteNoThreadCreation();
            //启动system_server
            if (startSystemServer) {
                startSystemServer(abiList, socketName, zygoteServer);
            }
        //进入循环,等待socket消息
          zygoteServer.runSelectLoop(abiList);
            zygoteServer.closeServerSocket();
        } catch (Zygote.MethodAndArgsCaller caller) {
            caller.run(); //重要
        } catch (RuntimeException ex) {
            zygoteServer.closeServerSocket();
            throw ex;
        }

2.2.1 创建Zygotes socket

Zygote采用socket的方式接收请求,关于Zygotesocket操作全部封装到了ZygoteServer.java
frameworks/base/core/java/com/android/internal/os/Zygote.java

/**
     * Registers a server socket for zygote command connections
     */
    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) { ..}

            try {
                FileDescriptor fd = new FileDescriptor();
                fd.setInt$(fileDesc); //设置文件描述符
                //创建Socket的本地服务端
                mServerSocket = new LocalServerSocket(fd);
            } catch (IOException ex) {...}
        }
    }

2.2.2 预加载类和资源

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

 static void preload() {
      ...//Trace
      beginIcuCachePinning();
         ...//Trace
       //预加载位于framework/base/preload-classes文件中的类
       preloadClasses();
         ...//Trace
      //预加载资源,包含drawable和color等资源
       preloadResources();
          ...//Trace
       //预加载OpenGL
        preloadOpenGL();
          ...//Trace
        //通过System.loadLibrary()方法,
        //预加载"android","compiler_rt","jnigraphics"这3个共享库
        preloadSharedLibraries();
        //预加载文本连接符资源
        preloadTextResources();
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes.
        //仅用于zygote进程,用于内存共享的进程
        WebViewFactory.prepareWebViewInZygote();
        endIcuCachePinning();
        warmUpJcaProviders();
  }

加载class时采用的Class.forName(...)

//[frameworks/base/core/java/com/android/internal/os/ZygoteInit.java::preloadClasses]
 // 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
// class-loader of this class in a variable).
Class.forName(line, true, null);

说明:preload_class文件由framework/base/tools/preload工具生成,它需要判断每个类加载的时间是否大于1250微秒,超过这个时间的类就会被写到preload-classes文件中,最后由zygote预加载。
这个参数可以在frameworks/base/tools/preload/WritePreloadedClassFile.java中找到

/**
     * Preload any class that take longer to load than MIN_LOAD_TIME_MICROS us.
     */
    static final int MIN_LOAD_TIME_MICROS = 1250;

2.2.3 总结

Zygote的分析整体和原书保持一致,按照原书的流程看源码,基本是一致的。更加面向对象的封装让源码看起更加清晰。

  • 创建AppRuntime对象,并调用它的start。此后的活动则由AppRuntime来控制。
  • 调用startVm创建Java虚拟机,然后调用startReg来注册JNI函数。
  • 通过JNI调用com.android.internal.os.ZygoteInit类的main函数,从此进入了Java世界。然而在这
    个世界刚开创的时候,什么东西都没有。
  • 调用registerZygoteSocket。通过这个函数,它可以响应子孙后代的请求。同时Zygote调用preload(),为Java世界添砖加瓦。
  • Zygote觉得自己工作压力太大,便通过调用startSystemServer分裂一个子进程system_server来为Java世界服务。
  • Zygote完成了Java世界的初创工作,它已经很满足了。下一步该做的就是调用runSelectLoopMode后,便沉沉地睡去了。

3 SystemService

Zygote还有一个重要的作用,启动SystemServer

//启动system_server
if (startSystemServer) {
    startSystemServer(abiList, socketName, zygoteServer);
}

3.1 SystemServer的诞生

frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

private static boolean startSystemServer(String abiList, String socketName, ZygoteServer zygoteServer)
            throws Zygote.MethodAndArgsCaller, RuntimeException {
        ...//省略
        String args[] = {
            "--setuid=1000",
            "--setgid=1000",
            "--setgroups=1001,1002,1003,1004,1005,1006,1007,1008,1009,1010,1018,1021,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 */
            //调用forSystemServerfork一个新的进程
            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 */
        //systemserver进程中
        if (pid == 0) {
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }
            zygoteServer.closeServerSocket();
            handleSystemServerProcess(parsedArgs);
        }

        return true;
}

上面代码调用了Zygote.forkSystemServer(...)去for新进程,进入继续查看
frameworks/base/core/java/com/android/internal/os/Zygote.java

 public static int forkSystemServer(int uid, int gid, int[] gids, int debugFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        VM_HOOKS.preFork();
        //继续调用函数fork
        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);
        }
        VM_HOOKS.postForkCommon();
        return pid;
    }

继续调用一个native函数实现fork,nativeForkSystemServer(...)对应的JNI实现为com_android_internal_os_Zygote_nativeForkSystemServer(...),文件位置:
frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint debug_flags, jobjectArray rlimits, jlong permittedCapabilities,
        jlong effectiveCapabilities) {
        //继续调用函数fork进程
  pid_t pid = ForkAndSpecializeCommon(env, uid, gid, gids,
                                      debug_flags, rlimits,
                                      permittedCapabilities, effectiveCapabilities,
                                      MOUNT_EXTERNAL_DEFAULT, NULL, NULL, true, NULL,
                                      NULL, NULL);
  if (pid > 0) {
      // The zygote process checks whether the child process has died or not.
      // zygote进程中,检测system_server进程是否创建
      gSystemServerPid = pid;
      // There is a slight window that the system server process has crashed
      // but it went unnoticed because we haven't published its pid yet. So
      // we recheck here just to make sure that all is well.
      int status;
      if (waitpid(pid, &status, WNOHANG) == pid) {
          ALOGE("System server process %d has died. Restarting Zygote!", pid);
         //当system_server进程死亡后,重启zygote进程
          RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
      }
  }
  return pid;
}

// Utility routine to fork zygote and specialize the child process.
static pid_t ForkAndSpecializeCommon(JNIEnv* env, uid_t uid, gid_t gid, jintArray javaGids,
                                     jint debug_flags, jobjectArray javaRlimits,
                                     jlong permittedCapabilities, jlong effectiveCapabilities,
                                     jint mount_external,
                                     jstring java_se_info, jstring java_se_name,
                                     bool is_system_server, jintArray fdsToClose,
                                     jstring instructionSet, jstring dataDir) {
 //设置信号处理
  SetSigChldHandler();
...//省略
    // fork进程
  pid_t pid = fork();
  if (pid == 0) {
    //子进程
    //关闭并清除文件描述符
    DetachDescriptors(env, fdsToClose); 
     if (!is_system_server) {
      //对于非system_server子进程,则创建进程组
        int rc = createProcessGroup(uid, getpid());
        ...
    }
    //设置gid
    SetGids(env, javaGids);
    //设置资源limits
    SetRLimits(env, javaRlimits);
    ...//省略
  }
  ...//省略}

继续查看SetSigChldHandler()函数
frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

static void SetSigChldHandler() {
  struct sigaction sa;
  memset(&sa, 0, sizeof(sa));
  sa.sa_handler = SigChldHandler;
//设置处理信号。该信号是子进程死亡的信号
  int err = sigaction(SIGCHLD, &sa, NULL);
...//省略
}

信号的处理函数是SigChldHandler(...)
frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

static void SigChldHandler(int /*signal_number*/) {
  pid_t pid;
  int status;

  // It's necessary to save and restore the errno during this function.
  // Since errno is stored per thread, changing it here modifies the errno
  // on the thread on which this signal handler executes. If a signal occurs
  // between a call and an errno check, it's possible to get the errno set
  // here.
  // See b/23572286 for extra information.
  int saved_errno = errno;

  while ((pid = waitpid(-1, &status, WNOHANG)) > 0) {
     // Log process-death status that we care about.  In general it is
     // not safe to call LOG(...) from a signal handler because of
     // possible reentrancy.  However, we know a priori that the
     // current implementation of LOG() is safe to call from a SIGCHLD
     // handler in the zygote process.  If the LOG() implementation
     // changes its locking strategy or its use of syscalls within the
     // lazy-init critical section, its use here may become unsafe.
    if (WIFEXITED(status)) {
      if (WEXITSTATUS(status)) {
        ALOGI("Process %d exited cleanly (%d)", pid, WEXITSTATUS(status));
      }
    } else if (WIFSIGNALED(status)) {
      if (WTERMSIG(status) != SIGKILL) {
        ALOGI("Process %d exited due to signal (%d)", pid, WTERMSIG(status));
      }
      if (WCOREDUMP(status)) {
        ALOGI("Process %d dumped core.", pid);
      }
    }

    // If the just-crashed process is the system_server, bring down zygote
    // so that it is restarted by init and system server will be restarted from there.
    //如果死去的子进程是SS,则Zygote把自己也干掉了,Zygote死掉会导致init重启zygote,这样zygote又能启动systemserver
    if (pid == gSystemServerPid) {
    ...
      kill(getpid(), SIGKILL);
    }
  }

  // Note that we shouldn't consider ECHILD an error because
  // the secondary zygote might have no children left to wait for.
  if (pid < 0 && errno != ECHILD) {...}

  errno = saved_errno;
}

由上面代码可知,做为Zygote的嫡长子,system_server确实具有非常高的地位,竟然到了与Zygote生死与共的地步!

3.2 SystemServer的重要使命

forksystem_server代码执行回到startSystemServer(...)(frameworks/base/core/java/com/android/internal/os/ZygoteInit.java)中

//[startSystemServer(...)代码片段]
/* For child process */
if (pid == 0) {
    if (hasSecondZygote(abiList)) {
        //?两个zygote进程(zygote/zygote64)?之后去了解先写笔记 
        waitForSecondaryZygote(socketName);
    }
    //关闭从Zygote那里继承下来的Socket
    //因为fork()创建新进程,采用copy on write方式
    //子进程继承了父进程的所所有资源?是这么理解吧?
    zygoteServer.closeServerSocket();
    //开启system_server的使命
    handleSystemServerProcess(parsedArgs);
}

开启使命:
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

private static void handleSystemServerProcess(
            ZygoteConnection.Arguments parsedArgs)
            throws Zygote.MethodAndArgsCaller {
     // set umask to 0077 so new files and directories will default to owner-only permissions.
    Os.umask(S_IRWXG | S_IRWXO);
    //设置进程名
    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }
   final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
    if (systemServerClasspath != null) {
       // 执行dex优化操作
        performSystemServerDexOpt(systemServerClasspath);
    }    
    if (parsedArgs.invokeWith != null) {
        ...    
    } else {
        ClassLoader cl = null;
        if (systemServerClasspath != null) {
            cl = createSystemServerClassLoader(systemServerClasspath,
                                                   parsedArgs.targetSdkVersion);

            Thread.currentThread().setContextClassLoader(cl);
        }

        /*
         * Pass the remaining arguments to SystemServer.
         */
         //调用ZygoteInit函数。
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);    
    }
}

其中systemServerClasspath环境变量主要有/system/framework/目录下的services.jarethernet-service.jar, wifi-service.jar这3个文件。
根据代码执行,继续跟入RuntimeInit.zygoteInit(...)函数
frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public static final void zygoteInit(int targetSdkVersion, String[] argv,
 ClassLoader classLoader)throws Zygote.MethodAndArgsCaller {
    ...//省略
    //做一些常规初始化
    commonInit();
    //native层的初始化
    nativeZygoteInit();
    //应用初始化
    applicationInit(targetSdkVersion, argv, classLoader); 
 }

zygoteInit(...)主要执行了三个函数调用完成。

private static final void commonInit() {
    /*
     * set handlers; these apply to all threads in the VM. Apps can replace
     * the default handler, but not the pre handler.
     */
     // 设置默认的未捕捉异常处理方法
    Thread.setUncaughtExceptionPreHandler(new LoggingHandler());
    Thread.setDefaultUncaughtExceptionHandler(new KillApplicationHandler());

    /*
     * Install a TimezoneGetter subclass for ZoneInfo.db
     */
     // 设置时区,中国时区为"Asia/Shanghai"
    TimezoneGetter.setInstance(new TimezoneGetter() {
        @Override
        public String getId() {
            return SystemProperties.get("persist.sys.timezone");
        }
    });
    TimeZone.setDefault(null);
     //重置log配置
    LogManager.getLogManager().reset();
    new AndroidConfig();

    /*
     * Sets the default HTTP User-Agent used by HttpURLConnection.
     */
     // 设置默认的HTTP User-agent格式,用于 HttpURLConnection
    String userAgent = getDefaultUserAgent();
    System.setProperty("http.agent", userAgent);
     /*
     * Wire socket tagging to traffic stats.
     */
    NetworkManagementSocketTagger.install();
    ...//
}

3.2.1 zygoteInitNative分析

非常重要的函数,单独列在一个小节里面。这是一个native函数,实现在frameworks/base/core/jni/AndroidRuntime.cpp

static void com_android_internal_os_RuntimeInit_nativeZygoteInit
(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

gCurRuntimeAndroidRuntime.cpp中的一个全局静态变量

static AndroidRuntime* gCurRuntime = NULL;

app_process.cpp中的main首先就构造了一个AppRuntime对象

int main(int argc, char* const argv[]){
    ...//省略
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...//省略
}

在本章开篇就说了AppRuntime继承自AndroidRuntime,在构造AppRuntime会先构造AndroidRuntime,查看AndroidRuntime的构造函数,果然就这这里赋值了:

AndroidRuntime::AndroidRuntime(...):...{
    ...//
    assert(gCurRuntime == NULL); // one per process
    gCurRuntime = this;
}

找到了真身,继续分析onZygoteInit()

 virtual void onZygoteInit()
    {
        sp<ProcessState> proc = ProcessState::self();
        ////启动一个线程,用于Binder通信。
        proc->startThreadPool();
    }

ProcessState::self()是单例模式,主要工作是调用open()打开/dev/binder驱动设备,再利用mmap()映射内核的地址空间,将Binder驱动的fd赋值ProcessState对象中的变量mDriverFD,用于交互操作。稍后的章节中会详解

3.2.2 applicationInit(...)

zygoteInit(...)第三个重要函数:

private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller {
    //true代表应用程序退出时不调用AppRuntime.onExit(),否则会在退出前调用
    nativeSetExitWithoutCleanup(true);
    //设置虚拟机的内存利用率参数值为0.75
    VMRuntime.getRuntime().setTargetHeapUtilization(0.75f);
    VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
    ...//
     // Remaining arguments are passed to the start class's static main
     //调用startClass的static方法 main()
        invokeStaticMain(args.startClass, args.startArgs, classLoader);
}

这里的startClass的参数就是com.android.server.SystemServer,做了那么多准备,终于看到要执行main函数了

private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)
            throws Zygote.MethodAndArgsCaller {
    Class<?> cl;

    try {
        cl = Class.forName(className, true, classLoader);
    } catch (ClassNotFoundException ex) {...}
    Method m;
    try {
        m = cl.getMethod("main", new Class[] { String[].class });
    } catch (NoSuchMethodException ex) {
    ...} catch (SecurityException ex) {
    ...}

    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {...}
    /*
     * This throw gets caught in ZygoteInit.main(), which responds
     * by invoking the exception's run() method. This arrangement
     * clears up all the stack frames that were required in setting
     * up the process.
     */
    //抛出一个异常,清空栈,提高利用率
    throw new Zygote.MethodAndArgsCaller(m, argv);
}    

由于system_server是从zygote``fork出来的,所以拥有相同的含函数栈,只是运行在两个不同进程,互不干扰(不知道这种说法对不对...求指教)。所以,这里抛出异常,就会沿着当前的进程的函数栈w往上抛,直到遇到catch,沿着调用栈找到
frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

//main函数
try{...} catch (Zygote.MethodAndArgsCaller caller) {
    caller.run();
}

现在函数执行到这里,对于zygote进程来说,因为没有异常,继续后面的代码,而system_server抛出了异常,进入异常处理代码:
frameworks/base/core/java/com/android/internal/os/Zygote.java::MethodAndArgsCaller::run()

public void run() {
    try {
        //这个mMethod为com.android.server.SystemServer的main函数
        mMethod.invoke(null, new Object[] { mArgs });
    }catch{...}
}

3.2.3 SystemServer的真面目

上面的代码明确的表示了SystemServermain函数被调用
frameworks/base/services/java/com/android/server/SystemServer.java

public static void main(String[] args) {
//创建SystemServer对象并调用对象的run()方法
    new SystemServer().run();
}

private void run() {
    ...//
    //如果时间当前时间小于1970设置为1970
    if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) {
    Slog.w(TAG, "System clock is before 1970; setting to 1970.");
    SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME);
    }
  ...//
  //变更虚拟机的库文件
  SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
  ...//
  //清除vm内存增长上限,由于启动过程需要较多的虚拟机内存空间
  VMRuntime.getRuntime().clearGrowthLimit();
  //设置内存的可能有效使用率为0.8
  VMRuntime.getRuntime().setTargetHeapUtilization(0.8f);
  ...//
  //访问环境变量前,需要明确地指定用户
  Environment.setUserRequired(true);
  // Within the system server, any incoming Bundles should be defused
  // to avoid throwing BadParcelableException.  
  BaseBundle.setShouldDefuse(true);
  // Ensure binder calls into the system always run at foreground priority.
  //确保当前系统进程的binder调用,总是运行在前台优先级
  BinderInternal.disableBackgroundScheduling(true);
  // Increase the number of binder threads in system_server
  BinderInternal.setMaxThreads(sMaxBinderThreads);
  //进程优先级设置,和不可自动变为后台进程
  android.os.Process.setThreadPriority(
  android.os.Process.THREAD_PRIORITY_FOREGROUND);
  android.os.Process.setCanSelfBackground(false);
  // Prepare the main looper thread (this thread).
  //准备当前线程的looper
  Looper.prepareMainLooper();
  // Initialize native services.
  //加载android_servers.so
  //该库的源码就在frameworks/base/services/core/jni下
  System.loadLibrary("android_servers");
  // Check whether we failed to shut down last time we tried.
  // This call may not return.
  //检车上次是否关机失败,这个方法可能不会返回
  performPendingShutdown();
  // Initialize the system context.
  //创建system context
  createSystemContext();
  // Create the system service manager.
  //创建SystemServiceManager并添加到本地服务中
   mSystemServiceManager = new SystemServiceManager(mSystemContext);
   LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
   ...//
   //启动各种服务
   startBootstrapServices();//引导服务
   startCoreServices();//核心服务
   startOtherServices();//其他服务
   ...//
   //loop
   Looper.loop();
}

SystemServer.run()方法中有很多有趣的函数调用可以研究一下

3.2.3.1 performPendingShutdown()

private void performPendingShutdown() {
    //从系统属性中拿到关机的action属性
    final String shutdownAction = SystemProperties.get(
                ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
    if (shutdownAction != null && shutdownAction.length() > 0) {
        //拿到actiong的第一个标识为
        boolean reboot = (shutdownAction.charAt(0) == '1');
        //标识位后面都是reason
        final String reason;
        if (shutdownAction.length() > 1) {
            reason = shutdownAction.substring(1, shutdownAction.length());
        } else {
            reason = null;
        }
        ...//检查确保不是reboot into recovery to apply update
        
        //关机或者重启
        ShutdownThread.rebootOrShutdown(null, reboot, reason);
    }
}

这个函数也比较简单,获取系统属性中是否写入得有sys.shutdown.requested这个属性,如果有就解析这个属性,判断是否要进行reboot or shutdwon

3.2.3.2 createSystemContext()

private void createSystemContext() {
    //创建ActivityThread对象
    ActivityThread activityThread = ActivityThread.systemMain();
    
    mSystemContext = activityThread.getSystemContext();
    //设置主题
    mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
}

第一个 ActivityThread.systemMain()

public static ActivityThread systemMain() {
        // The system process on low-memory devices do not get to use hardware
        // accelerated drawing, since this can add too much overhead to the
        // process.
    //内存低的设备关闭硬件加速,因为会增加很多开销
    if (!ActivityManager.isHighEndGfx()) {
        ThreadedRenderer.disable(true);
    } else {
        ThreadedRenderer.enableForegroundTrimming();
    }
    //创建AcvityThread
    ActivityThread thread = new ActivityThread();
    //创建Application以及调用其onCreate()方法
    thread.attach(true);
    return thread;
}

3.2.4开启其他的服务

SystemServer.run()方法的里,也是SystemServer最重要的任务,启动系统服务:startBootstrapServices()startCoreServices(),startOtherServices()`

3.2.4.1 startBootstrapServices

private void startBootstrapServices() {
    //确保installer服务先启动,在installer内部有LocalSocket,先mark,以后在分析
    Installer installer = mSystemServiceManager.startService(Installer.class);
    // Activity manager runs the show.
    mActivityManagerService = mSystemServiceManager.startService(
        ActivityManagerService.Lifecycle.class).getService();
    mActivityManagerService.setSystemServiceManager(mSystemServiceManager);
    mActivityManagerService.setInstaller(installer);
    // Power manager needs to be started early because other services need it.
    // Native daemons may be watching for it to be registered so it must be ready
    // to handle incoming binder calls immediately (including being able to verify
    // the permissions for those calls).
    mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
    // Now that the power manager has been started, let the activity manager
    // initialize power management features
    //初始化activityManagerService的power management功能
    mActivityManagerService.initPowerManagement();
    //启动服务LightsService
    mSystemServiceManager.startService(LightsService.class);
    // Display manager is needed to provide display metrics before package manager
    // starts up.
    mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
    // We need the default display before we can initialize the package manager.
    //方法里面追个调用已经添加到serviceManager中service,通知它们当前阶段????先留着,因为还有很多phase
    mSystemServiceManager.startBootPhase(SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY)
    // Only run "core" apps if we're encrypting the device.
    //获得系统属性,设备加密的状态,如果在加密只运行核心服务
    String cryptState = SystemProperties.get("vold.decrypt");
    if (ENCRYPTING_STATE.equals(cryptState)) {
        mOnlyCore = true;
    } else if (ENCRYPTED_STATE.equals(cryptState)) {
        mOnlyCore = true;
    }
    //启动服务PackageManagerService
    mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF, mOnlyCore);
    mFirstBoot = mPackageManagerService.isFirstBoot();
    mPackageManager = mSystemContext.getPackageManager();
    ...//不知道在说什么,注释也不会翻译
    // Manages A/B OTA dexopting. This is a bootstrap service as we need it to rename
    // A/B artifacts after boot, before anything else might touch/need them.
    // Note: this isn't needed during decryption (we don't have /data anyways).
    if (!mOnlyCore) {...}
    //启动服务UserManagerService
    mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
    // Initialize attribute cache used to cache resources from packages.
    AttributeCache.init(mSystemContext);
    // Set up the Application instance for the system process and get started.
    mActivityManagerService.setSystemProcess();
    // The sensor service needs access to package manager service, app ops
    // service, and permissions service, therefore we start it after them.
    //传感器服务需要访问其他服务才能才能,所以最后开启
    startSensorService();
}

来总结一下上面创建了哪些serviceInstaller,ActivityManagerService,PowerManagerService,LightsService,DisplayManagerService,PackageManagerService,UserManagerService,SensorService。启动顺序也是有讲究的。

3.2.4.2 startCoreServices

private void startCoreServices() {
    // Tracks the battery level.  Requires LightService.
    //启动服务BatteryService,用于统计电池电量
    mSystemServiceManager.startService(BatteryService.class);

    // Tracks application usage stats.
    //追踪应用使用状态
    mSystemServiceManager.startService(UsageStatsService.class);
    mActivityManagerService.setUsageStatsManager(
            LocalServices.getService(UsageStatsManagerInternal.class));

    // Tracks whether the updatable WebView is in a ready state and watches for update installs.
    //启动服务WebViewUpdateService
    mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
}

三个服务:BatteryService,UsageStatsService,WebViewUpdateService.

3.2.4.3 startOtherServices()

启动其他的服务,非常多。

private void startOtherServices() {
//太多了,还是不写了
...
}

3.3 总结

System_server真是是非常重要,他需要负责将启动service,特别是它他抛出异常,然后通过catch异常来执行SystemServer的main函数,不知道我理解的对不对。

4 Zygote的分裂

Zygote forksystem_server后执行zygoteServer.runSelectLoop(...)等待处理请求.

4.1 ActivityManagerService发送请求

ActivityManagerService是由system_server启动的,并且是在startBootStrapServices中启动的,书中直接就给出了在ActivityManagerService:: startProcessLocked(...)来发起请求。第一次看到肯定还是很懵的。熟悉了app启动流程就知道,创建一个新的app进程,层层调用,最终就会执行到这个函数。
参考:
Android应用程序启动过程源代码分析
frameworks/base/services/java/com/android/server/SystemServer.java

private final void startProcessLocked(ProcessRecord app, String hostingType,
            String hostingNameStr, String abiOverride, String entryPoint, String[] entryPointArgs) {
    ...//仅梳理流程,具体代码不详细解析,因为我都还没弄懂...哈哈。
    //请求创建进程
    Process.ProcessStartResult startResult = Process.start(entryPoint,
                    app.processName, uid, uid, gids, debugFlags, mountExternal,
                    app.info.targetSdkVersion, app.info.seinfo, requiredAbi, instructionSet,
                    app.info.dataDir, entryPointArgs);
    ...//省略
}

这里面的代码很多,这部分我觉得作者只是回应Zygotesocket的作用,重点不在分析ActivityManagerService所以不去深究其它的,因为太广了。
上面的start(...)最终会执行到:
frameworks/base/core/java/com/android/os/ZygoteProcess.java

 private Process.ProcessStartResult startViaZygote(...)
throws ZygoteStartFailedEx {
    ...//省略
    return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote);
}

openZygoteSocketIfNeeded(...)就是打开socket连接,zygoteSendArgsAndGetResult(...)发送请求,并读取结果。

4.2 Zygote的响应

上面已经给Zygote发送的请求,处理的函数就是zygoteServer.runSelectLoop(...)
frameworks/base/core/java/com/android/internal/os/ZygoteServer.java

void runSelectLoop(String abiList) throws Zygote.MethodAndArgsCaller {
    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 {
                //处理请求
                boolean done = peers.get(i).runOnce(this);
                if (done) {
                    peers.remove(i);
                    fds.remove(i);
                }
            }
        }
    }
}

那么可以看到,有请求来就会去执行runOnce(...)这个函数:
frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java

boolean runOnce(ZygoteServer zygoteServer) 
throws Zygote.MethodAndArgsCaller {
    ...//
    //读取写入的参数
    args = readArgumentList();
    ...//
    //for进程
    pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, 
                    parsedArgs.gids, parsedArgs.debugFlags, 
                    rlimits, parsedArgs.mountExternal, 
                    parsedArgs.seInfo,
                    parsedArgs.niceName, 
                    fdsToClose, parsedArgs.instructionSet,
                    parsedArgs.appDataDir);    
    if (pid == 0) {
    // in child
        zygoteServer.closeServerSocket();
        IoUtils.closeQuietly(serverPipeFd);
        serverPipeFd = null;
        //处理子进程
        handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr);

        // should never get here, the child is expected to either
        // throw Zygote.MethodAndArgsCaller or exec().
        return true;
    } else {
        // in parent...pid of < 0 means failure
        IoUtils.closeQuietly(childPipeFd);
        childPipeFd = null;
        return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs);
    }
    ...//
}
//处理函数
private void handleChildProc(Arguments parsedArgs,
            FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)
            throws Zygote.MethodAndArgsCaller {
    ...//省略
    if (parsedArgs.niceName != null) {
        Process.setArgV0(parsedArgs.niceName);
    }
    // End of the postFork event.
    Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
    if (parsedArgs.invokeWith != null) {
        WrapperInit.execApplication(parsedArgs.invokeWith,
                parsedArgs.niceName, parsedArgs.targetSdkVersion,
                VMRuntime.getCurrentInstructionSet(),
                pipeFd, parsedArgs.remainingArgs);
    } else {
        //进入这个分支
        //很熟悉,貌似见过。
        //对,是他是他就是他,在system_server启动的时候也是掉了这个,最后还抛了异常回到main函数
        RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion,
                parsedArgs.remainingArgs, null /* classLoader */);
    }
}

5 总结

Zygote在Java世界是爸爸,其他的都是他fork出来的,包括非常重要system_server,其次zygote还要这响应创建应用的请求。system_server也是不得了,是老大。Java世界的服务都得由他来启动。

上一篇 《第三章 - Init》读书笔记
下一篇 《第五章 - 常见类》读书笔记

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容