本文主要是介绍android 开机启动流程分析(11)Zygote启动分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
该系列文章总纲链接:专题分纲目录 android 开机启动流程分析
本章关键点总结 & 说明:
这里因为整体的导图太大,因此截取一部分 ,方便大家看的清楚:
同时,下面的图是开机启动流程分析 持续迭代的效果,可放大观看。
说明:思维导图是基于之前文章不断迭代的,本章内容我们关注➕"zygote"部分即可
1 Zygote启动分析
zygote的关键作用:从实现从native层到java层的调用,是由init进程根据init.rc文件中的配置项而创建的。
zygote名字的来历:zygote最初的名字叫app_process,这是在Android.mk文件中被指定的,但app_process在运行过程中通过Linux下的pctrl系统调用将自己的名字换成了zygote,所以我们通过ps命令看到的进程名是zygote。
1.1 解析zygote.rc
init进程启动后会解析zygote.rc,在文件中/system/core/rootdir/init.rc中包含了zygote.rc。其中${ro.zygote}是平台相关的参数,实际可对应到init.zygote32.rc, init.zygote64.rc, init.zygote64_32.rc, init.zygote32_64.rc,前两个只会启动单一app_process进程,而后两个则会启动两个app_process进程:第二个app_process进程称为secondary(有相应 secondary socket 的创建过程)。这里以 /system/core/rootdir/init.zygote32.rc 为例:
#import /init.${ro.zygote}.rc
service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-serverclass mainsocket zygote stream 660 root systemonrestart write /sys/android_power/request_state wakeonrestart write /sys/power/state ononrestart restart mediaonrestart restart netd
首先创建了名为zygote 的进程,这个进程是通过app_process的main 启动并以对应参数作为main的入口参数。
1.2 zygote启动
@1 zygote的原型app_process所对应的源文件是app_main.cpp,核心代码如下所示:
// Zygote进程由init通过fork而来,init.rc中设置的启动参数:
// -Xzygote/system/bin,--zygote,--start-system-server
int main(int argc, char* const argv[]) //这里argc=4,argv[0],argv[1],argv[2],argv[3]
{//...//参数的解析与处理1,startAppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));argc--;//argc=3argv++;//argv变成argv[1],argv[2],argv[3]int i;for (i = 0; i < argc; i++) {if (argv[i][0] != '-') {break;}if (argv[i][1] == '-' && argv[i][2] == 0) {++i; // Skip --.break;}//在option中添加参数 --zygote --start-system-server -Xzygote/system/binruntime.addOption(strdup(argv[i]));}//解析参数,根据传递进来的参数值来初始化对应的bool类型变量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;//将要设置的zygote别名} 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()) {//app mode,启动app时才不为空args.add(application ? String8("application") : String8("tool"));runtime.setClassNameAndArgs(className, argc - i, argv + i);} else {//zygote mode.初次进入,className为空,进这个分支maybeCreateDalvikCache();if (startSystemServer) {args.add(String8("start-system-server"));//args添加1项字符串}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);//通过属性获取ABI-Listargs.add(abiFlag);//args添加1项字符串for (; i < argc; ++i) {args.add(String8(argv[i]));}}//参数的解析与处理1,end//AppRuntime类继承了AndroidRuntime类,重载了onStarted、onZygoteInit和onExit函数if (!niceName.isEmpty()) {runtime.setArgv0(niceName.string());set_process_name(niceName.string());//设置本进程名为zygote,是个“换名把戏”。}if (zygote) {//调用runtime的start,注意这里第二个参数args中包含SystemServerruntime.start("com.android.internal.os.ZygoteInit", args);} else if (className) {//调用runtime的start,注意这里第二个参数args中包含app启动相关参数runtime.start("com.android.internal.os.RuntimeInit", args);} else {app_usage();//不是zygote模式,也不是app模式return 10;}
}
zygote主要做了2件事情
- zygote模式下,初始化参数,调用runtime{实际上就是AndroidRuntime}的start方法启动java类
- app启动模式下,初始化参数,调用runtime{实际上就是AndroidRuntime}的start方法启动app进程
@2 runtime的start方法,分析其代码实现:
void AndroidRuntime::start(const char* className, const Vector<String8>& options)
{...//创建虚拟机,关键点1,startJniInvocation jni_invocation;//这两句是在Android 4.4上出现的,在Android 4.0上,还没有它们jni_invocation.Init(NULL);// 初始化JNI接口JNIEnv* env;if (startVm(&mJavaVM, &env) != 0) {return;}onVmCreated(env);//创建虚拟机,关键点1,end//注册JNI函数,关键点2,startstartReg(env)...//注册JNI函数,关键点2,end//启动Java类,对于zygote模式是ZygoteInit类,关键点3,startjclass 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. 该线程会成为VM的主线程, 主线程退出之前不会/**toSlashClassName将字符串“com.android.internal.os.ZygoteInit”中的“. ”换成“/”,变成了“com/android/internal/os/ZygoteInit”,这个名字符合JNI规范,后面简称为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);} else {//通过JNI调用Java函数,注意调用的函数是main,所属的类是com.android.internal.os.ZygoteInit,//传递的参数是“com.android.internal.os.ZygoteInit ”与args(包含systemServer),//调用ZygoteInit的main后,Zygote进入了Java世界!//也就是说,Zygote是开创Android系统中Java世界的盘古。env->CallStaticVoidMethod(startClass, startMeth, strArray);}}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系统,所以已经定义了HAVE_ANDROID_OS宏,而且library参数为NULL,于是在JniInvocation的Init()函数中,会走到
property_get(kLibrarySystemProperty, default_library, kLibraryFallback);
kLibrarySystemProperty的定义是“persist.sys.dalvik.vm.lib”,这是个系统属性,它记录着系统实际需要用到的是哪种虚拟机(dalvik/ART)分别对应libdvm.so或libart.so。dlopen()之后会尝试加载libdvm.so或libart.so。这两个so中都export出了JNI_GetDefaultJavaVMInitArgs,JNI_CreateJavaVM和JNI_GetCreatedJavaVMs这三个接口函数。这里,我们找到了三个关键点,它们共同组成了开创Android系统中的Java世界。接下来对另外2个关键点进行详细的分析
@3 startVM{创建虚拟机}的代码实现如下所示:
int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv)
{...//这个函数绝大部分代码都是设置虚拟机的参数,我们只分析其中的两个。bool checkJni = false;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;}}/**JNI check选项指的是native层调用JNI函数时系统做的一些检查检查工作比较耗时,一般是在eng版本中使用检查工作比较严格,一旦出错直接导致调用进程abort*/if (checkJni) {addOption("-Xcheck:jni");// extended JNI checkingaddOption("-Xjnigreflimit:2000");//JNIcheck中的资源检查,系统中创建的Globalreference个数不能超过2000}...parseRuntimeOption("dalvik.vm.heapstartsize", heapstartsizeOptsBuf, "-Xms", "4m");//设置虚拟机heapsize,默认为16MB。绝大多数厂商都会修改这个值,一般是32MB。//heapsize不能设置过小,否则在操作大尺寸的图片时无法分配所需内存。//parseRuntimeOption抓要是解析属性,将其加入到对应的Vector中parseRuntimeOption("dalvik.vm.heapsize", heapsizeOptsBuf, "-Xmx", "16m");// libart tolerates libdvm flags, but not vice versa, so only pass some options if libart.//判断是否为art模式启动property_get("persist.sys.dalvik.vm.lib.2", dalvikVmLibBuf, "libart.so");bool libart = (strncmp(dalvikVmLibBuf, "libart", 6) == 0);...initArgs.version = JNI_VERSION_1_4;initArgs.options = mOptions.editArray();initArgs.nOptions = mOptions.size();initArgs.ignoreUnrecognized = JNI_FALSE;//调用JNI_CreateJavaVM创建虚拟机,pEnv返回当前线程的JNIEnv变量if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {ALOGE("JNI_CreateJavaVM failed\n");goto bail;}result = 0;
bail:return result;
}
这里主要做了2件事情,初始化虚拟机参数,调用JNI_CreateJavaVM方法初始化虚拟机。
说明:关于dalvik虚拟机的参数见Dalvik/Docs/Dexopt.html中的说明。
@4 注册JNI函数startReg
因为后续Java程序用到的一些函数是采用native方式来实现的,所以才必须提前注册这些函数。startReg函数,代码如下所示:
static const RegJNIRec gRegJNI[] = {REG_JNI(register_com_android_internal_os_RuntimeInit),REG_JNI(register_android_os_SystemClock),...REG_JNI(register_com_android_internal_net_NetworkStatsFactory),
};int AndroidRuntime::startReg(JNIEnv* env)
{//设置Thread类的线程创建函数为javaCreateThreadEtcandroidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);env->PushLocalFrame(200);//注册jni函数,gRegJNI是一个全局数组。/**register_jni_procs:仅仅是一个封装,调用gRegJNI数组中每个元素的mProc函数 */if (register_jni_procs(gRegJNI, NELEM(gRegJNI), env) < 0) {env->PopLocalFrame(NULL);return -1;}env->PopLocalFrame(NULL);//下面这句话应当是“码农”休闲时的小把戏。测试用的代码。//createJavaThread("fubar", quickTest, (void*)"hello");return 0;
}
这里注意:即mProc就是为Java类注册JNI函数。这里继续查看JNI注册函数的实现,一般代码如下:
int register_com_android_internal_os_RuntimeInit(JNIEnv* env)
{ //为android.internal.os.RuntimeInit类注册它所需要的JNI函数return jniRegisterNativeMethods(env, "com/android/internal/os/RuntimeInit", gMethods, NELEM(gMethods));
}
至此,虚拟机已创建好,JNI函数也已注册,下一步就要分析CallStaticVoidMethod了。
通过这个函数,我们将进入Android的Java世界。{说明:如果再次回到native世界,要么是挂了,要么重启。}
2 Zygote进入Java世界
CallStaticVoidMethod启动该java类,最终调用com.android.internal.os.ZygoteInit的main函数。代码如下所示:
public static void main(String argv[]) {try {...registerZygoteSocket(socketName);//注册Zygote用的socket,关键点1EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,SystemClock.uptimeMillis());addBootEvent(new String("Zygote:Preload Start"));preload();//预加载类和资源,关键点2EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,SystemClock.uptimeMillis());SamplingProfilerIntegration.writeZygoteSnapshot();gc();// 强制一次垃圾收集addBootEvent(new String("Zygote:Preload End"));if (startSystemServer) { //我们传入的参数满足if分支startSystemServer(abiList, socketName);//关键点3,启动system_server进程}runSelectLoop(abiList);//关键点4,zygote调用这个函数,开始监听来自AMS的请求closeServerSocket();//关闭socket} catch (MethodAndArgsCaller caller) {caller.run(); //关键点5,如果有异常,会获取caller,很重要的caller run函数。见#2里SystemServer分析中} catch (RuntimeException ex) {Log.e(TAG, "Zygote died with exception", ex);closeServerSocket();throw ex;}}
接下来分别针对4个关键点进行分析
2.1 建立IPC通信服务端registerZygoteSocket
Zygote以及系统中其他程序的通信没有使用Binder,而是采用了基于AF_UNIX类型的Socket。
registerZygoteSocket函数的使命正是建立这个Socket。代码如下所示:
//只分析核心逻辑,省略部分代码private static void registerZygoteSocket(String socketName) {if (sServerSocket == null) {int fileDesc;final String fullSocketName = ANDROID_SOCKET_PREFIX + socketName;String env = System.getenv(fullSocketName);// 从环境变量的字符串中解析出文件描述符fileDesc = Integer.parseInt(env);//创建服务端Socket,这个Socket将listen并accept ClientsServerSocket = new LocalServerSocket(createFileDescriptor(fileDesc));}}
2.2 预加载类和资源
preload的实现代码如下:
static void preload() {Log.d(TAG, "begin preload");Log.i(TAG1, "preloadMappingTable() -- start ");PluginLoader.preloadPluginInfo();Log.i(TAG1, "preloadMappingTable() -- end "); preloadClasses();//类的预加载preloadResources();//资源的预加载preloadOpenGL();//openGL相关预加载相关preloadSharedLibraries();//共享库相关预加载相关// Ask the WebViewFactory to do any initialization that must run in the zygote process,// for memory sharing purposes.WebViewFactory.prepareWebViewInZygote();Log.d(TAG, "end preload");}
这里着重分析preloadClasses和preloadResources
2.2.1 preloadClasses的代码实现如下所示:
//只分析核心逻辑,省略部分代码
private static void preloadClasses() {final VMRuntime runtime = VMRuntime.getRuntime();InputStream is;//预加载类的信息存储在"/system/etc/preloaded-classes"文件中;is = new FileInputStream(PRELOADED_CLASSES);long startTime = SystemClock.uptimeMillis();// Drop root perms while running static initializers.setEffectiveGroup(UNPRIVILEGED_GID);setEffectiveUser(UNPRIVILEGED_UID);// Alter the target heap utilization. With explicit GCs this's not likely to have any effect.float defaultUtilization = runtime.getTargetHeapUtilization();runtime.setTargetHeapUtilization(0.8f);// Start with a clean slate.System.gc();runtime.runFinalizationSync();int count = 0;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;}Class.forName(line); //通过Java反射来加载类,line中存储的是预加载的类名(每行读出来就是一个类名)if (Debug.getGlobalAllocSize() > PRELOAD_GC_THRESHOLD) {System.gc();runtime.runFinalizationSync();}count++;}Log.i(TAG, "...preloaded " + count + " classes in " + (SystemClock.uptimeMillis()-startTime) + "ms.");} finally {IoUtils.closeQuietly(is);// Restore default.runtime.setTargetHeapUtilization(defaultUtilization);// Fill in dex caches with classes, fields, and methods brought in by preloading.runtime.preloadDexCaches();Debug.stopAllocCounting();// Bring back root. We'll need it later.setEffectiveUser(ROOT_UID);setEffectiveGroup(ROOT_GID);addBootEvent(new String("Zygote:Preload "+ count + " classes in " +(SystemClock.uptimeMillis()-startTime)+ "ms"));}
}
preloadClasses看起来是如此简单,但是需要预先加载的类很多(在framework/base目录下),它是一个文本文件,内容如下:
# Classes which are preloaded bycom.android.internal.os.ZygoteInit.
# Automatically generated by frameworks/base/tools/preload/WritePreloadedClassFile.java.
# MIN_LOAD_TIME_MICROS=1250 //超时控制
android.R$styleable
android.accounts.AccountManager
android.accounts.AccountManager$4
android.accounts.AccountManager$6
android.accounts.AccountManager$AmsTask
android.accounts.AccountManager$BaseFutureTask
android.accounts.AccountManager$Future2Task
......//一共有3009行
特殊说明:
- preload_class文件由framework/base/tools/preload工具生成,它需要判断每个类加载的时间是否大于1250微秒。
- 超过这个时间的类就会被写到preload-classes文件中,最后由zygote预加载。
- preloadClass函数的执行时间比较长,这是导致Android系统启动慢的原因之一。
2.2.2 preloadResources的代码实现如下所示:
private static void preloadResources() {final VMRuntime runtime = VMRuntime.getRuntime();System.gc();runtime.runFinalizationSync();mResources = Resources.getSystem();mResources.startPreloading();if (PRELOAD_RESOURCES) {//与图片有关资源的获取和预加载TypedArray ar = mResources.obtainTypedArray(com.android.internal.R.array.preloaded_drawables);int N = preloadDrawables(runtime, ar);ar.recycle();//与颜色有关资源的获取和预加载ar = mResources.obtainTypedArray(com.android.internal.R.array.preloaded_color_state_lists);N = preloadColorStateLists(runtime, ar);ar.recycle();}mResources.finishPreloading();...
}
@1 加载第一类资源需要调用preloadDrawables(),逐个加载TypedArray里记录的图片资源,preloadDrawables()的实现如下:
private static int preloadDrawables(VMRuntime runtime, TypedArray ar) {int N = ar.length();for (int i=0; i<N; i++) {...int id = ar.getResourceId(i, 0);//得到数组项对应的资源id了/**mResources是ZygoteInit的私有静态成员getDrawable->loadDrawable(value, id, theme);加载drawable对象-->cacheDrawable(value, theme, isColorDrawable, caches, key, dr)//缓存到本地到此,这些图片资源就都加载到ZygoteInit的mResources里了。 */mResources.getDrawable(id, null);...}return N;
}
@2 加载第二类资源是颜色资源,是用preloadColorStateLists()加载的:
private static int preloadColorStateLists(VMRuntime runtime, TypedArray ar) {int N = ar.length();for (int i=0; i<N; i++) {...int id = ar.getResourceId(i, 0);/**mResources是ZygoteInit的私有静态成员->loadColorStateList(value, id);//加载colorstatelits对象-->sPreloadedColorStateLists.put(key, csl);//缓存到本地到此,这些颜色资源就都加载到ZygoteInit的mResources里了。 */mResources.getColorStateList(id);...}return N;
}
preloadResources和preloadClass类似,都主要是加载framework-res.apk中的资源。
说明:在UI编程中常使用的com.android.R.XXX资源,是系统默认的资源,它们就是由Zygote加载的。
@3 preloadOpenGL主要是加载openGL相关。
@4 preloadSharedLibraries的代码实现如下所示:
private static void preloadSharedLibraries() {//加载各种各样的so库Log.i(TAG, "Preloading shared libraries...");System.loadLibrary("android");System.loadLibrary("compiler_rt");System.loadLibrary("jnigraphics");
}
2.3 启动system_server
这个函数会创建Java世界中系统Service所驻留的进程system_server,该进程是framework的核心。如果它挂了,就会导致zygote自杀重启。启动systen_server的代码如下所示:
private static boolean startSystemServer(String abiList, String socketName) throws MethodAndArgsCaller, RuntimeException {long capabilities = posixCapabilitiesAsBits(OsConstants.CAP_BLOCK_SUSPEND,...OsConstants.CAP_SYS_TTY_CONFIG);//设置参数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。parsedArgs = new ZygoteConnection.Arguments(args);ZygoteConnection.applyDebuggerSystemProperty(parsedArgs);ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs);/* Request to fork the system server process */pid = Zygote.forkSystemServer(//fork一个子进程,这个子进程就是system_server进程。 ...parsedArgs.effectiveCapabilities);} catch (IllegalArgumentException ex) {throw new RuntimeException(ex);}/* For child process */if (pid == 0) {pid为零,则表示处于子进程中,也就是处于system_server进程中if (hasSecondZygote(abiList)) {//hasSecondZygote 是针对 init.zygote64_32.rc, init.zygote32_64.rc 这两者情况的waitForSecondaryZygote(socketName);}handleSystemServerProcess(parsedArgs);system_server进程的工作,后面会单独分析}return true;}
Zygote进行了一次分裂,fork一个system_server子进程。同时,这里的args字符串详细内容如下所示:
2.4 等待请求runSelectLoop
在{第1个关键点处}registerZygoteSocket中注册了一个用于IPC的Socket,在这个runSelectLoop中体现出来,实现如下:
private 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是我们先前在registerZygoteSocket建立的Socketfds.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--;}fdArray = fds.toArray(fdArray);//selectReadable内部调用select,使用多路复用I/O模型。当有客户端连接或有数据时,则selectReadable就会返回。index = selectReadable(fdArray);//返回-1表示错误,返回0表示fd不在监听的集合fd_set内,返回>0,表示fd在fd_set中if (index == 0) {//如有监听到一个客户端连接上,其客户端在Zygote的代表是ZygoteConnectionZygoteConnection newPeer = acceptCommandPeer(abiList);peers.add(newPeer); //添加peer对象fds.add(newPeer.getFileDescriptor());//将newPeer的fd添加fds的描述符集合中} else {boolean done;//客户端发送了请求,peers.get返回的是ZygoteConnection//后续处理将交给ZygoteConnection的runOnce函数完成。done = peers.get(index).runOnce(); //后面根据AMS数据来创建对象时会调用该方法if (done) {peers.remove(index);fds.remove(index);}}}
}
runSelectLoopMode实现的功能是:
- 处理客户连接和客户请求。其中客户在Zygote中用ZygoteConnection对象来表示。
- 客户的请求由ZygoteConnection的runOnce来处理。
3 Zygote的总结
Zygote是创建Android系统中Java世界的盘古,它创建了第一个Java虚拟机,且它成功创建了一个子进程system_server。回顾一下Zygote创建Java世界的步骤:
- 创建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后一直等待子孙们的请求。
4 一个疑问?为啥zygote不使用binder机制和systemserver之间进行通信呢?
这里主要是怕父进程binder线程有锁,然后子进程的主线程一直在等其子线程(从父进程拷贝过来的子进程)的资源,但是其实父进程的子进程并没有被拷贝过来,造成死锁,所以fork不允许存在多线程。而非常巧的是Binder通讯偏偏就是多线程,所以干脆父进程(Zgote)这个时候就不使用binder线程。详细内容可以参照一篇比较好的文章,👇:为什么SystemServer进程与Zygote进程通讯采用Socket而不是Binder
这篇关于android 开机启动流程分析(11)Zygote启动分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!