各位老司机们,现在闲下来终于有时间接着续写Android 9 Zygote进程启动源码分析指南二了,在前面的篇章Android P Zygote进程启动源码分析指南一中,我们已经讲解了zygote启动的前面阶段主要是为了孵化Android世界做的前期准备工作,大概的内容如下所示: 都说zygote开创了Android的世界,创造了五彩缤纷的Android生态,孵化了各式的上层App。那么本篇将会带领大伙看看,我们的zygote是怎么做到的!要的罗,让我们开干。 注意:本文演示的代码是Android P高通msm8953平台源码。其中涉及的源码路径如下: 在前面zygote启动阶段已经创建好了虚拟机,注册好了系统JNI函数,一切就绪只欠东风了!在接下来通过JNI的反射调用Java的类了。关于JNI的语法如果大伙有不熟悉的可以参见系列篇章JNI/NDK入门一锅端。 还是熟悉的味道,还是原来的配方,经过一顿猛如虎的操作最终调用CallStaticVoidMethod反射从而调用ZygoteInit的main函数, 兜兜转转,调用CallStaticVoidMethod终于登陆Java的世界了,Java世界真香,让我们畅游一番。 这里不过多详细解释,在main方法中主要做了如下几件事情: 该代码的路径是frameworks/base/core/java/com/android/internal/os/ZygoteServer.java,这里主要是通过解析zygote启动传入的变量值得到 zygote 文件描述符,根据该文件描述符创建 socket,用来和 ActivityManagerService 通信。AMS 通过 Process.start 来创建新的进程,而Process.start 会先通过 socket 连接到 zygote 进程,并最终由 zygote 完成进程创建。这里传入的-为-socket-name=zygote.。 LocalSocket是Android的妈咪谷歌为我们带来了,比Java本身的socket效率要高,没有经过协议栈,是Android自己实现的类似共享内存一样的东东,在传输大量数据的时候就需要用到,关于LocalSocket的介绍和使用大伙可以参考篇章Android Framework层和Native层通过LocalSocket实现通信。 我们知道ActivityManagerService 通过 Process.start 来创建新的进程,而 Process.start 会先通过socket 连接到 zygote 进程,并最终由 zygote 完成进程创建。如下是App进程创建请求Zygote创建新的进程。 我不知道大伙读到这里是否有一个疑问,为啥AMS和Zygote通信使用的是socket而不是Android的杜门绝技Binder,这个当初学习源码的时候也是我思考的,来大伙思考思考为啥Android的设计者是这么设计的呢,我认为主要有如下几个方面的考虑: 预加载类和资源,android Java 进程都是由 zygote 进程 fork,zygote 通过预加载类和资源可以加快子进程的执行速度和优化内存。因为预加载的类和资源较多,在开机优化过程中也需要重点关注 preload 的耗时。 当经过上述的步骤后,zygote进程内加载了preload()方法中的所有资源,当需要fork新进程时,采用COW(copy-on-write)技术,这里盗用已不在Android界的gityuan的一张图来说明: 该代码主要就是准备参数,并启动 system_server 进程,后续启动的Android Java 系统服务都将驻留在该进程中,它是是Android framework核心。这里主要设置了system_server 进程uid和gid,process name,class name。并且从zygote进程fork新进程后,需要关闭zygote原有的socket,另外,对于有两个zygote进程情况,需等待第2个zygote创建完成。 这里我有一个疑问就是设置的system_server进程的uid=1000,gid=1000可是实际ps查看的并不是,这个希望大伙一起探讨。 该代码定义在frameworks/base/core/java/com/android/internal/os/ZygoteServer.java,在这个阶段zygote将进入循环状态等待AMS来和zygote进行通信,从而孵化新的App。 从上面的代码可以看出,Zygote采用高效的I/O多路复用机制,保证在没有客户端连接请求或数据处理时休眠,否则响应客户端的请求。 该代码定义在frameworks/base/core/java/com/android/internal/os/ZygoteConnection.java中,解析socket客户端即AMS传递过来的参数,然后调用forkAndSpecialize创建App进程。 到这里zygote启动就基本告一段落了,zygote启动的调用流程图如下所示: Android 9 zygote启动就告一段落了,但是这个只是一个开端,因为其中的forkSystemServer启动system_server和forkAndSpecialize启动App并没有讲解,这个牵涉的东西太多了,现在功力不足以将其写清楚,所以接下来会修炼内功,在接下来的篇章中力求讲上述两个遗留的问题说透彻。如果对给位有帮助欢迎一个,如果写得有问题也欢迎多多指正。未完待续,下个篇章再见。
Android 9 Zygote进程启动源码分析指南二
前言
frameworks/base/include/android_runtime/AndroidRuntime.h frameworks/base/core/jni/AndroidRuntime.cpp frameworks/base//core/java/com/android/internal/os/ZygoteInit.java
一. 通过JNI反射启动ZygoteInit的main方法
1.1 JNI反射启动ZygoteInit的main
char* AndroidRuntime::toSlashClassName(const char* className) { char* result = strdup(className); for (char* cp = result; *cp != ' '; cp++) { if (*cp == '.') { *cp = '/'; } } return result; } void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote) { ...... /* * 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;//申明一些jni变量,没有什么好说的 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. */ /* *将字符中的.转换为/,我们前面传递过来的字符串是com.android.internal.os.ZygoteInit, *通过这里转换为com/android/internal/os/ZygoteInit,不要问我为啥要这样这个是JNI的规范 */ char* slashClassName = toSlashClassName(className != NULL ? className : ""); jclass startClass = env->FindClass(slashClassName); if (startClass == NULL) { ALOGE("JavaVM unable to locate class '%s'n", slashClassName); /* keep going */ } else { 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);//调用main方法 #if 0 if (env->ExceptionCheck()) threadExitUncaughtException(env); #endif } } free(slashClassName); ALOGD("Shutting down VMn"); if (mJavaVM->DetachCurrentThread() != JNI_OK)//退出当前线程 ALOGW("Warning: unable to detach main threadn"); if (mJavaVM->DestroyJavaVM() != 0)//等待所有线程结束关闭虚拟机 ALOGW("Warning: VM did not shut down cleanlyn"); ...... }
二. 登陆Java世界
2.1 ZygoteInit.main
private static final String SOCKET_NAME_ARG = "--socket-name="; public static void main(String argv[]) { .... String socketName = "zygote"; String abiList = null; boolean enableLazyPreload = false; for (int i = 1; i < argv.length; i++) {//解析参数 if ("start-system-server".equals(argv[i])) { startSystemServer = true; } else if ("--enable-lazy-preload".equals(argv[i])) { enableLazyPreload = 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."); } zygoteServer.registerServerSocketFromEnv(socketName);//注册zygote进程和AMS交互的通道 ...... preload(bootTimingsTraceLog);//预加载类和资源 gcAndFinalize();//GC操作 if (startSystemServer) { Runnable r = forkSystemServer(abiList, socketName, zygoteServer);//启动system_server // {@code r == null} in the parent (zygote) process, and {@code r != null} in the // child (system_server) process. if (r != null) { r.run(); return; } } Log.i(TAG, "Accepting command socket connections"); // The select loop returns early in the child process after a fork and // loops forever in the zygote. caller = zygoteServer.runSelectLoop(abiList);//进入循环模式 ...... }
2.2 zygoteServer.registerServerSocketFromEnv
/** * Registers a server socket for zygote command connections. This locates the server socket * file descriptor through an ANDROID_SOCKET_ environment variable. * * @throws RuntimeException when open fails */ void registerServerSocketFromEnv(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) { throw new RuntimeException(fullSocketName + " unset or invalid", ex); } try { FileDescriptor fd = new FileDescriptor(); fd.setInt$(fileDesc);//设置文件描述符 mServerSocket = new LocalServerSocket(fd);//创建socket本地服务端 mCloseSocketFd = true; } catch (IOException ex) { throw new RuntimeException( "Error binding to local socket '" + fileDesc + "'", ex); } } }
//定义在frameworks/base/core/java/android/os/Process.java public static final ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] zygoteArgs) { return zygoteProcess.start(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, zygoteArgs); } //定义在frameworks/base/core/java/android/os/ZygoteProcess.java public final Process.ProcessStartResult start(final String processClass, final String niceName, int uid, int gid, int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, String[] zygoteArgs) { try { return startViaZygote(processClass, niceName, uid, gid, gids, runtimeFlags, mountExternal, targetSdkVersion, seInfo, abi, instructionSet, appDataDir, invokeWith, false /* startChildZygote */, 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 Process.ProcessStartResult startViaZygote(final String processClass, final String niceName, final int uid, final int gid, final int[] gids, int runtimeFlags, int mountExternal, int targetSdkVersion, String seInfo, String abi, String instructionSet, String appDataDir, String invokeWith, boolean startChildZygote, String[] extraArgs) throws ZygoteStartFailedEx { ...... synchronized(mLock) { return zygoteSendArgsAndGetResult(openZygoteSocketIfNeeded(abi), argsForZygote); } ...... } private ZygoteState openZygoteSocketIfNeeded(String abi) throws ZygoteStartFailedEx { Preconditions.checkState(Thread.holdsLock(mLock), "ZygoteProcess lock not held"); if (primaryZygoteState == null || primaryZygoteState.isClosed()) { try { primaryZygoteState = ZygoteState.connect(mSocket); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to primary zygote", ioe); } maybeSetApiBlacklistExemptions(primaryZygoteState, false); maybeSetHiddenApiAccessLogSampleRate(primaryZygoteState); } if (primaryZygoteState.matches(abi)) { return primaryZygoteState; } // The primary zygote didn't match. Try the secondary. if (secondaryZygoteState == null || secondaryZygoteState.isClosed()) { try { secondaryZygoteState = ZygoteState.connect(mSecondarySocket); } catch (IOException ioe) { throw new ZygoteStartFailedEx("Error connecting to secondary zygote", ioe); } maybeSetApiBlacklistExemptions(secondaryZygoteState, false); maybeSetHiddenApiAccessLogSampleRate(secondaryZygoteState); } if (secondaryZygoteState.matches(abi)) { return secondaryZygoteState; } throw new ZygoteStartFailedEx("Unsupported zygote ABI: " + abi); }
2.3 preload预加载
//预加载位于/system/etc/preloaded-classes文件中的类 preloadClasses(); //预加载资源,包含drawable和color资源 preloadResources(); //预加载OpenGL preloadOpenGL(); //通过System.loadLibrary()方法, //预加载"android","compiler_rt","jnigraphics"这3个共享库 preloadSharedLibraries(); //预加载 文本连接符资源 preloadTextResources(); //仅用于zygote进程,用于内存共享的进程 WebViewFactory.prepareWebViewInZygote();
[Landroid.accounts.Account; [Landroid.animation.Animator; [Landroid.animation.Keyframe$FloatKeyframe; [Landroid.animation.Keyframe$IntKeyframe; [Landroid.animation.Keyframe$ObjectKeyframe; [Landroid.animation.Keyframe; [Landroid.animation.PropertyValuesHolder; [Landroid.app.LoaderManagerImpl; [Landroid.content.ContentProviderResult; [Landroid.content.ContentValues; [Landroid.content.Intent; [Landroid.content.UndoOwner; [Landroid.content.pm.ActivityInfo; [Landroid.content.pm.ConfigurationInfo; [Landroid.content.pm.FeatureGroupInfo; [Landroid.content.pm.FeatureInfo; [Landroid.content.pm.InstrumentationInfo; [Landroid.content.pm.PathPermission;
06-04 15:39:01.041 2901 2901 D Zygote : begin preload 06-04 15:39:01.041 2901 2901 I Zygote : Installing ICU cache reference pinning... 06-04 15:39:01.041 2901 2901 I Zygote : Preloading ICU data... 06-04 15:39:01.061 2901 2901 I Zygote : Preloading classes... 06-04 15:39:01.065 2901 2901 W Zygote : Class not found for preloading: [Landroid.view.Display$ColorTransform; 06-04 15:39:01.150 2901 2901 E Typeface: Error mapping font file /system/fonts/DroidSansFallback.ttf 06-04 15:39:01.291 2901 2901 I art : Thread[1,tid=2901,Native,Thread*=0x7f77696a00,peer=0x12c060d0,"main"] recursive attempt to load library "/system/lib64/libmedia_jni.so" 06-04 15:39:01.291 2901 2901 D MtpDeviceJNI: register_android_mtp_MtpDevice 06-04 15:39:01.292 2901 2901 I art : Thread[1,tid=2901,Native,Thread*=0x7f77696a00,peer=0x12c060d0,"main"] recursive attempt to load library "/system/lib64/libmedia_jni.so" 06-04 15:39:01.292 2901 2901 I art : Thread[1,tid=2901,Native,Thread*=0x7f77696a00,peer=0x12c060d0,"main"] recursive attempt to load library "/system/lib64/libmedia_jni.so" 06-04 15:39:01.316 2901 2901 D : Environment::getOverlayDir() = /system/vendor/Default/system/vendor/overlay 06-04 15:39:01.352 2901 2901 W Zygote : Class not found for preloading: android.view.Display$ColorTransform 06-04 15:39:01.352 2901 2901 W Zygote : Class not found for preloading: android.view.Display$ColorTransform$1 06-04 15:39:01.449 2901 2901 I System : Loaded time zone names for "" in 32ms (30ms in ICU) 06-04 15:39:01.469 2901 2901 I System : Loaded time zone names for "en_US" in 19ms (16ms in ICU) 06-04 15:39:01.491 2901 2901 I System : Loaded time zone names for "zh_CN" in 22ms (20ms in ICU) 06-04 15:39:01.518 2901 2901 I Zygote : ...preloaded 4158 classes in 457ms. 06-04 15:39:01.518 2901 2901 I art : VMRuntime.preloadDexCaches starting 06-04 15:39:01.572 1374 1419 E slim_daemon: [NDK] bindNDKSensors: Sensor server is unavailable. 06-04 15:39:01.664 2901 2901 I art : VMRuntime.preloadDexCaches strings total=292199 before=40345 after=40345 06-04 15:39:01.665 2901 2901 I art : VMRuntime.preloadDexCaches types total=24111 before=8040 after=8075 06-04 15:39:01.665 2901 2901 I art : VMRuntime.preloadDexCaches fields total=115222 before=41429 after=41660 06-04 15:39:01.665 2901 2901 I art : VMRuntime.preloadDexCaches methods total=201879 before=83038 after=83782 06-04 15:39:01.665 2901 2901 I art : VMRuntime.preloadDexCaches finished 06-04 15:39:01.666 2901 2901 I Zygote : Preloading resources... 06-04 15:39:01.682 2901 2901 W Resources: Preloaded drawable resource #0x108025d (android:drawable/dialog_background_material) that varies with configuration!! 06-04 15:39:01.683 2901 2901 W Resources: Preloaded drawable resource #0x1080299 (android:drawable/editbox_dropdown_background_dark) that varies with configuration!! 06-04 15:39:01.686 2901 2901 W Resources: Preloaded color resource #0x10600e2 (android:color/material_grey_800) that varies with configuration!! 06-04 15:39:01.686 2901 2901 W Resources: Preloaded drawable resource #0x10802ca (android:drawable/floating_popup_background_dark) that varies with configuration!! 06-04 15:39:01.694 2901 2901 W Resources: Preloaded drawable resource #0x108030c (android:drawable/ic_clear_disabled) that varies with configuration!! 06-04 15:39:01.694 2901 2901 W Resources: Preloaded drawable resource #0x1080311 (android:drawable/ic_clear_normal) that varies with configuration!! 06-04 15:39:01.698 2901 2901 W Resources: Preloaded drawable resource #0x108035a (android:drawable/ic_go) that varies with configuration!! 06-04 15:39:01.704 2901 2901 W Resources: Preloaded drawable resource #0x1080038 (android:drawable/ic_menu_close_clear_cancel) that varies with configuration!! 06-04 15:39:01.707 2901 2901 W Resources: Preloaded drawable resource #0x1080045 (android:drawable/ic_menu_more) that varies with configuration!! 06-04 15:39:01.714 2901 2901 W Resources: Preloaded drawable resource #0x10804f1 (android:drawable/menu_background_fill_parent_width) that varies with configuration!! 06-04 15:39:01.744 2901 2901 W Resources: Preloaded drawable resource #0x1080787 (android:drawable/text_edit_paste_window) that varies with configuration!! 06-04 15:39:01.748 2901 2901 W Resources: Preloaded drawable resource #0x1080096 (android:drawable/toast_frame) that varies with configuration!! 06-04 15:39:01.748 2901 2901 I Zygote : ...preloaded 114 resources in 82ms. 06-04 15:39:01.752 2901 2901 W Resources: Preloaded color resource #0x106010b (android:color/background_cache_hint_selector_material_dark) that varies with configuration!! 06-04 15:39:01.753 2901 2901 W Resources: Preloaded color resource #0x1060110 (android:color/btn_default_material_dark) that varies with configuration!! 06-04 15:39:01.755 2901 2901 I Zygote : ...preloaded 41 resources in 7ms. 06-04 15:39:01.757 2901 2901 D libEGL : loaded /vendor/lib64/egl/libEGL_adreno.so 06-04 15:39:01.773 2901 2901 D libEGL : loaded /vendor/lib64/egl/libGLESv1_CM_adreno.so 06-04 15:39:01.785 2901 2901 D libEGL : loaded /vendor/lib64/egl/libGLESv2_adreno.so 06-04 15:39:01.803 2901 2901 I Zygote : Preloading shared libraries... 06-04 15:39:01.815 2901 2901 I Zygote : Uninstalled ICU cache reference pinning... 06-04 15:39:01.816 2901 2901 I Zygote : Installed AndroidKeyStoreProvider in 2ms. 06-04 15:39:01.830 2901 2901 I Zygote : Warmed up JCA providers in 13ms. 06-04 15:39:01.830 2901 2901 D Zygote : end preload 06-04 15:39:01.831 2901 2901 I art : Starting a blocking GC Explicit 06-04 15:39:01.856 2901 2901 I art : Explicit concurrent mark sweep GC freed 58740(6MB) AllocSpace objects, 134(2MB) LOS objects, 71% free, 3MB/11MB, paused 152us total 24.977ms 06-04 15:39:01.858 2901 2901 I art : Starting a blocking GC Explicit 06-04 15:39:01.870 2901 2901 I art : Explicit concurrent mark sweep GC freed 4484(191KB) AllocSpace objects, 1(24KB) LOS objects, 72% free, 2MB/10MB, paused 127us total 11.445ms 06-04 15:39:01.873 2901 2908 I art : Starting a blocking GC HeapTrim 06-04 15:39:01.876 2901 2901 I art : Starting a blocking GC Background
copy-on-write即写时拷贝技术,zygote在这里使用了copy-on-write技术可以提高应用运行速度,因为该种方式对运行在内存中的进程实现了最大程度的复用,并通过库共享有效降低了内存的使用量。也就是说当新的App通过fork()创建的的时候不进行内存的复制,这是因为复制内存的开销是很大的,此时子进程只需要共享父进程的内存空间即可,因为这个时候他们没有差异。而当子进程需要需要修改共享内存信息时,此时才开始将内存信息复制到自己的内存空间中,并进行修改。感觉很高大上啊,这也就是为啥我们的App里面也能使用预加载的资源,so库等。这下大伙明白为啥我们能import com.android.internal.R.xxx的资源了吗。
2.4 forkSystemServer
private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) { long capabilities = posixCapabilitiesAsBits( OsConstants.CAP_IPC_LOCK, 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_PTRACE, OsConstants.CAP_SYS_TIME, OsConstants.CAP_SYS_TTY_CONFIG, OsConstants.CAP_WAKE_ALARM, OsConstants.CAP_BLOCK_SUSPEND ); /* Containers run without some capabilities, so drop any caps that are not available. */ StructCapUserHeader header = new StructCapUserHeader( OsConstants._LINUX_CAPABILITY_VERSION_3, 0); StructCapUserData[] data; try { data = Os.capget(header); } catch (ErrnoException ex) { throw new RuntimeException("Failed to capget()", ex); } capabilities &= ((long) data[0].effective) | (((long) data[1].effective) << 32); /* 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,1023,1024,1032,1065,3001,3002,3003,3006,3007,3009,3010", "--capabilities=" + capabilities + "," + capabilities, "--nice-name=system_server", "--runtime-args", "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT, "com.android.server.SystemServer", }; ZygoteConnection.Arguments parsedArgs = null; int pid; try { //用于解析参数,生成目标格式 parsedArgs = new ZygoteConnection.Arguments(args); ZygoteConnection.applyDebuggerSystemProperty(parsedArgs); ZygoteConnection.applyInvokeWithSystemProperty(parsedArgs); boolean profileSystemServer = SystemProperties.getBoolean( "dalvik.vm.profilesystemserver", false); if (profileSystemServer) { parsedArgs.runtimeFlags |= Zygote.PROFILE_SYSTEM_SERVER; } /* Request to fork the system server process */ //fork子进程,用于运行system_server pid = Zygote.forkSystemServer( parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.runtimeFlags, null, parsedArgs.permittedCapabilities, parsedArgs.effectiveCapabilities); } catch (IllegalArgumentException ex) { throw new RuntimeException(ex); } /* For child process */ if (pid == 0) {//进入子进程system_server if (hasSecondZygote(abiList)) { waitForSecondaryZygote(socketName); } zygoteServer.closeServerSocket(); // 完成system_server进程剩余的工作 return handleSystemServerProcess(parsedArgs); } return null; }
06-04 15:39:01.920 2901 2901 I Zygote : System server process 2910 has been created 06-04 15:39:01.923 2901 2901 I Zygote : Accepting command socket connections 06-04 15:39:01.940 2910 2910 I Zygote : Process: zygote socket opened, supported ABIS: armeabi-v7a,armeabi 06-04 15:39:01.941 2910 2910 I InstallerConnection: connecting... 06-04 15:39:01.942 771 771 I : new connection 06-04 15:39:01.945 2910 2910 I InstallerConnection: disconnecting... 06-04 15:39:01.945 771 771 E : eof 06-04 15:39:01.945 771 771 E : failed to read size 06-04 15:39:01.945 771 771 I : closing connection 06-04 15:39:01.955 2910 2910 V appproc : App process: starting thread pool. 06-04 15:39:01.959 2910 2910 I SystemServer: Entered the Android system server!
127|msm8953_64:/ # ps 1515 USER PID PPID VSIZE RSS WCHAN PC NAME system 1515 762 2384060 133700 SyS_epoll_ 0000000000 S system_server
2.5 ZygoteServer.runSelectLoop
Runnable runSelectLoop(String abiList) { ArrayList<FileDescriptor> fds = new ArrayList<FileDescriptor>(); ArrayList<ZygoteConnection> peers = new ArrayList<ZygoteConnection>(); //sServerSocket是socket通信中的服务端,即zygote进程。保存到fds[0] 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 { //处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里 Os.poll(pollFds, -1); } catch (ErrnoException ex) { throw new RuntimeException("poll failed", ex); } for (int i = pollFds.length - 1; i >= 0; --i) { //采用I/O多路复用机制,当接收到客户端发出连接请求 或者数据处理请求到来,则往下执行; // 否则进入continue,跳出本次循环。 if ((pollFds[i].revents & POLLIN) == 0) { continue; } if (i == 0) { //即fds[0],代表的是sServerSocket,则意味着有客户端连接请求; // 则创建ZygoteConnection对象,并添加到fds。 ZygoteConnection newPeer = acceptCommandPeer(abiList); peers.add(newPeer); fds.add(newPeer.getFileDesciptor()); } else { try { //i>0,则代表通过socket接收来自对端的数据,并执行相应操作 ZygoteConnection connection = peers.get(i); final Runnable command = connection.processOneCommand(this); if (mIsForkChild) { // We're in the child. We should always have a command to run at this // stage if processOneCommand hasn't called "exec". if (command == null) { throw new IllegalStateException("command == null"); } return command; } else { // We're in the server - we should never have any commands to run. if (command != null) { throw new IllegalStateException("command != null"); } // We don't know whether the remote side of the socket was closed or // not until we attempt to read from it from processOneCommand. This shows up as // a regular POLLIN event in our regular processing loop. if (connection.isClosedByPeer()) { connection.closeSocket(); peers.remove(i); fds.remove(i);//处理完则从fds中移除该文件描述符 } } } catch (Exception e) { if (!mIsForkChild) { // We're in the server so any exception here is one that has taken place // pre-fork while processing commands or reading / writing from the // control socket. Make a loud noise about any such exceptions so that // we know exactly what failed and why. Slog.e(TAG, "Exception executing zygote command: ", e); // Make sure the socket is closed so that the other end knows immediately // that something has gone wrong and doesn't time out waiting for a // response. ZygoteConnection conn = peers.remove(i); conn.closeSocket(); fds.remove(i); } else { // We're in the child so any exception caught here has happened post // fork and before we execute ActivityThread.main (or any other main() // method). Log the details of the exception and bring down the process. Log.e(TAG, "Caught post-fork exception in child process.", e); throw e; } } finally { // Reset the child flag, in the event that the child process is a child- // zygote. The flag will not be consulted this loop pass after the Runnable // is returned. mIsForkChild = false; } } } } }
2.6 ZygoteConnection.processOneCommand
Runnable processOneCommand(ZygoteServer zygoteServer) { String args[]; Arguments parsedArgs = null; FileDescriptor[] descriptors; try { //读取socket客户端发送过来的参数列表 args = readArgumentList(); descriptors = mSocket.getAncillaryFileDescriptors(); } catch (IOException ex) { ... throw new IllegalStateException("IOException on command socket", ex); } ... //将socket客户端传递过来的参数,解析成Arguments对象格式 parsedArgs = new Arguments(args); ... pid = Zygote.forkAndSpecialize(parsedArgs.uid, parsedArgs.gid, parsedArgs.gids, parsedArgs.runtimeFlags, rlimits, parsedArgs.mountExternal, parsedArgs.seInfo, parsedArgs.niceName, fdsToClose, fdsToIgnore, parsedArgs.startChildZygote, parsedArgs.instructionSet, parsedArgs.appDataDir); try { if (pid == 0) { // in child //子进程执行 zygoteServer.setForkChild(); zygoteServer.closeServerSocket(); IoUtils.closeQuietly(serverPipeFd); serverPipeFd = null; return handleChildProc(parsedArgs, descriptors, childPipeFd, parsedArgs.startChildZygote); } else { // In the parent. A pid < 0 indicates a failure and will be handled in // handleParentProc. //父进程执行 IoUtils.closeQuietly(childPipeFd); childPipeFd = null; handleParentProc(pid, descriptors, serverPipeFd); return null; } } finally { IoUtils.closeQuietly(childPipeFd); IoUtils.closeQuietly(serverPipeFd); } }
总结
细数下来,zygote进程启动主要干了如下的相关大事:
写在最后
本网页所有视频内容由 imoviebox边看边下-网页视频下载, iurlBox网页地址收藏管理器 下载并得到。
ImovieBox网页视频下载器 下载地址: ImovieBox网页视频下载器-最新版本下载
本文章由: imapbox邮箱云存储,邮箱网盘,ImageBox 图片批量下载器,网页图片批量下载专家,网页图片批量下载器,获取到文章图片,imoviebox网页视频批量下载器,下载视频内容,为您提供.
阅读和此文章类似的: 全球云计算