Zygote及System进程启动

 

1.  init 根据init.rc 运行 app_process, 并携带‘--zygote' 和 ’--startSystemServer' 参数。java

2.  AndroidRuntime.cpp::start() 里将启动JavaVM,而且注册全部framework相关的系统JNI接口。linux

3.  第一次进入Java世界,运行ZygoteInit.java::main() 函数初始化Zygote. Zygote 并建立Socket的server 端。android

4.  而后fork一个新的进程并在新进程里初始化SystemServer. Fork以前,Zygote是preload经常使用的Java类库,以及系统的resources,同时GC()清理内存空间,为子进程省去重复的工做。app

5.  SystemServer 里将全部的系统Service初始化,包括ActivityManager 和 WindowManager, 他们是应用程序运行起来的前提。框架

6.  与此同时,Zygote监听服务端Socket,等待新的应用启动请求。less

7.  ActivityManager ready 以后寻找系统的“Startup” Application, 将请求发给Zygote。dom

8.  Zygote收到请求后,fork出一个新的进程。socket

9.  Zygote监听并处理SystemServer 的 SIGCHID 信号,一旦System Server崩溃,当即将本身杀死。init会重启Zygote.ide

 

如下内容主要针对上面的介绍展开,附上两张图,这两张图片包含了咱们今天要讲解的全部内容函数

zygote启动流程图

 

 zygote相关的全部类的结构图

 

  这里要讲的是zygote启动流程因此主要针对第一张图来说 ,关于这部份内容,我的以为,对于想本身开发系统的人来讲是颇有帮助,每一个系统首先启动的即是孵化器进程,以及server监听进程。

一 概念

  在Android系统中,全部的应用程序和系统服务进程,都是Zygote负责建立的,所以,Zygote也就被成为进程孵化器。Zygote进程是经过复制自身的方式来建立System进程和应用程序进程的。 Zygote会在系统启动时建立一个虚拟机实例,所以,经过复制Zygote进程而获得的System进程和应用程序进程能够快速第在内部得到一个虚拟机实例拷贝。  

  Zygote进程启动完成以后,会将system进程启动起来,以便它能够将系统的关键服务启动起来。例如AMS ContentService 和WMS及PMS等。

二 Zygote启动  

  Zygote进程在init进程启动过程当中被以service服务的形式启动,代码以下:./system/core/rootdir/init.zygote32.rc的service_start()

    service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server   ...  socket zygote stream 660 root system

    onrestart write /sys/android_power/request_state wake
    onrestart write /sys/power/state on
    onrestart restart media
    onrestart restart netd

   前面的关键字service告诉init进程建立一个名为"zygote"的进程,这个zygote进程要执行的程序是/system/bin/app_process,后面是要传给app_process的参数。 

        接下来的socket关键字表示这个zygote进程须要一个名称为"zygote"的socket资源,这样,系统启动后,咱们就能够在/dev/socket目录下看到有一个名为zygote的文件。这里定义的socket的类型为unix domain socket,它是用来做本地进程间通讯用的。前面咱们说到的ActivityManagerService就是通这个socket来和zygote进程通讯请求fork一个应用程序进程的了。

        最后的一系列onrestart关键字表示这个zygote进程重启时须要执行的命令。

        关于init.rc文件的更多信息,请参考system/core/init/readme.txt文件。

        了解了这个信息以后,咱们就知道Zygote进程要执行的程序即是system/bin/app_process了,它的源代码位于frameworks/base/cmds/app_process/app_main.cpp文件中,入口函数是main。 

 在继续分析Zygote进程启动的过程以前,咱们先来看看它的启动序列图: 

下面咱们就详细分析每个步骤。

        Step 1. app_process.main

        这个函数定义在frameworks/base/cmds/app_process/app_main.cpp文件中:

int main(int argc, char* const argv[]) { if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) { // Older kernels don't understand PR_SET_NO_NEW_PRIVS and return // EINVAL. Don't die on such kernels.
        if (errno != EINVAL) { LOG_ALWAYS_FATAL("PR_SET_NO_NEW_PRIVS failed: %s", strerror(errno)); return 12; } } AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv)); // Process command line arguments // ignore argv[0]
    argc--; argv++; // Everything up to '--' or first non '-' arg goes to the vm. //
    // The first argument after the VM args is the "parent dir", which // is currently unused. //
    // After the parent dir, we expect one or more the following internal // arguments : //
    // --zygote : Start in zygote mode // --start-system-server : Start the system server. // --application : Start in application (stand alone, non zygote) mode. // --nice-name : The nice name for this process. //
    // For non zygote starts, these arguments will be followed by // the main class name. All remaining arguments are passed to // the main method of this class. //
    // For zygote starts, all remaining arguments are passed to the zygote. // main function. //
    // Note that we must copy argument string values since we will rewrite the // entire argument block when we apply the nice name to argv0.

    int i; for (i = 0; i < argc; i++) { if (argv[i][0] != '-') { break; } if (argv[i][1] == '-' && argv[i][2] == 0) { ++i; // Skip --.
            break; } runtime.addOption(strdup(argv[i])); } // 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++]; if (strcmp(arg, "--zygote") == 0) { zygote = true; niceName = ZYGOTE_NICE_NAME; } else if (strcmp(arg, "--start-system-server") == 0) { startSystemServer = true; } else if (strcmp(arg, "--application") == 0) { application = true; } else if (strncmp(arg, "--nice-name=", 12) == 0) { niceName.setTo(arg + 12); } else if (strncmp(arg, "--", 2) != 0) { className.setTo(arg); break; } else { --i; break; } } Vector<String8> args; if (!className.isEmpty()) { // We're not in zygote mode, the only argument we need to pass // to RuntimeInit is the application argument. //
        // The Remainder of args get passed to startup class main(). Make // copies of them before we overwrite them with the process name.
        args.add(application ? String8("application") : String8("tool")); runtime.setClassNameAndArgs(className, argc - i, argv + i); } else { // We're in zygote mode.
 maybeCreateDalvikCache(); if (startSystemServer) { args.add(String8("start-system-server")); } 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()); set_process_name(niceName.string()); } 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."); return 10; } }

  这个函数的主要做用就是建立一个AppRuntime变量,而后调用它的start成员函数。它一样是在frameworks/base/cmds/app_process/app_main.cpp文件中定义:

class AppRuntime : public AndroidRuntime { public: AppRuntime(char* argBlockStart, const size_t argBlockLength) : AndroidRuntime(argBlockStart, argBlockLength) , mClass(NULL) { } void setClassNameAndArgs(const String8& className, int argc, char * const *argv) { mClassName = className; for (int i = 0; i < argc; ++i) { mArgs.add(String8(argv[i])); } } virtual void onVmCreated(JNIEnv* env) { if (mClassName.isEmpty()) { return; // Zygote. Nothing to do here.
 } /* * This is a little awkward because the JNI FindClass call uses the * class loader associated with the native method we're executing in. * If called in onStarted (from RuntimeInit.finishInit because we're * launching "am", for example), FindClass would see that we're calling * from a boot class' native method, and so wouldn't look for the class * we're trying to look up in CLASSPATH. Unfortunately it needs to, * because the "am" classes are not boot classes. * * The easiest fix is to call FindClass here, early on before we start * executing boot class Java code and thereby deny ourselves access to * non-boot classes. */
        char* slashClassName = toSlashClassName(mClassName.string()); mClass = env->FindClass(slashClassName); if (mClass == NULL) { ALOGE("ERROR: could not find class '%s'\n", mClassName.string()); } free(slashClassName); mClass = reinterpret_cast<jclass>(env->NewGlobalRef(mClass)); } virtual void onStarted() { sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); AndroidRuntime* ar = AndroidRuntime::getRuntime(); ar->callMain(mClassName, mClass, mArgs); IPCThreadState::self()->stopProcess(); } virtual void onZygoteInit() { sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n"); proc->startThreadPool(); } virtual void onExit(int code) { if (mClassName.isEmpty()) { // if zygote
            IPCThreadState::self()->stopProcess(); } AndroidRuntime::onExit(code); } String8 mClassName; Vector<String8> mArgs; jclass mClass; }; }

  它继承于AndroidRuntime类, AndroidRuntime类定义在frameworks/base/core/jni/AndroidRuntime.cpp文件中:

static AndroidRuntime* gCurRuntime = NULL; ... AndroidRuntime::AndroidRuntime(char* argBlockStart, const size_t argBlockLength) : mExitWithoutCleanup(false), mArgBlockStart(argBlockStart), mArgBlockLength(argBlockLength) { SkGraphics::Init(); // There is also a global font cache, but its budget is specified by // SK_DEFAULT_FONT_CACHE_COUNT_LIMIT and SK_DEFAULT_FONT_CACHE_LIMIT. // Pre-allocate enough space to hold a fair number of options.
    mOptions.setCapacity(20); assert(gCurRuntime == NULL);        // one per process
    gCurRuntime = this; }

    当AppRuntime对象建立时,会调用其父类AndroidRuntime的构造函数,而在AndroidRuntime类的构造函数里面,会将this指针保存在静态全局变量gCurRuntime中,这样,当其它地方须要使用这个AppRuntime对象时,就能够经过同一个文件中的这个函数来获取这个对象的指针:

AndroidRuntime* AndroidRuntime::getRuntime() { return gCurRuntime; }

  回到上面的main函数中,因为咱们在init.rc文件中,设置了app_process启动参数--zygote和--start-system-server,所以,在main函数里面,最终会执行下面语句:

runtime.start("com.android.internal.os.ZygoteInit", args, zygote);

   这里的参数startSystemServer为true,表示要启动SystemServer组件。因为AppRuntime没有实现本身的start函数,它继承了父类AndroidRuntime的start函数,所以,下面会执行AndroidRuntime类的start函数。

        Step 2. AndroidRuntime.start

        这个函数定义在frameworks/base/core/jni/AndroidRuntime.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) { ALOGD(">>>>>> START %s uid %d <<<<<<\n", className != NULL ? className : "(unknown)", getuid()); static const String8 startSystemServer("start-system-server"); /* * 'startSystemServer == true' means runtime is obsolete and not run from * init.rc anymore, so we print out the boot start event here. */
    for (size_t i = 0; i < options.size(); ++i) { if (options[i] == startSystemServer) { /* track our progress through the boot sequence */
           const int LOG_BOOT_PROGRESS_START = 3000; LOG_EVENT_LONG(LOG_BOOT_PROGRESS_START, ns2ms(systemTime(SYSTEM_TIME_MONOTONIC))); } } const char* rootDir = getenv("ANDROID_ROOT"); if (rootDir == NULL) { rootDir = "/system"; if (!hasDir("/system")) { LOG_FATAL("No root directory specified, and /android does not exist."); return; } setenv("ANDROID_ROOT", rootDir, 1); } //const char* kernelHack = getenv("LD_ASSUME_KERNEL"); //ALOGD("Found LD_ASSUME_KERNEL='%s'\n", kernelHack);

    /* 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. */
    if (startReg(env) < 0) { ALOGE("Unable to register all android natives\n"); return; } /* * 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); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL); env->SetObjectArrayElement(strArray, 0, classNameStr); 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. */
    char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else { jmethodID startMeth = env->GetStaticMethodID(startClass, "main", "([Ljava/lang/String;)V"); if (startMeth == NULL) { ALOGE("JavaVM unable to find main() in '%s'\n", className); /* keep going */ } else { env->CallStaticVoidMethod(startClass, startMeth, strArray); #if 0
            if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } 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"); }

   这个函数的做用是启动Android系统运行时库,它主要作了三件事情,一是调用函数startVM启动虚拟机,二是调用函数startReg注册JNI方法,三是调用了com.android.internal.os.ZygoteInit类的main函数。

        Step 3. ZygoteInit.main

        这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

public static void main(String argv[]) { try { RuntimeInit.enableDdms(); // 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]); } } if (abiList == null) { throw new RuntimeException("No ABI list supplied."); } registerZygoteSocket(socketName); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); preload(); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END, SystemClock.uptimeMillis()); // Finish profiling the zygote initialization.
 SamplingProfilerIntegration.writeZygoteSnapshot(); // Do an initial gc to clean up after startup
 gcAndFinalize(); // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote.
            Trace.setTracingEnabled(false); if (startSystemServer) { startSystemServer(abiList, socketName); } Log.i(TAG, "Accepting command socket connections"); runSelectLoop(abiList); closeServerSocket(); } catch (MethodAndArgsCaller caller) { caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }

  它主要做了三件事情,一个调用registerZygoteSocket函数建立了一个socket接口,用来和ActivityManagerService通信,二是调用startSystemServer函数来启动SystemServer组件,三是调用runSelectLoopMode函数进入一个无限循环在前面建立的socket接口上等待ActivityManagerService请求建立新的应用程序进程。 

         Step 4. ZygoteInit.registerZygoteSocket

         这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

  private static void registerZygoteSocket(String socketName) { if (sServerSocket == null) { int fileDesc; final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName; try { String env = System.getenv(fullSocketName); fileDesc = Integer.parseInt(env); } catch (RuntimeException ex) { throw new RuntimeException(fullSocketName + " unset or invalid", ex); } try { FileDescriptor fd = new FileDescriptor(); fd.setInt$(fileDesc); sServerSocket = new LocalServerSocket(fd); } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } }

  这个socket接口是经过文件描述符来建立的,这个文件描符表明的就是咱们前面说的/dev/socket/zygote文件了。这个文件描述符是经过环境变量ANDROID_SOCKET_ENV获得的,它定义为:

public class ZygoteInit { ...... private static final String ANDROID_SOCKET_ENV = "ANDROID_SOCKET_zygote"; ...... } 

  那么,这个环境变量的值又是由谁来设置的呢?咱们知道,系统启动脚本文件system/core/rootdir/init.rc是由init进程来解释执行的,而init进程的源代码位于system/core/init目录中,在init.cpp文件中,是由service_start函数来解释init.rc文件中的service命令的:

void service_start(struct service *svc, const char *dynamic_args) { // Starting a service removes it from the disabled or reset state and // immediately takes it out of the restarting state if it was in there.
    svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET|SVC_RESTART|SVC_DISABLED_START)); svc->time_started = 0; // Running processes require no additional work --- if they're in the // process of exiting, we've ensured that they will immediately restart // on exit, unless they are ONESHOT.
    if (svc->flags & SVC_RUNNING) { return; } bool needs_console = (svc->flags & SVC_CONSOLE); if (needs_console && !have_console) { ERROR("service '%s' requires console\n", svc->name); svc->flags |= SVC_DISABLED; return; } struct stat s; if (stat(svc->args[0], &s) != 0) { ERROR("cannot find '%s', disabling '%s'\n", svc->args[0], svc->name); svc->flags |= SVC_DISABLED; return; } if ((!(svc->flags & SVC_ONESHOT)) && dynamic_args) { ERROR("service '%s' must be one-shot to use dynamic args, disabling\n", svc->args[0]); svc->flags |= SVC_DISABLED; return; } char* scon = NULL; if (is_selinux_enabled() > 0) { if (svc->seclabel) { scon = strdup(svc->seclabel); if (!scon) { ERROR("Out of memory while starting '%s'\n", svc->name); return; } } else { char *mycon = NULL, *fcon = NULL; INFO("computing context for service '%s'\n", svc->args[0]); int rc = getcon(&mycon); if (rc < 0) { ERROR("could not get context while starting '%s'\n", svc->name); return; } rc = getfilecon(svc->args[0], &fcon); if (rc < 0) { ERROR("could not get context while starting '%s'\n", svc->name); freecon(mycon); return; } rc = security_compute_create(mycon, fcon, string_to_security_class("process"), &scon); if (rc == 0 && !strcmp(scon, mycon)) { ERROR("Warning! Service %s needs a SELinux domain defined; please fix!\n", svc->name); } freecon(mycon); freecon(fcon); if (rc < 0) { ERROR("could not get context while starting '%s'\n", svc->name); return; } } } NOTICE("Starting service '%s'...\n", svc->name); pid_t pid = fork(); if (pid == 0) { struct socketinfo *si; struct svcenvinfo *ei; char tmp[32]; int fd, sz; umask(077); if (properties_initialized()) { get_property_workspace(&fd, &sz); snprintf(tmp, sizeof(tmp), "%d,%d", dup(fd), sz); add_environment("ANDROID_PROPERTY_WORKSPACE", tmp); } for (ei = svc->envvars; ei; ei = ei->next) add_environment(ei->name, ei->value); for (si = svc->sockets; si; si = si->next) { int socket_type = ( !strcmp(si->type, "stream") ? SOCK_STREAM : (!strcmp(si->type, "dgram") ? SOCK_DGRAM : SOCK_SEQPACKET)); int s = create_socket(si->name, socket_type, si->perm, si->uid, si->gid, si->socketcon ?: scon); if (s >= 0) {  publish_socket(si->name, s); } } freecon(scon); scon = NULL; if (svc->writepid_files_) { std::string pid_str = android::base::StringPrintf("%d", pid); for (auto& file : *svc->writepid_files_) { if (!android::base::WriteStringToFile(pid_str, file)) { ERROR("couldn't write %s to %s: %s\n", pid_str.c_str(), file.c_str(), strerror(errno)); } } } if (svc->ioprio_class != IoSchedClass_NONE) { if (android_set_ioprio(getpid(), svc->ioprio_class, svc->ioprio_pri)) { ERROR("Failed to set pid %d ioprio = %d,%d: %s\n", getpid(), svc->ioprio_class, svc->ioprio_pri, strerror(errno)); } } if (needs_console) { setsid(); open_console(); } else { zap_stdio(); } if (false) { for (size_t n = 0; svc->args[n]; n++) { INFO("args[%zu] = '%s'\n", n, svc->args[n]); } for (size_t n = 0; ENV[n]; n++) { INFO("env[%zu] = '%s'\n", n, ENV[n]); } } setpgid(0, getpid()); // As requested, set our gid, supplemental gids, and uid.
        if (svc->gid) { if (setgid(svc->gid) != 0) { ERROR("setgid failed: %s\n", strerror(errno)); _exit(127); } } if (svc->nr_supp_gids) { if (setgroups(svc->nr_supp_gids, svc->supp_gids) != 0) { ERROR("setgroups failed: %s\n", strerror(errno)); _exit(127); } } if (svc->uid) { if (setuid(svc->uid) != 0) { ERROR("setuid failed: %s\n", strerror(errno)); _exit(127); } } if (svc->seclabel) { if (is_selinux_enabled() > 0 && setexeccon(svc->seclabel) < 0) { ERROR("cannot setexeccon('%s'): %s\n", svc->seclabel, strerror(errno)); _exit(127); } } if (!dynamic_args) { if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) { ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno)); } } else { char *arg_ptrs[INIT_PARSER_MAXARGS+1]; int arg_idx = svc->nargs; char *tmp = strdup(dynamic_args); char *next = tmp; char *bword; /* Copy the static arguments */ memcpy(arg_ptrs, svc->args, (svc->nargs * sizeof(char *))); while((bword = strsep(&next, " "))) { arg_ptrs[arg_idx++] = bword; if (arg_idx == INIT_PARSER_MAXARGS) break; } arg_ptrs[arg_idx] = NULL; execve(svc->args[0], (char**) arg_ptrs, (char**) ENV); } _exit(127); } freecon(scon); if (pid < 0) { ERROR("failed to start '%s'\n", svc->name); svc->pid = 0; return; } svc->time_started = gettime(); svc->pid = pid; svc->flags |= SVC_RUNNING; if ((svc->flags & SVC_EXEC) != 0) { INFO("SVC_EXEC pid %d (uid %d gid %d+%zu context %s) started; waiting...\n", svc->pid, svc->uid, svc->gid, svc->nr_supp_gids, svc->seclabel ? : "default"); waiting_for_exec = true; } svc->NotifyStateChange("running"); }

   每个service命令都会促使init进程调用fork函数来建立一个新的进程,在新的进程里面,会分析里面的socket选项,对于每个socket选项,都会经过create_socket函数来在/dev/socket目录下建立一个文件,在这个场景中,这个文件即是zygote了,而后获得的文件描述符经过publish_socket函数写入到环境变量中去:

static void publish_socket(const char *name, int fd) { char key[64] = ANDROID_SOCKET_ENV_PREFIX; char val[64]; strlcpy(key + sizeof(ANDROID_SOCKET_ENV_PREFIX) - 1, name, sizeof(key) - sizeof(ANDROID_SOCKET_ENV_PREFIX)); snprintf(val, sizeof(val), "%d", fd); add_environment(key, val); /* make sure we don't close-on-exec */ fcntl(fd, F_SETFD, 0); }

  这里传进来的参数name值为"zygote",而ANDROID_SOCKET_ENV_PREFIX在system/core/include/cutils/sockets.h定义为:

#define ANDROID_SOCKET_ENV_PREFIX       "ANDROID_SOCKET_"
#define ANDROID_SOCKET_DIR              "/dev/socket"

   所以,这里就把上面获得的文件描述符写入到以"ANDROID_SOCKET_zygote"为key值的环境变量中。又由于上面的ZygoteInit.registerZygoteSocket函数与这里建立socket文件的create_socket函数是运行在同一个进程中,所以,上面的ZygoteInit.registerZygoteSocket函数能够直接使用这个文件描述符来建立一个Java层的LocalServerSocket对象。若是其它进程也须要打开这个/dev/socket/zygote文件来和Zygote进程进行通讯,那就必需要经过文件名来链接这个LocalServerSocket了,ActivityManagerService是经过Process.start函数来建立一个新的进程的,而Process.start函数会首先经过Socket链接到Zygote进程中,最终由Zygote进程来完成建立新的应用程序进程,而Process类是经过openZygoteSocketIfNeeded函数来链接到Zygote进程中的Socket的:frameworks/base/core/java/android/os/Process.java


  public static final String ZYGOTE_SOCKET = "zygote";
  /** * Tries to open socket to Zygote process if not already open. If * already open, does nothing. May block and retry. */ private static ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { if (primaryZygoteState == null || primaryZygoteState.isClosed()) { try { primaryZygoteState = ZygoteState.connect(ZYGOTE_SOCKET); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe); } } if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } // The primary zygote didn't match. Try the secondary. if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { try { secondaryZygoteState = ZygoteState.connect(SECONDARY_ZYGOTE_SOCKET); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe); } } if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }

 ZYGOTE_SOCKET恰好就是对应/dev/socket目录下的zygote文件了。 

        Android系统中的socket机制和binder机制同样,都是能够用来进行进程间通讯。

       Socket对象建立完成以后,回到Step 3中的ZygoteInit.main函数中,startSystemServer函数来启动SystemServer组件。

       Step 5. ZygoteInit.startSystemServer
       这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

/** * Prepare the arguments and fork for the system server process. */
    private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_BLOCK_SUSPEND, 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_RESOURCE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG ); /* 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,1032,3001,3002,3003,3006,3007", "--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 */ 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) { if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } handleSystemServerProcess(parsedArgs); } return true; }

   这里咱们能够看到,Zygote进程经过Zygote.forkSystemServer函数来建立一个新的进程来启动SystemServer组件,返回值pid等0的地方就是新的进程要执行的路径,即新建立的进程会执行handleSystemServerProcess函数。 

        Step 6. ZygoteInit.handleSystemServerProcess
        这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

/** * Finish remaining work for the newly forked system server process. */
    private static void handleSystemServerProcess( ZygoteConnection.Arguments parsedArgs) throws ZygoteInit.MethodAndArgsCaller { closeServerSocket(); // 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) { performSystemServerDexOpt(systemServerClasspath); } if (parsedArgs.invokeWith != null) { String[] args = parsedArgs.remainingArgs; // If we have a non-null system server class path, we'll have to duplicate the // existing arguments and append the classpath to it. ART will handle the classpath // correctly when we exec a new process.
            if (systemServerClasspath != null) { String[] amendedArgs = new String[args.length + 2]; amendedArgs[0] = "-cp"; amendedArgs[1] = systemServerClasspath; System.arraycopy(parsedArgs.remainingArgs, 0, amendedArgs, 2, parsedArgs.remainingArgs.length); } WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, VMRuntime.getCurrentInstructionSet(), null, args); } else { ClassLoader cl = null; if (systemServerClasspath != null) { cl = new PathClassLoader(systemServerClasspath, ClassLoader.getSystemClassLoader()); Thread.currentThread().setContextClassLoader(cl); } /* * Pass the remaining arguments to SystemServer. */ RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl); } /* should never reach here */ }

  因为由Zygote进程建立的子进程会继承Zygote进程在前面Step 4中建立的Socket文件描述符,而这里的子进程又不会用到它,所以,这里就调用closeServerSocket函数来关闭它。这个函数接着调用RuntimeInit.zygoteInit函数来进一步执行启动SystemServer组件的操做。 

        Step 7. RuntimeInit.zygoteInit

        这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

/** * The main function called when started through the zygote process. This * could be unified with main(), if the native code in nativeFinishInit() * were rationalized with Zygote startup.<p> * * Current recognized args: * <ul> * <li> <code> [--] &lt;start class name&gt; &lt;args&gt; * </ul> * * @param targetSdkVersion target SDK version * @param argv arg strings */
    public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { if (DEBUG) Slog.d(TAG, "RuntimeInit: Starting application from zygote"); Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "RuntimeInit"); redirectLogStreams(); commonInit(); nativeZygoteInit(); applicationInit(targetSdkVersion, argv, classLoader); }

  这个函数会执行两个操做,一个是调用zygoteInitNative函数来执行一个Binder进程间通讯机制的初始化工做,这个工做完成以后,这个进程中的Binder对象就能够方便地进行进程间通讯了,另外一个是调用上面Step 5传进来的com.android.server.SystemServer类的main函数。 

         Step 8. RuntimeInit.nativeZygoteInit

         这个函数定义在frameworks/base/core/java/com/android/internal/os/RuntimeInit.java文件中:

public class RuntimeInit { ...... public static final native void nativeZygoteInit(); ...... }

   这里能够看出,函数nativeZygoteInit是一个Native函数,实如今frameworks/base/core/jni/AndroidRuntime.cpp文件中,完成这一步后,这个进程的Binder进程间通讯机制基础设施就准备好了。 

        回到Step 7中的RuntimeInit.nativeZygoteInit函数,下一步它就要执行com.android.server.SystemServer类的main函数了。

        Step 9. SystemServer.main

        这个函数定义在frameworks/base/services/java/com/android/server/SystemServer.java文件中:

/** * The main entry point from zygote. */
    public static void main(String[] args) { new SystemServer().run(); } public SystemServer() { // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode(); } private void run() { // If a device's clock is before 1970 (before 0), a lot of // APIs crash dealing with negative numbers, notably // java.io.File#setLastModified, so instead we fake it and // hope that time from cell towers or NTP fixes it shortly.
        if (System.currentTimeMillis() < EARLIEST_SUPPORTED_TIME) { Slog.w(TAG, "System clock is before 1970; setting to 1970."); SystemClock.setCurrentTimeMillis(EARLIEST_SUPPORTED_TIME); } // If the system has "persist.sys.language" and friends set, replace them with // "persist.sys.locale". Note that the default locale at this point is calculated // using the "-Duser.locale" command line flag. That flag is usually populated by // AndroidRuntime using the same set of system properties, but only the system_server // and system apps are allowed to set them. //
        // NOTE: Most changes made here will need an equivalent change to // core/jni/AndroidRuntime.cpp
        if (!SystemProperties.get("persist.sys.language").isEmpty()) { final String languageTag = Locale.getDefault().toLanguageTag(); SystemProperties.set("persist.sys.locale", languageTag); SystemProperties.set("persist.sys.language", ""); SystemProperties.set("persist.sys.country", ""); SystemProperties.set("persist.sys.localevar", ""); } // Here we go!
        Slog.i(TAG, "Entered the Android system server!"); EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, SystemClock.uptimeMillis()); // In case the runtime switched since last boot (such as when // the old runtime was removed in an OTA), set the system // property so that it is in sync. We can't do this in // libnativehelper's JniInvocation::Init code where we already // had to fallback to a different runtime because it is // running as root and we need to be the system user to set // the property. http://b/11463182
        SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary()); // Enable the sampling profiler.
        if (SamplingProfilerIntegration.isEnabled()) { SamplingProfilerIntegration.start(); mProfilerSnapshotTimer = new Timer(); mProfilerSnapshotTimer.schedule(new TimerTask() { @Override public void run() { SamplingProfilerIntegration.writeSnapshot("system_server", null); } }, SNAPSHOT_INTERVAL, SNAPSHOT_INTERVAL); } // Mmmmmm... more memory!
 VMRuntime.getRuntime().clearGrowthLimit(); // The system server has to run all of the time, so it needs to be // as efficient as possible with its memory usage.
        VMRuntime.getRuntime().setTargetHeapUtilization(0.8f); // Some devices rely on runtime fingerprint generation, so make sure // we've defined it before booting further.
 Build.ensureFingerprintProperty(); // Within the system server, it is an error to access Environment paths without // explicitly specifying a user.
        Environment.setUserRequired(true); // Ensure binder calls into the system always run at foreground priority.
        BinderInternal.disableBackgroundScheduling(true); // Prepare the main looper thread (this thread).
 android.os.Process.setThreadPriority( android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false); Looper.prepareMainLooper(); // Initialize native services.
        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.
 createSystemContext(); // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager); // Start services.
        try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { Slog.e("System", "******************************************"); Slog.e("System", "************ Failure starting system services", ex); throw ex; } // For debug builds, log event loop stalls to dropbox for analysis.
        if (StrictMode.conditionallyEnableDebugLogging()) { Slog.i(TAG, "Enabled StrictMode for system server main thread."); } // Loop forever.
 Looper.loop(); throw new RuntimeException("Main thread loop unexpectedly exited"); }

  这里执行完成后,层层返回,最后回到上面的Step 3中的ZygoteInit.main函数中,接下来它就要调用runSelectLoopMode函数进入一个无限循环在前面Step 4中建立的socket接口上等待ActivityManagerService请求建立新的应用程序进程了。

Step 10. ZygoteInit.runSelectLoopMode

        这个函数定义在frameworks/base/core/java/com/android/internal/os/ZygoteInit.java文件中:

/** * 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. * * @throws MethodAndArgsCaller in a child process when a main() should * be executed. */
    private static void runSelectLoop(String abiList) throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); fds.add(sServerSocket.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(); if (done) { peers.remove(i); fds.remove(i); } } } } }

   这个函数就是在等待ActivityManagerService来链接这个Socket,而后调用ZygoteConnection.runOnce函数来建立新的应用程序。

        这样,Zygote进程就启动完成了,学习到这里,咱们终于都对Android系统中的进程有了一个深入的认识了,这里总结一下:

        1. 系统启动时init进程会建立Zygote进程,Zygote进程负责后续Android应用程序框架层的其它进程的建立和启动工做。

        2. Zygote进程会首先建立一个SystemServer进程,SystemServer进程负责启动系统的关键服务,如包管理服务PackageManagerService和应用程序组件管理服务ActivityManagerService。

        3. 当咱们须要启动一个Android应用程序时,ActivityManagerService会经过Socket进程间通讯机制,通知Zygote进程为这个应用程序建立一个新的进程。

相关文章
相关标签/搜索