深入理解zygote
来源:互联网 发布:java se8 编辑:程序博客网 时间:2024/05/22 11:55
Zygote分析
zygote本身是一个native的应用程序。通过对init的解析,我们知道zygote是通过init进程根据init.rc文件中的配置项创建的,其实是通过init进程fork和execve产生的。zygote最原始的名字叫"app_process",是在其Android.mk中指定的,但是在运行过程中,将自己的名字修改成了"zygote"。
zygote的这个main函数比较简单,但是重要功能却是由AppRuntime完成的,接下来分析AppRuntime。
AppRuntime(frameworks/base/cmds/app_process)分析
AppRuntime继承与AndroidRuntime(/frameworks/base/core/jni),并且重载了onStarted()、onZygoteInit()、onExit()函数。前面调用了AppRuntime的start方法实际上是调用了AndroidRuntime的start()。
通过上面的分析,我们知道从native层进入java层需要关键的三个步骤:
(1)startVm
(2)startReg
(3)env->CallStaticVoidMethod(startClass, startMeth, strArray)
1.创建虚拟机-startVm
2.注册JNI函数-startReg
前面已经介绍了如何创建虚拟机,下一步则需要给这个虚拟机注册一些JNI函数。正是因为后续java世界用到的一些函数是native层实现的,所以才必须提前注册这些函数。
REG_JNI是一个宏,宏里边包括的就是那个mProc函数。
至此虚拟机已创建好,JNI函数已注册,下一步就是要分析CallStaticVoidMethod了,通过这个函数将从native世界进入java世界了。
根据前面的分析得知,CallStaticVoidMethod最终调用的是com.android.internal.os.ZygoteInit的main函数
2.预加载一些类和资源--preload()
|->preloadClasses()
preload()--
|->preloadResources()
上述的预加载类比较简单,但是预加载这些类非常耗时,比如我现在正在做的mtk5.0项目中,这个preloaded-classes有3000行,也就是需要预加载3000个类。
preloaded-classes这个文件由frameworks/base/tools/preload工具生成,它会判断每个类加载是否超过1250微秒,如果超时则会被写入到preloaded-classes文件中,最后由zygote进行预加载。
preloadResources和preloadClasses类似,加载的是framework-res.apk中的资源。即frameworks/base/core/res/res目录下的资源。
3.开始启动system_server进程--startSystemServer(abiList, socketName)
4.有求必应之等待请求-runSelectLoop(abiList)
当zygote从startSystemServer返回后,将会进入runSelectLoop中,在这之前registerZygoteSocket注册了一个socket,不过还没地方用到,其实主要用在runSelectLoop中。
runSelectLoop比较简单,即
1.处理客户端的连接和请求,其中客户端在zygote中用ZygoteConnection对象描述。
2.客户端的请求由ZygoteCoonection的runOnce()处理。
关于zygote的总结:
zygote在Android系统中创建了java世界,它创建了第一个java虚拟机,它fork出了system_server进程,zygote创建java世界的步骤:
1.创建AppRuntime对象,并调用它的start方法,实际上调用的是它的基类即AndroidRuntime的start方法。
2.创建虚拟机(startVm)、注册JNI函数(startReg)。
3.利用JNI调用java世界的ZygoteInit.java的main方法(CallStaticVoidMethod),从此进入java世界,但是这个时候java世界什么都没有。
4.在这个java世界中,调用registerZygoteSocket。通过这个函数可以响应子孙后代的请求。同时,zygote调用preloadClasses和preloadResources,为java世界添砖加瓦。
5.zygote觉得工作压力太大,就分裂出一个system_server为java世界服务。
SystemServer分析
我们先看一下SystemServer是怎么产生的。
从代码分析可知,system_server是通过zygote进程fork而来,forkSystemServer最终调用的native层代码:
接下来分析上述两点:
1.nativeZygoteInit()
2.invokeStaticMain
前面说到启动system_server进程之后,就是调用runSelectLoop,等待客户端的响应了,那么谁会向zygote发送请求呢?
这里以Activity的启动为例进行分析。
ActivityManagerService发送请求,ActivityManagerService也是由system_server启动的。假设通过startActivity来启动一个Activity,那么这个Activity附属于一个未启动的进程,这个进程该如何启动?
先来看一下ActivityManagerService中的startProcessLocked函数,代码如下:
ActivityManagerService的请求时序图如下:
zygote本身是一个native的应用程序。通过对init的解析,我们知道zygote是通过init进程根据init.rc文件中的配置项创建的,其实是通过init进程fork和execve产生的。zygote最原始的名字叫"app_process",是在其Android.mk中指定的,但是在运行过程中,将自己的名字修改成了"zygote"。
app_process对应的源文件是app_main.cpp
-->app_main.cpp(frameworks/base/cmds/app_process/app_main.cpp)int main(int argc, char* const argv[]){ /*zygote进程是由init进程fork而来,init.rc文件中为zygote进程设置的启动参数如下:service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server其中zygote是要创建的进程/system/bin/app_process是要执行的应用程序-Xzygote /system/bin --zygote --start-system-server 是传入的参数argc = 4argv = {"-Xzygote","/system/bin","--zygote","--start-system-server"}*/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++;//添加虚拟机参数,结果返回0 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])); } }//就是在这里修改app_process为zygote的 if (!niceName.isEmpty()) { runtime.setArgv0(niceName.string()); set_process_name(niceName.string()); }//调用AppRuntime的start方法 if (zygote) { runtime.start("com.android.internal.os.ZygoteInit", args); } else if (className) { runtime.start("com.android.internal.os.RuntimeInit", args); } 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; }}
zygote的这个main函数比较简单,但是重要功能却是由AppRuntime完成的,接下来分析AppRuntime。
AppRuntime(frameworks/base/cmds/app_process)分析
AppRuntime继承与AndroidRuntime(/frameworks/base/core/jni),并且重载了onStarted()、onZygoteInit()、onExit()函数。前面调用了AppRuntime的start方法实际上是调用了AndroidRuntime的start()。
void AndroidRuntime::start(const char* className, const char* options){ if (!strcmp(className, "com.android.internal.os.ZygoteInit")) { removeHprofEmptyFile(); } /* * 'startSystemServer == true' means runtime is obsolete and not run from * init.rc anymore, so we print out the boot start event here. */ if (strcmp(options, "start-system-server") == 0) { /* 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))); }//如果环境变量中没有"ANDROID_ROOT",则新增该变量,并设置值为"/system" 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;//1.创建虚拟机 if (startVm(&mJavaVM, &env) != 0) { return; } onVmCreated(env); /* * Register android functions. *///2.注册JNI函数 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; jstring optionsStr; stringClass = env->FindClass("java/lang/String"); assert(stringClass != NULL);//创建一个有两个元素的string数组 strArray = env->NewObjectArray(2, stringClass, NULL); assert(strArray != NULL); classNameStr = env->NewStringUTF(className); assert(classNameStr != NULL);//设置第一个元素为"com.android.internal.os.ZygoteInit" env->SetObjectArrayElement(strArray, 0, classNameStr); optionsStr = env->NewStringUTF(options);
<span style="white-space:pre">//设置第二个元素为"start-system-server"</span> env->SetObjectArrayElement(strArray, 1, optionsStr); /* * Start VM. This thread becomes the main thread of the VM, and will * not return until the VM exits. *///将com.android.internal.os.ZygoteInit转换成"com/android/internal/os/ZygoteInit" char* slashClassName = toSlashClassName(className); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'\n", slashClassName); /* keep going */ } else {//找到ZygoteInit类的static main函数的JMethodId 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 {//3.通过JNI调用java函数,注意调用的函数是main,所属的类是"com.android.internal.os.ZygoteInit"//在调用了ZygoteInit的main函数之后,zygote便进入了java世界 env->CallStaticVoidMethod(startClass, startMeth, strArray);#if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env);#endif } } free(slashClassName);}
通过上面的分析,我们知道从native层进入java层需要关键的三个步骤:
(1)startVm
(2)startReg
(3)env->CallStaticVoidMethod(startClass, startMeth, strArray)
1.创建虚拟机-startVm
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv){//这个函数并没有什么特别的,我们只分析其中两点:/*下面代码是用来设置JNI check选项的。JNI check指的是Native层调用JNI函数时,系统会去做一些检查。*/property_get("dalvik.vm.checkjni", propBuf, ""); if (strcmp(propBuf, "true") == 0) { checkJni = true; } else if (strcmp(propBuf, "false") != 0) { /* property is neither true nor false; fall back on kernel parameter */ property_get("ro.kernel.android.checkjni", propBuf, ""); if (propBuf[0] == '1') { checkJni = true; } }/* * The default starting and maximum size of the heap. Larger * values should be specified in a product property override. */ strcpy(heapstartsizeOptsBuf, "-Xms"); property_get("dalvik.vm.heapstartsize", heapstartsizeOptsBuf+4, "4m"); opt.optionString = heapstartsizeOptsBuf; mOptions.add(opt);//设置虚拟机的heapsize,默认为16M。绝大多数厂商都会修改这个值,一般为32M strcpy(heapsizeOptsBuf, "-Xmx"); property_get("dalvik.vm.heapsize", heapsizeOptsBuf+4, "16m"); opt.optionString = heapsizeOptsBuf; mOptions.add(opt);/* * 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. *///创建dalvik虚拟机 if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) { ALOGE("JNI_CreateJavaVM failed\n"); goto bail; }}
2.注册JNI函数-startReg
前面已经介绍了如何创建虚拟机,下一步则需要给这个虚拟机注册一些JNI函数。正是因为后续java世界用到的一些函数是native层实现的,所以才必须提前注册这些函数。
int AndroidRuntime::startReg(JNIEnv* env){ /* * 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.) */ 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是一个全局数组,存放需要注册的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;}static int register_jni_procs(const RegJNIRec array[], size_t count, JNIEnv* env){ for (size_t i = 0; i < count; i++) {//调用数组元素的mProce方法 if (array[i].mProc(env) < 0) { return -1; } } return 0;}接下来看一下gRegJNI全局数组static const RegJNIRec gRegJNI[] = { REG_JNI(register_com_android_internal_os_RuntimeInit), REG_JNI(register_android_os_SystemClock), REG_JNI(register_android_util_EventLog), REG_JNI(register_android_util_Log), REG_JNI(register_com_mediatek_xlog_Xlog)}
REG_JNI是一个宏,宏里边包括的就是那个mProc函数。
至此虚拟机已创建好,JNI函数已注册,下一步就是要分析CallStaticVoidMethod了,通过这个函数将从native世界进入java世界了。
根据前面的分析得知,CallStaticVoidMethod最终调用的是com.android.internal.os.ZygoteInit的main函数
-->ZygoteInit.javapublic static void main(String argv[]) { try { /// M: Added for BOOTPROF //MTPROF_DISABLE = "1".equals(SystemProperties.get("ro.mtprof.disable")); MTPROF_DISABLE = false; // Start profiling the zygote initialization. SamplingProfilerIntegration.start(); boolean startSystemServer = false; String socketName = "zygote"; String abiList = null;//从native层传进来的参数是[com.android.internal.os.ZygoteInit,start-system-server] 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."); }//1.注册zygote用的socket registerZygoteSocket(socketName); EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START, SystemClock.uptimeMillis()); /// M: Added for BOOTPROF addBootEvent(new String("Zygote:Preload Start"));//2.预加载一些类和资源 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//强制执行一次垃圾回收 gc(); // Disable tracing so that forked processes do not inherit stale tracing tags from // Zygote. Trace.setTracingEnabled(false); /// M: Added for BOOTPROF addBootEvent(new String("Zygote:Preload End"));//在这里startSystemServer为true if (startSystemServer) {//3.开始启动system_server进程 startSystemServer(abiList, socketName); } Log.i(TAG, "Accepting command socket connections");//4.zygote调用这个函数 runSelectLoop(abiList);//关闭socket closeServerSocket(); } catch (MethodAndArgsCaller caller) {//5.很重要的caller run caller.run(); } catch (RuntimeException ex) { Log.e(TAG, "Zygote died with exception", ex); closeServerSocket(); throw ex; } }}
在ZygoteInit的main函数中,主要做了5点,下面一一分析。
1.注册zygote需要用的socket--registerZygoteSocket(socketName);
/** * Registers a server socket for zygote command connections * * @throws RuntimeException when open fails */private static void registerZygoteSocket(String socketName) {if (sServerSocket == null) {int fileDesc;final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;try {//从环境变量中获取socket的fd,这个环境变量是从init进程中通过execv传入。String env = System.getenv(fullSocketName);fileDesc = Integer.parseInt(env);} catch (RuntimeException ex) {throw new RuntimeException(fullSocketName + " unset or invalid", ex);}try {//创建服务端的socket,这个socket将listen并accept clientsServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));} catch (IOException ex) {throw new RuntimeException("Error binding to local socket '" + fileDesc + "'", ex);}}}//注册zygote所需要的socket很简单,但是应该想谁是客户端?服务端怎么处理客户端的消息的?
2.预加载一些类和资源--preload()
|->preloadClasses()
preload()--
|->preloadResources()
-->preloadClasses()private static void preloadClasses() { final VMRuntime runtime = VMRuntime.getRuntime();//预加载类的信息存储在PRELOADED_CLASSES中,它的值为preloaded-classes,路径在frameworks/base/preloaded-classes InputStream is = ClassLoader.getSystemClassLoader().getResourceAsStream(PRELOADED_CLASSES); if (is == null) { Log.e(TAG, "Couldn't find " + PRELOADED_CLASSES + "."); } else { Log.i(TAG, "Preloading classes..."); ...... //做一些统计工作 try { BufferedReader br = new BufferedReader(new InputStreamReader(is), 256); String line; while ((line = br.readLine()) != null) { // Skip comments and blank lines. line = line.trim();//按行读取,并忽略#开头的注释行 if (line.startsWith("#") || line.equals("")) { continue; } try { if (false) { Log.v(TAG, "Preloading " + line + "..."); }//通过java反射来加载类,line中存储的是预加载的类名 Class.forName(line); if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) { if (false) { Log.v(TAG, " GC at " + Debug.getGlobalAllocSize()); } System.gc(); runtime.runFinalizationSync(); Debug.resetGlobalAllocSize(); } count++; } catch (ClassNotFoundException e) { .... } catch (UnsatisfiedLinkError e) { .... } catch (Throwable t) { .... } } } catch (IOException e) { .... } finally { .... } }}
上述的预加载类比较简单,但是预加载这些类非常耗时,比如我现在正在做的mtk5.0项目中,这个preloaded-classes有3000行,也就是需要预加载3000个类。
preloaded-classes这个文件由frameworks/base/tools/preload工具生成,它会判断每个类加载是否超过1250微秒,如果超时则会被写入到preloaded-classes文件中,最后由zygote进行预加载。
preloadResources和preloadClasses类似,加载的是framework-res.apk中的资源。即frameworks/base/core/res/res目录下的资源。
3.开始启动system_server进程--startSystemServer(abiList, socketName)
-->startSystemServer/** * Prepare the arguments and fork for the system server process. */private static boolean startSystemServer(String abiList, String socketName)throws MethodAndArgsCaller, RuntimeException {...//设置一些参数/* 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,1032,3001,3002,3003,3006,3007","--capabilities=" + capabilities + "," + capabilities,"--runtime-init","--nice-name=system_server",//进程名,叫system_server"com.android.server.SystemServer",//启动的类名};ZygoteConnection.Arguments parsedArgs = null;int pid;try {//将上述的参数数组转换成Arguments对象parsedArgs = new ZygoteConnection.Arguments(args);ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);/* Request to fork the system server process *///fork一个子进程,这个子进程就是system_serverpid = 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 *///fork的返回值等0则表示这是子进程if (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}//开始处理system_server进程,从此进入system_server的世界handleSystemServerProcess(parsedArgs);}return true;}
4.有求必应之等待请求-runSelectLoop(abiList)
当zygote从startSystemServer返回后,将会进入runSelectLoop中,在这之前registerZygoteSocket注册了一个socket,不过还没地方用到,其实主要用在runSelectLoop中。
-->runSelectLoopprivate static void runSelectLoop(String abiList) throws MethodAndArgsCaller { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); FileDescriptor[] fdArray = new FileDescriptor[4];//sServerSocket是之前创建的socket fds.add(sServerSocket.getFileDescriptor()); peers.add(null); int loopCount = GC_LOOP_COUNT; while (true) { int index; if (loopCount <= 0) { gc(); loopCount = GC_LOOP_COUNT; } else { loopCount--; } try { fdArray = fds.toArray(fdArray);/*selectReadable内部调用select,当有客户端连接或有数据时,则selectReadable就会返回*/ index = selectReadable(fdArray); } catch (IOException ex) { throw new RuntimeException("Error in select()", ex); } if (index < 0) { throw new RuntimeException("Error in select()"); } else if (index == 0) {//有一个客户端连接上。请注意,客户端在zygote的代表是ZygoteConnection ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDescriptor()); } else { boolean done;//客户端发送了请求,peers.get(index)返回的是ZygoteConnection,后续处理将调用ZygoteConnection的runOnce处理 done = peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } } }}
runSelectLoop比较简单,即
1.处理客户端的连接和请求,其中客户端在zygote中用ZygoteConnection对象描述。
2.客户端的请求由ZygoteCoonection的runOnce()处理。
关于zygote的总结:
zygote在Android系统中创建了java世界,它创建了第一个java虚拟机,它fork出了system_server进程,zygote创建java世界的步骤:
1.创建AppRuntime对象,并调用它的start方法,实际上调用的是它的基类即AndroidRuntime的start方法。
2.创建虚拟机(startVm)、注册JNI函数(startReg)。
3.利用JNI调用java世界的ZygoteInit.java的main方法(CallStaticVoidMethod),从此进入java世界,但是这个时候java世界什么都没有。
4.在这个java世界中,调用registerZygoteSocket。通过这个函数可以响应子孙后代的请求。同时,zygote调用preloadClasses和preloadResources,为java世界添砖加瓦。
5.zygote觉得工作压力太大,就分裂出一个system_server为java世界服务。
6.zygote完成了java世界的初创,它已经很满足了。下一步就是调用runSelectLoop,等待客户端的响应了。
Zygote的时序图如下:
SystemServer分析
我们先看一下SystemServer是怎么产生的。
-->startSystemServer/** * Prepare the arguments and fork for the system server process. */private static boolean startSystemServer(String abiList, String socketName)throws MethodAndArgsCaller, RuntimeException {...//设置一些参数/* 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,1032,3001,3002,3003,3006,3007","--capabilities=" + capabilities + "," + capabilities,"--runtime-init","--nice-name=system_server",//进程名,叫system_server"com.android.server.SystemServer",//启动的类名};ZygoteConnection.Arguments parsedArgs = null;int pid;try {//将上述的参数数组转换成Arguments对象parsedArgs = new ZygoteConnection.Arguments(args);ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);/* Request to fork the system server process *///fork一个子进程,这个子进程就是system_serverpid = 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 *///fork的返回值等0则表示这是子进程if (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}//开始处理system_server进程,从此进入system_server的世界handleSystemServerProcess(parsedArgs);}return true;}
从代码分析可知,system_server是通过zygote进程fork而来,forkSystemServer最终调用的native层代码:
-->dalvik_system_Zygote.cpp(这是高通平台下的,路径是/dalvik/vm/native)static void Dalvik_dalvik_system_Zygote_forkSystemServer( const u4* args, JValue* pResult){ pid_t pid;//根据参数,fork一个子进程 pid = forkAndSpecializeCommon(args, true); /* The zygote process checks whether the child process has died or not. */ if (pid > 0) { int status;//保存system_server的进程id gDvm.systemServerPid = pid; //函数退出前先检查刚刚创建的子进程是否退出了 if (waitpid(pid, &status, WNOHANG) == pid) { ALOGE("System server process %d has died. Restarting Zygote!", pid);//如果system_server退出了,zygote直接自杀,这是真爱 kill(getpid(), SIGKILL); } } RETURN_INT(pid);}static pid_t forkAndSpecializeCommon(const u4* args, bool isSystemServer){ pid_t pid; uid_t uid = (uid_t) args[0]; gid_t gid = (gid_t) args[1]; ArrayObject* gids = (ArrayObject *)args[2]; u4 debugFlags = args[3]; ArrayObject *rlimits = (ArrayObject *)args[4]; u4 mountMode = MOUNT_EXTERNAL_NONE; int64_t permittedCapabilities, effectiveCapabilities; char *seInfo = NULL; char *niceName = NULL;//设置信号处理 setSignalHandler(); dvmDumpLoaderStats("zygote");//fork子进程 pid = fork();.....}接下来看一下setSignalHandlerstatic void setSignalHandler(){ int err; struct sigaction sa; memset(&sa, 0, sizeof(sa)); sa.sa_handler = sigchldHandler; err = sigaction (SIGCHLD, &sa, NULL); if (err < 0) { ALOGW("Error setting SIGCHLD handler: %s", strerror(errno)); }}发现调用的是sigchldHandlerstatic void sigchldHandler(int s){ pid_t pid; int status;if (pid == gDvm.systemServerPid) {ALOG(LOG_INFO, ZYGOTE_LOG_TAG,"Exit zygote because system server (%d) has terminated",(int) pid);//如果system_server死了,zygote也要自杀了。kill(getpid(), SIGKILL);} if (pid < 0) { ALOG(LOG_WARN, ZYGOTE_LOG_TAG,"Zygote SIGCHLD error in waitpid: %s",strerror(errno)); }}通过代码分析,我们知道system_server和zygote真正做到了生死与共。接下来分析system_server的使命。从代码可知,system_server是从下面这几行代码开始的,if (pid == 0) {if (hasSecondZygote(abiList)) {waitForSecondaryZygote(socketName);}//开始处理system_server进程,从此进入system_server的世界handleSystemServerProcess(parsedArgs);}private static void handleSystemServerProcess(ZygoteConnection.Arguments parsedArgs)throws ZygoteInit.MethodAndArgsCaller {//关闭从Zygote那里继承下来的socketcloseServerSocket();//调用zygoteInit函数 RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, cl);}public static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {//做一些常规初始化 commonInit();//1.native层的初始化 nativeZygoteInit(); applicationInit(targetSdkVersion, argv, classLoader);}private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { .... final Arguments args; try { args = new Arguments(argv); } catch (IllegalArgumentException ex) { return; } // Remaining arguments are passed to the start class's static main//2.调用com.android.server.SystemServer类的main函数 invokeStaticMain(args.startClass, args.startArgs, classLoader);}
接下来分析上述两点:
1.nativeZygoteInit()
static void com_android_internal_os_RuntimeInit_nativeZygoteInit(JNIEnv* env, jobject clazz){//gCurRuntime即App_Runtime gCurRuntime->onZygoteInit();}virtual void onZygoteInit(){ // Re-enable tracing now that we're no longer in Zygote. atrace_set_tracing_enabled(true); sp<ProcessState> proc = ProcessState::self(); ALOGV("App process: starting thread pool.\n");//启动一个线程,用于Binder通信,这样system_server就可以使用binder了 proc->startThreadPool();}
2.invokeStaticMain
private static void invokeStaticMain(String className, String[] argv, ClassLoader classLoader)throws ZygoteInit.MethodAndArgsCaller { Class<?> cl;//这里的className是"com.android.server.SystemServer" try { cl = Class.forName(className, true, classLoader); } catch (ClassNotFoundException ex) { throw new RuntimeException("Missing class when invoking static main " + className, ex); } Method m; try { //找到com.android.server.SystemServer的main方法m = cl.getMethod("main", new Class[] { String[].class }); } catch (NoSuchMethodException ex) { throw new RuntimeException("Missing static main on " + className, ex); } catch (SecurityException ex) { throw new RuntimeException("Problem getting static main on " + className, ex); } int modifiers = m.getModifiers(); if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) { throw new RuntimeException("Main method is not public and static on " + className); } //抛出一个异常,为什么不直接调用main方法呢? throw new ZygoteInit.MethodAndArgsCaller(m, argv);}上述抛出的异常是在ZygoteInit中的main函数中拦截到的,catch (MethodAndArgsCaller caller) {//5.很重要的caller run caller.run();}public void run() { try {//这个mMethod为com.android.server.SystemServer的main方法 mMethod.invoke(null, new Object[] { mArgs }); } catch (IllegalAccessException ex) { .... } }
Zygote进程fork出来的system_server进程,其实就是为了调用com.android.server.SystemServer的main函数。接下来看一下SystemServer.java的main函数。
public static void main(String[] args) { new SystemServer().run();}private void run() {//将当前进程设置成前台进程 // Prepare the main looper thread (this thread). android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_FOREGROUND); android.os.Process.setCanSelfBackground(false);//创建looper对象并与当前线程绑定 Looper.prepareMainLooper();//加载libandroid_servers.so // Initialize native services. System.loadLibrary("android_servers");//调用native Init函数 nativeInit(); // Initialize the system context. createSystemContext(); // Create the system service manager. mSystemServiceManager = new SystemServiceManager(mSystemContext); LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);/*这里就是system_server的主要功能了,即启动各项服务*/ // Start services. try { startBootstrapServices(); startCoreServices(); startOtherServices(); } catch (Throwable ex) { ..... } // Loop forever. Looper.loop();}
前面说到启动system_server进程之后,就是调用runSelectLoop,等待客户端的响应了,那么谁会向zygote发送请求呢?
这里以Activity的启动为例进行分析。
ActivityManagerService发送请求,ActivityManagerService也是由system_server启动的。假设通过startActivity来启动一个Activity,那么这个Activity附属于一个未启动的进程,这个进程该如何启动?
先来看一下ActivityManagerService中的startProcessLocked函数,代码如下:
-->ActivityManagerService.javaprivate 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);..... }-->Process.javapublic static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String[] zygoteArgs) { try {//调用startViaZygote return startViaZygote(processClass, niceName, uid, gid, gids, debugFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, zygoteArgs); } catch (ZygoteStartFailedEx ex) { Log.e(LOG_TAG, "Starting VM process through Zygote failed"); throw new RuntimeException( "Starting VM process through Zygote failed", ex); }}private static ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int debugFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String[] extraArgs) throws ZygoteStartFailedEx { synchronized(Process.class) { ...//注意这里调用了openZygoteSocketIfNeeded(abi),打开了和zygote通信的socket return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); }} private static ProcessStartResult zygoteSendArgsAndGetResult(ZygoteState zygoteState, ArrayList<String> args)throws ZygoteStartFailedEx { try { final BufferedWriter writer = zygoteState.writer; final DataInputStream inputStream = zygoteState.inputStream; writer.write(Integer.toString(args.size())); writer.newLine();//把请求的参数发到zygote int sz = args.size(); for (int i = 0; i < sz; i++) { String arg = args.get(i); if (arg.indexOf('\n') >= 0) { throw new ZygoteStartFailedEx(embedded newlines not allowed"); } writer.write(arg); writer.newLine(); } writer.flush(); // Should there be a timeout on this? ProcessStartResult result = new ProcessStartResult();//读取zygote处理完的结果,便可得知是某个进程的pid result.pid = inputStream.readInt(); if (result.pid < 0) { throw new ZygoteStartFailedEx("fork() failed"); } result.usingWrapper = inputStream.readBoolean(); return result; } catch (IOException ex) { zygoteState.close(); throw new ZygoteStartFailedEx(ex); }}由于ActivityManagerService驻留于system_server进程中,所以是system_server向zygote发送了消息。
根据上述代码,我们知道ActivityManagerService已经向zygote发起请求了。那么再看一下zygote是如何响应的。
-->ZygoteInit.javaprivate static void runSelectLoop(String abiList) throws MethodAndArgsCaller {try { fdArray = fds.toArray(fdArray); index = selectReadable(fdArray); } catch (IOException ex) { ... } else if (index == 0) { ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDescriptor()); } else { boolean done;//每当有请求时,zygote都会调用ZygoteConnection的runOnce() done = peers.get(index).runOnce(); if (done) { peers.remove(index); fds.remove(index); } }} -->ZygoteConnection.java boolean runOnce() throws ZygoteInit.MethodAndArgsCaller {//读取system_server发送过来的参数 try { args = readArgumentList(); descriptors = mSocket.getAncillaryFileDescriptors(); } catch (IOException ex) { .... } int pid = -1; try {//zygote又分裂出来一个子进程 pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.debugFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, parsedArgs.instructionSet, parsedArgs.appDataDir); checkTime(startTime, "zygoteConnection.runOnce: postForkAndSpecialize"); } catch (IOException ex) { .... } try { if (pid == 0) {//子进程处理,这个子进程是不是我们需要创建的Activity的子进程呢? handleChildProc(parsedArgs, descriptors, childPipeFd, newStderr); return true; } else { return handleParentProc(pid, descriptors, serverPipeFd, parsedArgs); } }....}private void handleChildProc(Arguments parsedArgs,FileDescriptor[] descriptors, FileDescriptor pipeFd, PrintStream newStderr)throws ZygoteInit.MethodAndArgsCaller {//关闭连接的socket closeSocket(); ZygoteInit.closeServerSocket(); if (parsedArgs.runtimeInit) { if (parsedArgs.invokeWith != null) { WrapperInit.execApplication(parsedArgs.invokeWith, parsedArgs.niceName, parsedArgs.targetSdkVersion, pipeFd, parsedArgs.remainingArgs); } else { RuntimeInit.zygoteInit(parsedArgs.targetSdkVersion, parsedArgs.remainingArgs, null /* classLoader */); } }}-->RuntimeInit.javapublic static final void zygoteInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller {//做一些常规初始化 commonInit();//1.native层的初始化,最终会调用到AppRuntime的onZygoteInit,在那个函数中建立了与binder的关系 nativeZygoteInit(); applicationInit(targetSdkVersion, argv, classLoader);}private static void applicationInit(int targetSdkVersion, String[] argv, ClassLoader classLoader) throws ZygoteInit.MethodAndArgsCaller { .... final Arguments args; try { args = new Arguments(argv); } catch (IllegalArgumentException ex) { return; } // Remaining arguments are passed to the start class's static main//这里调用的是android.app.ActivityThread类的main函数 invokeStaticMain(args.startClass, args.startArgs, classLoader);}
ActivityManagerService的请求时序图如下:
0 0
- 深入理解Zygote
- 深入理解zygote
- 深入理解Zygote
- android启动--深入理解zygote
- android启动--深入理解zygote
- android启动--深入理解zygote
- android启动--深入理解zygote (II)
- Zygote (深入理解android 卷1)
- 深入理解Android之init与zygote
- android启动--深入理解zygote (II)
- 深入理解Android(05)——深入理解zygote
- 《深入理解Android 卷I》init和zygote
- 深入理解zygote——1(代码源于GooGle)
- 深入理解zygote——2(代码源于GooGle)
- 深入理解Android(08)——深入理解zygote的分裂原理
- [深入理解Android卷一全文-第四章]深入理解zygote
- [深入理解Android卷一全文-第四章]深入理解zygote
- [深入理解Android卷一全文-第四章]深入理解zygote
- 复数中的运算符重载(续)
- mac下tomcat的安装与配置
- [SQL] 查询某个字段值类型的数量
- 递归实现:字符串反向排序.
- [spark]spark读取postgresql的表(纯SQL方式)
- 深入理解zygote
- 模板类与类模板、函数模板与模板函数等的区别
- GlusterFS Split-Brain Recovery Made Easy
- 如何下载网页中嵌入的flash文件
- 【第一章】 Spring概述 ——跟我学Spring3
- 循序渐进Java Socket网络编程(多客户端、信息共享、文件传输)
- Nginx系列(九.nginx日志分割)
- IOS中集合视图UICollectionView中DecorationView的简易使用方法
- 冒泡排序