Zygote启动流程分析

一.zygote简介

Zygote进程是init进程启动时创建的,Zygote进程的名称并不是叫zygote,而是叫app_process,这个名称是在Android.mk中定义的,Zygote进程启动后,Linux 系统下的petri 系统会调用app_process ,将其名称换成了“zygote ”。

二.zygote怎么创建启动的

1.init进程读取init.rc文件启动zygote(app_main.cpp)

我们知道zygote进程是init进程在SecondStageMain方法中解析init.rc文件,然后通过ExecuteOneCommand死循环执行init.rc文件命令创建出来的。

先来看init.rc里面和启动zygote相关的代码:

#文件路径:system/core/rootdir/init.rc   或设备上 /system/etc/init/hw/init.rc
 
#引入子rc文件,${ro.zygote}是一个变量,取值范围zygote32、zygote64、zygote32_64、zygote64_32,会根据实际设备是32位还是64位进行选择
import /system/etc/init/hw/init.${ro.zygote}.rc
 
# Mount filesystems and start core system services.
on late-init
    # Now we can start zygote for devices with file based encryption
    #在init启动后的一个时机,触发启动zygote进程
    trigger zygote-start
 
 
on zygote-start && property:ro.crypto.state=unencrypted
    # A/B update verifier that marks a successful boot.
    exec_start update_verifier_nonencrypted
    start statsd
    start netd
    start zygote  #启动zygote进程,那么这个zygote是什么呢?
    start zygote_secondary
 
 
#还记得文件开头处的import 引入的子rc文件吗?我们以init.zygote64.rc为例:
#文件路径: system/core/rootdir/init.zygote64.rc
 
#service zygote 服务名为zygote
#对应的可执行程序路径:/system/bin/app_process64  (设备上的路径)
#-Xzygote /system/bin --zygote --start-system-server  执行app_process64时传入的参数
service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server
    class main
    priority -20
    user root  #用户角色
    group root readproc reserved_disk
    socket zygote stream 660 root system
    socket usap_pool_primary stream 660 root system
   
    #如果意外挂掉需要重启的服务
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart netd
    onrestart restart wificond
    writepid /dev/cpuset/foreground/tasks

最后会跑到app_main.cpp文件中执行main方法: 

Zygote(app_main.cpp)是在native层的,一开始就创建AppRuntime runtime,然后一个while循环给当前进程改名称,最后执行runtime.start("com.android.internal.os.ZygoteInit", args, zygote)后,进入AndroidRuntime.cpp里面,也就是一开始创建的AppRuntime。


//文件路径:framesworks/base/cmds/app_process/app_main.cpp
 
//argv :-Xzygote /system/bin --zygote --start-system-server
int main(int argc, char* const argv[])
{
    //创建了android运行时环境
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
 
    //根据传入的参数设置变量值
    bool zygote = false;
    bool startSystemServer = false;
    bool application = false;
    String8 niceName;
    String8 className;
 
    while (i < argc) {
        const char* arg = argv[i++];
        if (strcmp(arg, "--zygote") == 0) { //传入参数中有--zygote,所以zygote = true
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) { //同理startSystemServer = true
            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 args;
    if (!className.isEmpty()) {
       ...
    }else {
        // We're in zygote mode.
        maybeCreateDalvikCache();
 
        if (startSystemServer) { //上面已经赋值为true
            // args中又添加了这个参数
            args.add(String8("start-system-server"));
        }
 
        ...
 
        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }
    ...
    //启动zygote的java层调用,从native层转到到java层
    if (zygote) {
		//启动运行时环境,这里就是有native转到到java层的入口,这也是为什么说zygote是java层进程的鼻祖
        //zygote 为true 表示正在启动的进程为zygote进程
        //由此可知app_main.cpp在zygote启动其他进程的时候都会通过main()方法
        //这里启动的是zygote进程调用runtime start()方法 传入参数
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (className) { 
        //而这个分支是启动app相关的流程,可以先有个印象后续分析到应用的启动流程可能还会看到这里
        // 将上面的args参数数组传入
        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.");
    }
}

2.AndroidRuntime.cpp的start方法

AndroidRuntime.cpp的start代码如下:

//文件路径: frameworks/base/core/jni/AndroidRuntime.cpp
void AndroidRuntime::start(const char* className, const Vector& options, bool zygote)
{
   
    bool primary_zygote = false;
 
    /*
     * 'startSystemServer == true' means runtime is obsolete and not run from
     * init.rc anymore, so we print out the boot start event here.
     */
    //根据options参数判断是否是第一次启动zygote
    for (size_t i = 0; i < options.size(); ++i) {
        if (options[i] == startSystemServer) {
            primary_zygote = true;
           /* 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目录环境变量
    const char* rootDir = getenv("ANDROID_ROOT");
    if (rootDir == NULL) {
        rootDir = "/system";
        if (!hasDir("/system")) {
            LOG_FATAL("No root directory specified, and /system does not exist.");
            return;
        }
        setenv("ANDROID_ROOT", rootDir, 1);
    }
 
 
    JNIEnv* env;
    //创建虚拟机,这边设置了虚拟机的一些参数(可在这边虚拟机调优)然后启用虚拟机 
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {  
        return;
    }
    //注册JNI方法,系统api中涉及的jni方法都是在这里注册的
    //注册android SDK需要使用的JNI方法
     if (startReg(env) < 0) {  
        ALOGE("Unable to register all android natives\n");
        return;
    }
 
 
    //放射调用ZygoteInit.java 的main()方法
    //这里的className 是app_main.cpp的main()方法里面 
    //执行runtime.start("com.android.internal.os.ZygoteInit", args, zygote)
    //传入的com.android.internal.os.ZygoteInit
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    //找到com.android.internal.os.ZygoteInit类
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
    
    }else {
        //找到com.android.internal.os.ZygoteInit类的main方法
        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 {
            // 进入zygoteInit.main,将zygoteinit带入java世界
            //反射执行ZygoteInit.java 的main()方法,由此过渡到java层
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
    }
}

首先创建虚拟机,注册android SDK需要使用的JNI方法,最后通过反射调用zygoteInit.main函数,将zygoteinit带入java世界(由native过度到java层)。

       注:AndroidRuntime里面不止创建虚拟机,还会加载各类引用Core Libraries加载核心Libraries

创建虚拟机(startVm(&mJavaVM, &env, zygote, primary_zygote))

startVm代码如下:

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote)
{
    //JVM参数设置
    JavaVMInitArgs initArgs;
    char propBuf[PROPERTY_VALUE_MAX];
    char jniOptsBuf[sizeof("-Xjniopts:")-1 + PROPERTY_VALUE_MAX];
    char heapstartsizeOptsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
    char heapsizeOptsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
    char heapgrowthlimitOptsBuf[sizeof("-XX:HeapGrowthLimit=")-1 + PROPERTY_VALUE_MAX];
    char heapminfreeOptsBuf[sizeof("-XX:HeapMinFree=")-1 + PROPERTY_VALUE_MAX];
    char heapmaxfreeOptsBuf[sizeof("-XX:HeapMaxFree=")-1 + PROPERTY_VALUE_MAX];
    char usejitOptsBuf[sizeof("-Xusejit:")-1 + PROPERTY_VALUE_MAX];
    char jitpthreadpriorityOptsBuf[sizeof("-Xjitpthreadpriority:")-1 + PROPERTY_VALUE_MAX];
    char jitmaxsizeOptsBuf[sizeof("-Xjitmaxsize:")-1 + PROPERTY_VALUE_MAX];
    char jitinitialsizeOptsBuf[sizeof("-Xjitinitialsize:")-1 + PROPERTY_VALUE_MAX];
    char jitthresholdOptsBuf[sizeof("-Xjitthreshold:")-1 + PROPERTY_VALUE_MAX];
    char useJitProfilesOptsBuf[sizeof("-Xjitsaveprofilinginfo:")-1 + PROPERTY_VALUE_MAX];
    char jitprithreadweightOptBuf[sizeof("-Xjitprithreadweight:")-1 + PROPERTY_VALUE_MAX];
    char jittransitionweightOptBuf[sizeof("-Xjittransitionweight:")-1 + PROPERTY_VALUE_MAX];
    char hotstartupsamplesOptsBuf[sizeof("-Xps-hot-startup-method-samples:")-1 + PROPERTY_VALUE_MAX];
    char saveResolvedClassesDelayMsOptsBuf[
            sizeof("-Xps-save-resolved-classes-delay-ms:")-1 + PROPERTY_VALUE_MAX];
    char madviseRandomOptsBuf[sizeof("-XX:MadviseRandomAccess:")-1 + PROPERTY_VALUE_MAX];
    char gctypeOptsBuf[sizeof("-Xgc:")-1 + PROPERTY_VALUE_MAX];
    char backgroundgcOptsBuf[sizeof("-XX:BackgroundGC=")-1 + PROPERTY_VALUE_MAX];
    char heaptargetutilizationOptsBuf[sizeof("-XX:HeapTargetUtilization=")-1 + PROPERTY_VALUE_MAX];
    char foregroundHeapGrowthMultiplierOptsBuf[
            sizeof("-XX:ForegroundHeapGrowthMultiplier=")-1 + PROPERTY_VALUE_MAX];
    char finalizerTimeoutMsOptsBuf[sizeof("-XX:FinalizerTimeoutMs=")-1 + PROPERTY_VALUE_MAX];
    char threadSuspendTimeoutOptsBuf[sizeof("-XX:ThreadSuspendTimeout=")-1 + PROPERTY_VALUE_MAX];
    char cachePruneBuf[sizeof("-Xzygote-max-boot-retry=")-1 + PROPERTY_VALUE_MAX];
    char dex2oatXmsImageFlagsBuf[sizeof("-Xms")-1 + PROPERTY_VALUE_MAX];
    char dex2oatXmxImageFlagsBuf[sizeof("-Xmx")-1 + PROPERTY_VALUE_MAX];
    char dex2oatCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
    char dex2oatImageCompilerFilterBuf[sizeof("--compiler-filter=")-1 + PROPERTY_VALUE_MAX];
    char dex2oatThreadsBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];
    char dex2oatThreadsImageBuf[sizeof("-j")-1 + PROPERTY_VALUE_MAX];
    char dex2oatCpuSetBuf[sizeof("--cpu-set=")-1 + PROPERTY_VALUE_MAX];
    char dex2oatCpuSetImageBuf[sizeof("--cpu-set=")-1 + PROPERTY_VALUE_MAX];
    char dex2oat_isa_variant_key[PROPERTY_KEY_MAX];
    char dex2oat_isa_variant[sizeof("--instruction-set-variant=") -1 + PROPERTY_VALUE_MAX];
    char dex2oat_isa_features_key[PROPERTY_KEY_MAX];
    char dex2oat_isa_features[sizeof("--instruction-set-features=") -1 + PROPERTY_VALUE_MAX];
    char dex2oatFlagsBuf[PROPERTY_VALUE_MAX];
    char dex2oatImageFlagsBuf[PROPERTY_VALUE_MAX];
    char extraOptsBuf[PROPERTY_VALUE_MAX];
    char voldDecryptBuf[PROPERTY_VALUE_MAX];
    char perfettoHprofOptBuf[sizeof("-XX:PerfettoHprof=") + PROPERTY_VALUE_MAX];
    enum {
      kEMDefault,
      kEMIntPortable,
      kEMIntFast,
      kEMJitCompiler,
    } executionMode = kEMDefault;
    char localeOption[sizeof("-Duser.locale=") + PROPERTY_VALUE_MAX];
    char lockProfThresholdBuf[sizeof("-Xlockprofthreshold:")-1 + PROPERTY_VALUE_MAX];
    char nativeBridgeLibrary[sizeof("-XX:NativeBridge=") + PROPERTY_VALUE_MAX];
    char cpuAbiListBuf[sizeof("--cpu-abilist=") + PROPERTY_VALUE_MAX];
    char corePlatformApiPolicyBuf[sizeof("-Xcore-platform-api-policy:") + PROPERTY_VALUE_MAX];
    char methodTraceFileBuf[sizeof("-Xmethod-trace-file:") + PROPERTY_VALUE_MAX];
    char methodTraceFileSizeBuf[sizeof("-Xmethod-trace-file-size:") + PROPERTY_VALUE_MAX];
    std::string fingerprintBuf;
    char jdwpProviderBuf[sizeof("-XjdwpProvider:") - 1 + PROPERTY_VALUE_MAX];
    char opaqueJniIds[sizeof("-Xopaque-jni-ids:") - 1 + PROPERTY_VALUE_MAX];
    char bootImageBuf[sizeof("-Ximage:") - 1 + PROPERTY_VALUE_MAX];

     ........

    /*
     * 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.
     */
    //创建JVM
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
    }

    return 0;
}

可以看到startVm方法一开始对JVM的参数进行了各种设置,最后在JNI_CreateJavaVM方法中创建JVM。

            注:JVM最大的作用就是进行内存管理

注册JNI(startReg(env))

JNI是Java层调用C/C++的中间层,比如说java层调用函数a,会通过JNI去找一个映射关系,最后调用到C/C++层的函数b。JNI的函数注册可以分为静态注册与动态注册。

可以看到这这个方法中调用register_jni_procs(gRegJNI, NELEM(gRegJNI), env)动态注册了一些java层调用native层的jni函数。

/*
 * Register android native functions with the VM.
 */
/*static*/ int AndroidRuntime::startReg(JNIEnv* env)
{
    ATRACE_NAME("RegisterAndroidNatives");
    /*
     * This hook causes all future threads created in this process to be
     * attached to the JavaVM.  (This needs to go away in favor of JNI
     * Attach calls.)
     */
    androidSetCreateThreadFunc((android_create_thread_fn) javaCreateThreadEtc);

    ALOGV("--- registering native functions ---\n");

    /*
     * 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);

    // gRegJNI,动态注册的java调用native的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 const RegJNIRec gRegJNI[] = {
        REG_JNI(register_com_android_internal_os_RuntimeInit),
        REG_JNI(register_com_android_internal_os_ZygoteInit_nativeZygoteInit),
        REG_JNI(register_android_os_SystemClock),
        REG_JNI(register_android_util_EventLog),
        REG_JNI(register_android_util_Log),
        REG_JNI(register_android_util_MemoryIntArray),
        REG_JNI(register_android_app_admin_SecurityLog),
        REG_JNI(register_android_content_AssetManager),
        REG_JNI(register_android_content_StringBlock),
        REG_JNI(register_android_content_XmlBlock),
        REG_JNI(register_android_content_res_ApkAssets),
        REG_JNI(register_android_text_AndroidCharacter),
        REG_JNI(register_android_text_Hyphenator),
        REG_JNI(register_android_view_InputDevice),
        REG_JNI(register_android_view_KeyCharacterMap),
        REG_JNI(register_android_os_Process),
        REG_JNI(register_android_os_SystemProperties),
        REG_JNI(register_android_os_Binder),
        REG_JNI(register_android_os_Parcel),
        REG_JNI(register_android_os_HidlMemory),
        REG_JNI(register_android_os_HidlSupport),
        REG_JNI(register_android_os_HwBinder),
        REG_JNI(register_android_os_HwBlob),
        REG_JNI(register_android_os_HwParcel),
        REG_JNI(register_android_os_HwRemoteBinder),
        REG_JNI(register_android_os_NativeHandle),
        REG_JNI(register_android_os_ServiceManager),
        REG_JNI(register_android_os_storage_StorageManager),
        REG_JNI(register_android_os_VintfObject),
        REG_JNI(register_android_os_VintfRuntimeInfo),
        REG_JNI(register_android_service_DataLoaderService),
        REG_JNI(register_android_view_DisplayEventReceiver),
        REG_JNI(register_android_view_InputApplicationHandle),
        REG_JNI(register_android_view_InputWindowHandle),
        REG_JNI(register_android_view_Surface),
        REG_JNI(register_android_view_SurfaceControl),
        REG_JNI(register_android_view_SurfaceSession),
        REG_JNI(register_android_view_CompositionSamplingListener),
        REG_JNI(register_android_view_TextureView),
        REG_JNI(register_com_google_android_gles_jni_EGLImpl),
        REG_JNI(register_com_google_android_gles_jni_GLImpl),
        REG_JNI(register_android_opengl_jni_EGL14),
        REG_JNI(register_android_opengl_jni_EGL15),
        REG_JNI(register_android_opengl_jni_EGLExt),
        REG_JNI(register_android_opengl_jni_GLES10),
        REG_JNI(register_android_opengl_jni_GLES10Ext),
        REG_JNI(register_android_opengl_jni_GLES11),
        REG_JNI(register_android_opengl_jni_GLES11Ext),
        REG_JNI(register_android_opengl_jni_GLES20),
        REG_JNI(register_android_opengl_jni_GLES30),
        REG_JNI(register_android_opengl_jni_GLES31),
        REG_JNI(register_android_opengl_jni_GLES31Ext),
        REG_JNI(register_android_opengl_jni_GLES32),
        REG_JNI(register_android_graphics_classes),
        REG_JNI(register_android_graphics_BLASTBufferQueue),
        REG_JNI(register_android_graphics_GraphicBuffer),
        REG_JNI(register_android_graphics_SurfaceTexture),
        REG_JNI(register_android_database_CursorWindow),
        REG_JNI(register_android_database_SQLiteConnection),
        REG_JNI(register_android_database_SQLiteGlobal),
        REG_JNI(register_android_database_SQLiteDebug),
        REG_JNI(register_android_os_Debug),
        REG_JNI(register_android_os_FileObserver),
        REG_JNI(register_android_os_GraphicsEnvironment),
        REG_JNI(register_android_os_MessageQueue),
        REG_JNI(register_android_os_SELinux),
        REG_JNI(register_android_os_Trace),
        REG_JNI(register_android_os_UEventObserver),
        REG_JNI(register_android_net_LocalSocketImpl),
        REG_JNI(register_android_net_NetworkUtils),
        REG_JNI(register_android_os_MemoryFile),
        REG_JNI(register_android_os_SharedMemory),
        REG_JNI(register_android_os_incremental_IncrementalManager),
        REG_JNI(register_com_android_internal_content_om_OverlayConfig),
        REG_JNI(register_com_android_internal_os_ClassLoaderFactory),
        REG_JNI(register_com_android_internal_os_Zygote),
        REG_JNI(register_com_android_internal_os_ZygoteInit),
        REG_JNI(register_com_android_internal_util_VirtualRefBasePtr),
        REG_JNI(register_android_hardware_Camera),
        REG_JNI(register_android_hardware_camera2_CameraMetadata),
        REG_JNI(register_android_hardware_camera2_legacy_LegacyCameraDevice),
        REG_JNI(register_android_hardware_camera2_legacy_PerfMeasurement),
        REG_JNI(register_android_hardware_camera2_DngCreator),
        REG_JNI(register_android_hardware_display_DisplayManagerGlobal),
        REG_JNI(register_android_hardware_HardwareBuffer),
        REG_JNI(register_android_hardware_SensorManager),
        REG_JNI(register_android_hardware_SerialPort),
        REG_JNI(register_android_hardware_UsbDevice),
        REG_JNI(register_android_hardware_UsbDeviceConnection),
        REG_JNI(register_android_hardware_UsbRequest),
        REG_JNI(register_android_hardware_location_ActivityRecognitionHardware),
        REG_JNI(register_android_media_AudioDeviceAttributes),
        REG_JNI(register_android_media_AudioEffectDescriptor),
        REG_JNI(register_android_media_AudioSystem),
        REG_JNI(register_android_media_AudioRecord),
        REG_JNI(register_android_media_AudioTrack),
        REG_JNI(register_android_media_AudioAttributes),
        REG_JNI(register_android_media_AudioProductStrategies),
        REG_JNI(register_android_media_AudioVolumeGroups),
        REG_JNI(register_android_media_AudioVolumeGroupChangeHandler),
        REG_JNI(register_android_media_MediaMetrics),
        REG_JNI(register_android_media_MicrophoneInfo),
        REG_JNI(register_android_media_RemoteDisplay),
        REG_JNI(register_android_media_ToneGenerator),
        REG_JNI(register_android_media_midi),

        REG_JNI(register_android_opengl_classes),
        REG_JNI(register_android_server_NetworkManagementSocketTagger),
        REG_JNI(register_android_ddm_DdmHandleNativeHeap),
        REG_JNI(register_android_backup_BackupDataInput),
        REG_JNI(register_android_backup_BackupDataOutput),
        REG_JNI(register_android_backup_FileBackupHelperBase),
        REG_JNI(register_android_backup_BackupHelperDispatcher),
        REG_JNI(register_android_app_backup_FullBackup),
        REG_JNI(register_android_app_Activity),
        REG_JNI(register_android_app_ActivityThread),
        REG_JNI(register_android_app_NativeActivity),
        REG_JNI(register_android_util_jar_StrictJarFile),
        REG_JNI(register_android_view_InputChannel),
        REG_JNI(register_android_view_InputEventReceiver),
        REG_JNI(register_android_view_InputEventSender),
        REG_JNI(register_android_view_InputQueue),
        REG_JNI(register_android_view_KeyEvent),
        REG_JNI(register_android_view_MotionEvent),
        REG_JNI(register_android_view_PointerIcon),
        REG_JNI(register_android_view_VelocityTracker),
        REG_JNI(register_android_view_VerifiedKeyEvent),
        REG_JNI(register_android_view_VerifiedMotionEvent),

        REG_JNI(register_android_content_res_ObbScanner),
        REG_JNI(register_android_content_res_Configuration),

        REG_JNI(register_android_animation_PropertyValuesHolder),
        REG_JNI(register_android_security_Scrypt),
        REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
        REG_JNI(register_com_android_internal_os_FuseAppLoop),
        REG_JNI(register_com_android_internal_os_KernelCpuUidBpfMapReader),
        REG_JNI(register_com_android_internal_os_KernelSingleUidTimeReader),
};

反射调用zygoteInit.main函数,由native层到java层过度

代码如下:

可以看到这边通过反射调用了com.android.internal.os.ZygoteInit的main方法。

              注:C/C++调用java代码一般是通过反射调用

//放射调用ZygoteInit.java 的main()方法
    //这里的className 是app_main.cpp的main()方法里面 
    //执行runtime.start("com.android.internal.os.ZygoteInit", args, zygote)
    //传入的com.android.internal.os.ZygoteInit
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    //找到com.android.internal.os.ZygoteInit类
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
    
    }else {
        //找到com.android.internal.os.ZygoteInit类的main方法
        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 {
            // 进入zygoteInit.main,将zygoteinit带入java世界
            //反射执行ZygoteInit.java 的main()方法,由此过渡到java层
            env->CallStaticVoidMethod(startClass, startMeth, strArray);
        }
    }

3.zygoteInit

zygoteInit的main代码方法如下:

 public static void main(String argv[]) {
        ZygoteServer zygoteServer = null;

        // Mark zygote start. This ensures that thread creation will throw
        // an error.
        ZygoteHooks.startZygoteNoThreadCreation();

        // Zygote goes into its own process group.
        try {
            Os.setpgid(0, 0);
        } catch (ErrnoException ex) {
            throw new RuntimeException("Failed to setpgid(0,0)", ex);
        }

        Runnable caller;
        try {
            // Store now for StatsLogging later.
            final long startTime = SystemClock.elapsedRealtime();
            final boolean isRuntimeRestarted = "1".equals(
                    SystemProperties.get("sys.boot_completed"));

            String bootTimeTag = Process.is64Bit() ? "Zygote64Timing" : "Zygote32Timing";
            TimingsTraceLog bootTimingsTraceLog = new TimingsTraceLog(bootTimeTag,
                    Trace.TRACE_TAG_DALVIK);
            bootTimingsTraceLog.traceBegin("ZygoteInit");
            RuntimeInit.preForkInit();

            boolean startSystemServer = false;
            String zygoteSocketName = "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)) {
                    zygoteSocketName = argv[i].substring(SOCKET_NAME_ARG.length());
                } else {
                    throw new RuntimeException("Unknown command line argument: " + argv[i]);
                }
            }

            final boolean isPrimaryZygote = zygoteSocketName.equals(Zygote.PRIMARY_SOCKET_NAME);
            if (!isRuntimeRestarted) {
                if (isPrimaryZygote) {
                    FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                            BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__ZYGOTE_INIT_START,
                            startTime);
                } else if (zygoteSocketName.equals(Zygote.SECONDARY_SOCKET_NAME)) {
                    FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                            BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SECONDARY_ZYGOTE_INIT_START,
                            startTime);
                }
            }

            if (abiList == null) {
                throw new RuntimeException("No ABI list supplied.");
            }

            // In some configurations, we avoid preloading resources and classes eagerly.
            // In such cases, we will preload things prior to our first fork.
            if (!enableLazyPreload) {
                bootTimingsTraceLog.traceBegin("ZygotePreload");
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_START,
                        SystemClock.uptimeMillis());
				// step1 重要的函数 preload
                preload(bootTimingsTraceLog);
                EventLog.writeEvent(LOG_BOOT_PROGRESS_PRELOAD_END,
                        SystemClock.uptimeMillis());
                bootTimingsTraceLog.traceEnd(); // ZygotePreload
            }

            // Do an initial gc to clean up after startup
            bootTimingsTraceLog.traceBegin("PostZygoteInitGC");
            gcAndFinalize();
            bootTimingsTraceLog.traceEnd(); // PostZygoteInitGC

            bootTimingsTraceLog.traceEnd(); // ZygoteInit

            Zygote.initNativeState(isPrimaryZygote); 

            ZygoteHooks.stopZygoteNoThreadCreation();

            //Step2 重要函数 创建socket服务
            zygoteServer = new ZygoteServer(isPrimaryZygote);  

            if (startSystemServer) {
                //Zygote Fork出的第一个进程 system_server
                Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

                // {@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.
            //循环等待fork出其他的应用进程,比如Launcher,比如app
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }

        // We're in the child process and have exited the select loop. Proceed to execute the
        // command.
        if (caller != null) {
            //执行返回的Runnable对象,进入子进程
            caller.run();
        }
    }

从代码中可以看出有四个重要的步骤:加载资源---》preload(bootTimingsTraceLog),创建socket服务---》zygoteServer = new ZygoteServer(isPrimaryZygote),Zygote Fork出的第一个进程 system_server---》Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer),循环等待fork出其他的应用进程,比如Launcher,比如app---》caller = zygoteServer.runSelectLoop(abiList);

加载资源---》preload(bootTimingsTraceLog)

代码如下:

可以看到都是加载一些资源的代码。特别注意preloadClasses()方法,这个方法加载系统类。我们使用一些三方的库或者需要先implementation一下,把包编译到app里面。但是使用ImageView的时候不用implementation,原因就是在preloadClasses帮我们引入了。

static void preload(TimingsTraceLog bootTimingsTraceLog) {
        Log.d(TAG, "begin preload");
        bootTimingsTraceLog.traceBegin("BeginPreload");
        beginPreload();
        bootTimingsTraceLog.traceEnd(); // BeginPreload
        bootTimingsTraceLog.traceBegin("PreloadClasses");
        //加载系统类,帮我们引入了一些系统资源,比如说我们使用ImageView的时候不用implementation
        preloadClasses();
        bootTimingsTraceLog.traceEnd(); // PreloadClasses
        bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders");
        cacheNonBootClasspathClassLoaders();
        bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
        bootTimingsTraceLog.traceBegin("PreloadResources");
        preloadResources();// 加载系统资源
        bootTimingsTraceLog.traceEnd(); // PreloadResources
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
        nativePreloadAppProcessHALs();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadGraphicsDriver");
        maybePreloadGraphicsDriver();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        preloadSharedLibraries();// 加载一些共享so库,其实就三个:android、compiler_rt、jnigraphics
        preloadTextResources();// 加载字体资源
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes.
        WebViewFactory.prepareWebViewInZygote();// 加载webview相关资源
        endPreload();
        warmUpJcaProviders();// 初始化JCA安全相关的参数
        Log.d(TAG, "end preload");

        sPreloadComplete = true;
    }

创建socket服务---》zygoteServer = new ZygoteServer(isPrimaryZygote)

C/S模式
AMS发送socket
ZygoteServer里面都是服务器,不仅仅要接收AMS发送的socket还要接收其他的socket


Zygote Fork出的第一个进程 system_server

forkSystemServer方法代码如下:

可以看到最后是调用了handleSystemServerProcess方法。

 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 */
        //注意,这边的"com.android.server.SystemServer"最后会传递到findStaticMain方法里面, 
        //反射创建"com.android.server.SystemServer"的main方法
        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,3011",
                "--capabilities=" + capabilities + "," + capabilities,
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer",
        };
        ZygoteArguments parsedArgs = null;

        int pid;

        try {
            parsedArgs = new ZygoteArguments(args);
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);

            if (Zygote.nativeSupportsTaggedPointers()) {
                /* Enable pointer tagging in the system server. Hardware support for this is present
                 * in all ARMv8 CPUs. */
                parsedArgs.mRuntimeFlags |= Zygote.MEMORY_TAG_LEVEL_TBI;
            }

            /* Enable gwp-asan on the system server with a small probability. This is the same
             * policy as applied to native processes and system apps. */
            parsedArgs.mRuntimeFlags |= Zygote.GWP_ASAN_LEVEL_LOTTERY;

            if (shouldProfileSystemServer()) {
                parsedArgs.mRuntimeFlags |= Zygote.PROFILE_SYSTEM_SERVER;
            }

            /* Request to fork the system server process */
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }

        /* For child process */
        if (pid == 0) { 
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName);
            }

            zygoteServer.closeServerSocket();
            //parsedArgs里面存储了"com.android.server.SystemServer"类名
            return handleSystemServerProcess(parsedArgs);
        }

        return null;
    }

handleSystemServerProcess方法代码如下:

可以看到最后执行了ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl)方法。

 /**
     * Finish remaining work for the newly forked system server process.
     */
    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
             ......

            /*
             * Pass the remaining arguments to SystemServer.
             */
            //parsedArgs.mRemainingArgs是"com.android.server.SystemServer"
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }

        /* should never reach here */
    }

ZygoteInit.zygoteInit代码如下:

可以看到最后调用RuntimeInit.applicationInit方法。

public static final Runnable zygoteInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        if (RuntimeInit.DEBUG) {
            Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
        }

        Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "ZygoteInit");
        RuntimeInit.redirectLogStreams();

        RuntimeInit.commonInit();//初始化运行环境 
        ZygoteInit.nativeZygoteInit();//启动Binder ,方法在 androidRuntime.cpp中注册
        // 通过反射创建程序入口函数的 Method 对象,并返回 Runnable 对象
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

RuntimeInit.applicationInit代码如下:

可以看到最后执行了findStaticMain方法。

 protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        // If the application calls System.exit(), terminate the process
        // immediately without running any shutdown hooks.  It is not possible to
        // shutdown an Android application gracefully.  Among other things, the
        // Android runtime shutdown hooks close the Binder driver, which can cause
        // leftover running threads to crash before the process actually exits.
        nativeSetExitWithoutCleanup(true);

        VMRuntime.getRuntime().setTargetSdkVersion(targetSdkVersion);
        VMRuntime.getRuntime().setDisabledCompatChanges(disabledCompatChanges);

        final Arguments args = new Arguments(argv);

        // The end of of the RuntimeInit event (see #zygoteInit).
        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);

        // Remaining arguments are passed to the start class's static main
        // startClass: 如果AMS通过socket传递过来的是 ActivityThread
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

 findStaticMain代码如下:

protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class cl;

        try {
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException(
                    "Missing class when invoking static main " + className,
                    ex);
        }

        Method m;
        try {
            // 通过反射拿到对应类的main方法的Method对象
            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);
        }

        /*
         * This throw gets caught in ZygoteInit.main(), which responds
         * by invoking the exception's run() method. This arrangement
         * clears up all the stack frames that were required in setting
         * up the process.
         */
        return new MethodAndArgsCaller(m, argv);
    }

通过这几个一系列的函数调用,我们可以看到在forkSystemServer方法中定义了"com.android.server.SystemServer"类名,最后传递到findStaticMain方法中通过反射创建了SystemServer得main方法。

同理我们可以知道app需要跑起来,会反射调用ActivityThread的main方法。

循环等待fork出其他的应用进程,比如Launcher,比如app---》caller = zygoteServer.runSelectLoop(abiList);

runSelectLoop代码如下:

 Runnable runSelectLoop(String abiList) {
        ArrayList socketFDs = new ArrayList<>();
        ArrayList peers = new ArrayList<>();

        //mZygoteSocket 是socket通信中的服务端,即zygote进程。保存到socketFDs[0]
        socketFDs.add(mZygoteSocket.getFileDescriptor());
        peers.add(null);

        mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;

        while (true) {
            fetchUsapPoolPolicyPropsWithMinInterval();
            mUsapPoolRefillAction = UsapPoolRefillAction.NONE;

            int[] usapPipeFDs = null;
            //每次循环,都重新创建需要监听的pollFds
            StructPollfd[] pollFDs;

            // Allocate enough space for the poll structs, taking into account
            // the state of the USAP pool for this Zygote (could be a
            // regular Zygote, a WebView Zygote, or an AppZygote).
            if (mUsapPoolEnabled) {
                usapPipeFDs = Zygote.getUsapPipeFDs();
                pollFDs = new StructPollfd[socketFDs.size() + 1 + usapPipeFDs.length];
            } else {
                pollFDs = new StructPollfd[socketFDs.size()];
            }

            /*
             * For reasons of correctness the USAP pool pipe and event FDs
             * must be processed before the session and server sockets.  This
             * is to ensure that the USAP pool accounting information is
             * accurate when handling other requests like API blacklist
             * exemptions.
             */

            int pollIndex = 0;
            for (FileDescriptor socketFD : socketFDs) {
                pollFDs[pollIndex] = new StructPollfd();
                pollFDs[pollIndex].fd = socketFD;
                //关注事件的到来
                pollFDs[pollIndex].events = (short) POLLIN;
                ++pollIndex;
            }

            final int usapPoolEventFDIndex = pollIndex;

            if (mUsapPoolEnabled) {
                pollFDs[pollIndex] = new StructPollfd();
                pollFDs[pollIndex].fd = mUsapPoolEventFD;
                pollFDs[pollIndex].events = (short) POLLIN;
                ++pollIndex;

                // The usapPipeFDs array will always be filled in if the USAP Pool is enabled.
                assert usapPipeFDs != null;
                for (int usapPipeFD : usapPipeFDs) {
                    FileDescriptor managedFd = new FileDescriptor();
                    managedFd.setInt$(usapPipeFD);

                    pollFDs[pollIndex] = new StructPollfd();
                    pollFDs[pollIndex].fd = managedFd;
                    pollFDs[pollIndex].events = (short) POLLIN;
                    ++pollIndex;
                }
            }

            int pollTimeoutMs;

            if (mUsapPoolRefillTriggerTimestamp == INVALID_TIMESTAMP) {
                pollTimeoutMs = -1;
            } else {
                long elapsedTimeMs = System.currentTimeMillis() - mUsapPoolRefillTriggerTimestamp;

                if (elapsedTimeMs >= mUsapPoolRefillDelayMs) {
                    // Normalize the poll timeout value when the time between one poll event and the
                    // next pushes us over the delay value.  This prevents poll receiving a 0
                    // timeout value, which would result in it returning immediately.
                    pollTimeoutMs = -1;

                } else if (elapsedTimeMs <= 0) {
                    // This can occur if the clock used by currentTimeMillis is reset, which is
                    // possible because it is not guaranteed to be monotonic.  Because we can't tell
                    // how far back the clock was set the best way to recover is to simply re-start
                    // the respawn delay countdown.
                    pollTimeoutMs = mUsapPoolRefillDelayMs;

                } else {
                    pollTimeoutMs = (int) (mUsapPoolRefillDelayMs - elapsedTimeMs);
                }
            }

            int pollReturnValue;
            try {
                //处理轮询状态,当pollFds有事件到来则往下执行,否则阻塞在这里
                pollReturnValue = Os.poll(pollFDs, pollTimeoutMs);
            } catch (ErrnoException ex) {
                throw new RuntimeException("poll failed", ex);
            }

            if (pollReturnValue == 0) {
                // The poll timeout has been exceeded.  This only occurs when we have finished the
                // USAP pool refill delay period.

                mUsapPoolRefillTriggerTimestamp = INVALID_TIMESTAMP;
                mUsapPoolRefillAction = UsapPoolRefillAction.DELAYED;

            } else {
                boolean usapPoolFDRead = false;

                /*注意这里是倒序处理的,网上有的博客说是优先处理已建立连接的信息,后处理新建连接的请求
                * 我觉得这个表述不是很正确,我觉得采用倒序是为了先处理已经建立连接的请求,
                *但是这个优先反而是后面建立连接的请求有数据到来是优先处理了
                * 然后接着最后处理 mZygoteSocket,此时即有新的客户端要求建立连接
                */
                while (--pollIndex >= 0) {
                    // 采用I/O多路复用机制,当接收到客户端发出连接请求 或者数据处理请求到来,则往下执行;
                    // 否则进入continue,跳出本次循环。
                    if ((pollFDs[pollIndex].revents & POLLIN) == 0) {
                        continue;
                    }

                    if (pollIndex == 0) {
                        // Zygote server socket
                        // 即socketFDs[0],代表的是 mZygoteSocket 因为它最先加入,则意味着有客户端连接请求;
                        // 则创建ZygoteConnection对象,并添加到socketFDs。
                        ZygoteConnection newPeer = acceptCommandPeer(abiList);
                        //  加入到peers和socketFDs,下一次也开始监听
                        peers.add(newPeer);
                        socketFDs.add(newPeer.getFileDescriptor());

                    } else if (pollIndex < usapPoolEventFDIndex) {
                        // Session socket accepted from the Zygote server socket

                        try {
                            //pollIndex>0,则代表通过socket接收来自对端的数据,并执行相应操作
                            ZygoteConnection connection = peers.get(pollIndex);
							
							///重要细节///
							
                            //  进行进程的处理:创建进程
                            final Runnable command = connection.processOneCommand(this);

                            // TODO (chriswailes): Is this extra check necessary?
                            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(pollIndex);
                                    socketFDs.remove(pollIndex);//处理完则从socketFDs中移除该文件描述符
									
                                }
                            }
                        } 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(pollIndex);
                                conn.closeSocket();

                                socketFDs.remove(pollIndex);
                            } 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;
                        }

                    } else {
                        // Either the USAP pool event FD or a USAP reporting pipe.

                        // If this is the event FD the payload will be the number of USAPs removed.
                        // If this is a reporting pipe FD the payload will be the PID of the USAP
                        // that was just specialized.  The `continue` statements below ensure that
                        // the messagePayload will always be valid if we complete the try block
                        // without an exception.
                        long messagePayload;

                        try {
                            byte[] buffer = new byte[Zygote.USAP_MANAGEMENT_MESSAGE_BYTES];
                            int readBytes =
                                    Os.read(pollFDs[pollIndex].fd, buffer, 0, buffer.length);

                            if (readBytes == Zygote.USAP_MANAGEMENT_MESSAGE_BYTES) {
                                DataInputStream inputStream =
                                        new DataInputStream(new ByteArrayInputStream(buffer));

                                messagePayload = inputStream.readLong();
                            } else {
                                Log.e(TAG, "Incomplete read from USAP management FD of size "
                                        + readBytes);
                                continue;
                            }
                        } catch (Exception ex) {
                            if (pollIndex == usapPoolEventFDIndex) {
                                Log.e(TAG, "Failed to read from USAP pool event FD: "
                                        + ex.getMessage());
                            } else {
                                Log.e(TAG, "Failed to read from USAP reporting pipe: "
                                        + ex.getMessage());
                            }

                            continue;
                        }

                        if (pollIndex > usapPoolEventFDIndex) {
                            Zygote.removeUsapTableEntry((int) messagePayload);
                        }

                        usapPoolFDRead = true;
                    }
                }

                if (usapPoolFDRead) {
                    int usapPoolCount = Zygote.getUsapPoolCount();

                    if (usapPoolCount < mUsapPoolSizeMin) {
                        // Immediate refill
                        mUsapPoolRefillAction = UsapPoolRefillAction.IMMEDIATE;
                    } else if (mUsapPoolSizeMax - usapPoolCount >= mUsapPoolRefillThreshold) {
                        // Delayed refill
                        mUsapPoolRefillTriggerTimestamp = System.currentTimeMillis();
                    }
                }
            }

            if (mUsapPoolRefillAction != UsapPoolRefillAction.NONE) {
                int[] sessionSocketRawFDs =
                        socketFDs.subList(1, socketFDs.size())
                                .stream()
                                .mapToInt(FileDescriptor::getInt$)
                                .toArray();

                final boolean isPriorityRefill =
                        mUsapPoolRefillAction == UsapPoolRefillAction.IMMEDIATE;

                final Runnable command =
                        fillUsapPool(sessionSocketRawFDs, isPriorityRefill);

                if (command != null) {
                    return command;
                } else if (isPriorityRefill) {
                    // Schedule a delayed refill to finish refilling the pool.
                    mUsapPoolRefillTriggerTimestamp = System.currentTimeMillis();
                }
            }
        }
    }

可以看出里面是一个死循环,不断的轮询,如果socket有消息就fork进程出来。

     思考:这边的死循环是不是和init进程一样,使用了linux的epoll机制休眠。

三.system_server进程的作用

我们知道启动system_server进程是通过反射执行system_server的main函数来实现的。

SystemServer主要代码如下:

 public static void main(String[] args) {
        new SystemServer().run();
    }

    public SystemServer() {
        // Check for factory test mode.
        mFactoryTestMode = FactoryTest.getMode();

        // Record process start information.
        // Note SYSPROP_START_COUNT will increment by *2* on a FDE device when it fully boots;
        // one for the password screen, second for the actual boot.
        mStartCount = SystemProperties.getInt(SYSPROP_START_COUNT, 0) + 1;
        mRuntimeStartElapsedTime = SystemClock.elapsedRealtime();
        mRuntimeStartUptime = SystemClock.uptimeMillis();
        Process.setStartTimes(mRuntimeStartElapsedTime, mRuntimeStartUptime);

        // Remember if it's runtime restart(when sys.boot_completed is already set) or reboot
        // We don't use "mStartCount > 1" here because it'll be wrong on a FDE device.
        // TODO: mRuntimeRestart will *not* be set to true if the proccess crashes before
        // sys.boot_completed is set. Fix it.
        mRuntimeRestart = "1".equals(SystemProperties.get("sys.boot_completed"));
    }

    private void run() {
        TimingsTraceAndSlog t = new TimingsTraceAndSlog();
        try {
            t.traceBegin("InitBeforeStartServices");

            // Record the process start information in sys props.
            SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));
            SystemProperties.set(SYSPROP_START_ELAPSED, String.valueOf(mRuntimeStartElapsedTime));
            SystemProperties.set(SYSPROP_START_UPTIME, String.valueOf(mRuntimeStartUptime));

            EventLog.writeEvent(EventLogTags.SYSTEM_SERVER_START,
                    mStartCount, mRuntimeStartUptime, mRuntimeStartElapsedTime);

            //
            // Default the timezone property to GMT if not set.
            //
            String timezoneProperty = SystemProperties.get("persist.sys.timezone");
            if (timezoneProperty == null || timezoneProperty.isEmpty()) {
                Slog.w(TAG, "Timezone not set; setting to GMT.");
                SystemProperties.set("persist.sys.timezone", "GMT");
            }

            // 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", "");
            }

            // The system server should never make non-oneway calls
            Binder.setWarnOnBlocking(true);
            // The system server should always load safe labels
            PackageItemInfo.forceSafeLabels();

            // Default to FULL within the system server.
            SQLiteGlobal.sDefaultSyncMode = SQLiteGlobal.SYNC_MODE_FULL;

            // Deactivate SQLiteCompatibilityWalFlags until settings provider is initialized
            SQLiteCompatibilityWalFlags.init(null);

            // Here we go!
            Slog.i(TAG, "Entered the Android system server!");
            final long uptimeMillis = SystemClock.elapsedRealtime();
            EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_SYSTEM_RUN, uptimeMillis);
            if (!mRuntimeRestart) {
                FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                        FrameworkStatsLog
                                .BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_INIT_START,
                        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());

            // Mmmmmm... more memory!
            VMRuntime.getRuntime().clearGrowthLimit();

            // 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);

            // Within the system server, any incoming Bundles should be defused
            // to avoid throwing BadParcelableException.
            BaseBundle.setShouldDefuse(true);

            // Within the system server, when parceling exceptions, include the stack trace
            Parcel.setStackTraceParceling(true);

            // Ensure binder calls into the system always run at foreground priority.
            BinderInternal.disableBackgroundScheduling(true);

            // Increase the number of binder threads in system_server
            BinderInternal.setMaxThreads(sMaxBinderThreads);

            // Prepare the main looper thread (this thread).
            android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            Looper.prepareMainLooper();
            Looper.getMainLooper().setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);

            SystemServiceRegistry.sEnableServiceNotFoundWtf = true;

            // Initialize native services.
            System.loadLibrary("android_servers");

            // Allow heap / perf profiling.
            initZygoteChildHeapProfiling();

            // Debug builds - spawn a thread to monitor for fd leaks.
            if (Build.IS_DEBUGGABLE) {
                spawnFdLeakCheckThread();
            }

            // Check whether we failed to shut down last time we tried.
            // This call may not return.
            performPendingShutdown();

            // Initialize the system context.
            // 创建进程的context
            createSystemContext();

            // Call per-process mainline module initialization.
            ActivityThread.initializeMainlineModules();

            // Create the system service manager.
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // Prepare the thread pool for init tasks that can be parallelized
            SystemServerInitThreadPool.start();
            // Attach JVMTI agent if this is a debuggable build and the system property is set.
            if (Build.IS_DEBUGGABLE) {
                // Property is of the form "library_path=parameters".
                String jvmtiAgent = SystemProperties.get("persist.sys.dalvik.jvmtiagent");
                if (!jvmtiAgent.isEmpty()) {
                    int equalIndex = jvmtiAgent.indexOf('=');
                    String libraryPath = jvmtiAgent.substring(0, equalIndex);
                    String parameterList =
                            jvmtiAgent.substring(equalIndex + 1, jvmtiAgent.length());
                    // Attach the agent.
                    try {
                        Debug.attachJvmtiAgent(libraryPath, parameterList, null);
                    } catch (Exception e) {
                        Slog.e("System", "*************************************************");
                        Slog.e("System", "********** Failed to load jvmti plugin: " + jvmtiAgent);
                    }
                }
            }
        } finally {
            t.traceEnd();  // InitBeforeStartServices
        }

        // Setup the default WTF handler
        RuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);

        // Start services.
        try {
            t.traceBegin("StartServices");
            startBootstrapServices(t);
            startCoreServices(t);
            startOtherServices(t);
        } catch (Throwable ex) {
            Slog.e("System", "******************************************");
            Slog.e("System", "************ Failure starting system services", ex);
            throw ex;
        } finally {
            t.traceEnd(); // StartServices
        }

        StrictMode.initVmDefaults(null);

        if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
            final long uptimeMillis = SystemClock.elapsedRealtime();
            FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                    FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__SYSTEM_SERVER_READY,
                    uptimeMillis);
            final long maxUptimeMillis = 60 * 1000;
            if (uptimeMillis > maxUptimeMillis) {
                Slog.wtf(SYSTEM_SERVER_TIMING_TAG,
                        "SystemServer init took too long. uptimeMillis=" + uptimeMillis);
            }
        }

        // Diagnostic to ensure that the system is in a base healthy state. Done here as a common
        // non-zygote process.
        if (!VMRuntime.hasBootImageSpaces()) {
            Slog.wtf(TAG, "Runtime is not running with a boot image!");
        }

        // Loop forever.
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }

整个代码流程可以使用这张图来概括一下:

Zygote启动流程分析_第1张图片

其中最重要的代码是:

           startBootstrapServices(t);
            startCoreServices(t);
            startOtherServices(t);

这三个方法创建90多个服务(AMS,WMS等),并且把这些服务的Binder添加到ServiceManger(ServiceManager是init进程负责启动的,具体是在解析init.rc配置文件时启动的)维护的表单中。

Zygote启动流程分析_第2张图片

四.zygote流程总结

可以使用下面这张图来总结整个zygote流程

Zygote启动流程分析_第3张图片

五.Launcher进程启动app流程

知道这些知识我们就可以来看一下Launcher进程启动app流程:Launcher先去ServiceManager中拿到AMS的Binder,然后基于AMS的Binder到system_server和AMS通信,要求发送一个消息给zygote,要求fork出app进程。

具体流程如下:

Zygote启动流程分析_第4张图片

四.问题思考

1.zygoteServer.runSelectLoop里面的死循环为什么不会消耗cpu资源呢?是和init进程一样使用了linux的epoll机制吗?

2.fork到底做了什么?

     zygote没执行fork之前只有一个zygote进程,执行fork之后多了一个子进程,zygote有的东西在子进程里面都有。

3.app的启动为什么是从zygote fork而不是从init fork

    如果是从init进程fork的话,需要重新创建虚拟机,注册JNI方法等

4.为什么zygote启动的时候是采用socket而不是binder

假如需要创建10个进程,AMS发送10条消息给zygote,如果是使用binder,这时候AMS是C端,zygote是S端,AMS需要拿到zygote的binder。

   第一点: init进程会先创建servcieManager(AMS的binder是注册在servcieManager中的),后创建zygote。system_server进程又是zygote fork出来的,他的职责就是创建服务并且往servcieManager里面注册相应的binder。如果AMS想通过binder向Zygote发送信号,必须向ServiceManager获取Zygote的binder引用,而前提是Zygote进程中必须提前注册好才行。因为servcieManager和zygote是两个进程,不能保证zygote注册binder的时候servcieManager已经初始化好了。(本人持怀疑态度,按照这个逻辑,在system_server进程中创建好AMS等服务后,并且把对应binder注册到ServiceManager,此时ServiceManager也有可能没有初始化完成)

第二点:AMS拿到zygote的binder后,会在在binder线程池里面创建10个线程去处理这十个消息,进行十次fork。这时候如果Binder中有一个线程处于等锁的状态,fork出来的进程的Binder依旧在等锁。通过zygote fork出来的zygote进程的Binder会自己解锁,但是zygote fork出来的另外的一个进程里面的Binder没有进程可以给他解锁,一直是死锁。而socket是一个消息处理完,再处理下一个,不会出现死锁。

可参考android中AMS通知Zygote去fork进程为什么使用socket而不使用binder?_zygote为什么用socket-CSDN博客

你可能感兴趣的:(zygote,android)