Android启动过程 - Zygote

这篇具有很好参考价值的文章主要介绍了Android启动过程 - Zygote。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、Zygote servcie的配置

在上一篇中,我们知道zygote进程是在`/system/etc/init/hw/init.rc`文件中配置,由init进程启动的。看下init中关于zygote的配置:

...
import /system/etc/init/hw/init.${ro.zygote}.rc
...

on late-init
    ...
    trigger zygote-start

on zygote-start
    // 等待签名校验完成
    // platform\system\security\ondevice-signing\odsign_main.cpp
    wait_for_prop odsign.verification.done 1
    // 启动用于标识(A/B)更新完成的守护进程
    exec_start update_verifier
    // 启动收集性能指标的statsd服务
    start statsd
    // 启动网络管理模块
    start netd
    // 启动zygote
    start zygote
    start zygote_secondary
    
on userspace-reboot-resume
    ...
    trigger zygote-start

其中第一句import /system/etc/init/hw/init.${ro.zygote}.rc中的ro.zygote为属性,从源码看,对应的文件:core/rootdir/init.zygote64.rc、core/rootdir/init.zygote32.rc和init.zygote64_32.rc。具体是哪一个,可以在实际系统中getprop ro.zygote查看。这里以core/rootdir/init.zygote64_32.rc(兼容64和32位)为例:

import /system/etc/init/hw/init.zygote64.rc

service zygote_secondary /system/bin/app_process32 -Xzygote /system/bin --zygote --socket-name=zygote_secondary --enable-lazy-preload
    class main
    priority -20
    user root
    group root readproc reserved_disk
    socket zygote_secondary stream 660 root system
    socket usap_pool_secondary stream 660 root system
    onrestart restart zygote
    task_profiles ProcessCapacityHigh MaxPerformance

首行所import的init.zygote64.rc内容为:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote
    // 指定class为main。可通过class_start main来启动所有class为main的service
    class main
    // 优先级
    priority -20
    // 设置进程user
    user root
    // 设置进程gorup
    group root readproc reserved_disk
    // 创建一个名为zygote的socket服务端,用于接收孵化新进程的请求
    socket zygote stream 660 root system
    // 创建usap_pool_primary socket。用于以usap方式孵化进程
    socket usap_pool_primary stream 660 root system
    // 下面是在onrestart时执行的一些列指令
    onrestart exec_background - system system -- /system/bin/vdc volume abort_fuse
    onrestart write /sys/power/state on
    # NOTE: If the wakelock name here is changed, then also
    # update it in SystemSuspend.cpp
    onrestart write /sys/power/wake_lock zygote_kwl
    onrestart restart audioserver
    onrestart restart cameraserver
    onrestart restart media
    onrestart restart --only-if-running media.tuner
    onrestart restart netd
    onrestart restart wificond
    // 设置cgroup
    task_profiles ProcessCapacityHigh MaxPerformance
    // 本服务对设备来说是至关重要的。如果在window指定的分钟数(默认为4)内crash超过4次,则重启进入target指定模式(默认为bootloader,即fastboot)。
    critical window=${zygote.critical_window.minute:-off} target=zygote-fatal

从前两篇init.rc的处理过程解析我们知道,如上的声明,执行的过程为:

1)init.zygote64_32.rc里的service zygote.. 、service zygote_secondary被解析后加入service队列等待执行

2)late-init这个trigger被触发,随后继续触发zygote-start,然后从上到下依次执行zygote-start下的每个Command,并最终执行两个zygote服务。

我们看64位的service zygote:

service zygote /system/bin/app_process64 -Xzygote /system/bin --zygote --start-system-server --socket-name=zygote

zygote:service的名称,注意这里并非是进程名称,而是init进程内部标识service的name。 

/system/bin/app_process64:指定了可执行文件的路径。

-Xzygote:是传递给虚拟机的参数,告诉虚拟机是否已zygote模式启动。这里实际影响的是虚拟机启动时是否加载boot.art内存映射文件,即预加载常用的系统类。具体实现的代码路径:

app_main.cpp

runtime.start

AndroidRuntime.cpp

startVm(&mJavaVM, &env, zygote, primary_zygote)

java_vm_ext.cc

JNI_CreateJavaVM

runtime.cc

bool Runtime::Create(RuntimeArgumentMap&& runtime_options

bool Runtime::Init(RuntimeArgumentMap&& runtime_options_in)

Opt runtime_options(std::move(runtime_options_in))

gc::Heap(runtime_options.GetOrDefault(Opt::MemoryInitialSize)

heap.cc

space::ImageSpace::LoadBootImage(boot_class_path,

image_space.cc

bool ImageSpace::LoadBootImage(const std::vector<std::string>& 

BootImageLayout::LoadFromSystem(

ImageSpace::BootImageLayout::Load

/system/bin:目前实际没有使用到

--zygote:app_process64内部有两种启动模式,--zygote指定启动类为com.android.internal.os.ZygoteInit。另一种则启动com.android.internal.os.RuntimeInit。

--start-system-server:指明启动system server

--socket-name:指定作为客户端要连接的服务端zygote名称。首先zygote service在启动时,先根据下面option的声明`socket zygote stream 660 root system`创建一个服务端的socket,名称为zygote。随后再启动作为zygote的app_process64进程。启动进程的过程中,会根据--socket-name参数指定的名称,创建socket客户端去连接服务端。我们知道zygote是app进程的孵化器,被孵化的子进程将继承这个客户端的socket,与服务端通信。

service zygote下的options:

class main是在某些时候,比如init将文件系统挂载后,通过class_start main启动所有class为main的服务。class同为main的service还有storaged、netd等service。

priority和task_profiles是为zygote进程分配了优先级较高的cpu资源,同时保证在内存紧张时不会被回收

socket zygote和usap_pool_primary,是建立了两种孵化进程方式的通道。除了传统的zygote孵化方式,从Android Q开始,新增了usap方式,可以预创建一个进程池,在孵化app进程时更加高效。

而一系列的onrestart,则是在zygote进程意外退出被init重启的情况下,需要一同启动的一系列基础服务servcie,如audioserver、cameraserver、media等等。

二、Zygote进程的启动

/system/bin/app_process64的源码在app_main.cpp, 入口为main函数

platform/frameworks/base/cmds/app_process/app_main.cpp

int main(int argc, char* const argv[])
{
    ...
    // 虚拟机runtime
    AppRuntime runtime(argv[0], computeArgBlockSize(argc, argv));
    ...
    // 将虚拟机参数-XZytote放入runtime.addOption
    for (i = 0; i < argc; i++) {
        if (argv[i][0] != '-') {
            break;
        }
        if (argv[i][1] == '-' && argv[i][2] == 0) {
            ++i; // Skip --.
            break;
        }
        runtime.addOption(strdup(argv[i]));
    }
    
    // 解析跟zygote本身有关的参数
    ++i;  // Skip unused "parent dir" argument.
    while (i < argc) {
        const char* arg = argv[i++];
        // 如果设置--zygote参数,则把进程名设置为ZYGOTE_NICE_NAME,也就是zygote64
        if (strcmp(arg, "--zygote") == 0) {
            zygote = true;
            niceName = ZYGOTE_NICE_NAME;
        } else if (strcmp(arg, "--start-system-server") == 0) {
            startSystemServer = true;
        } else if (strcmp(arg, "--application") == 0) {
            application = true;
        } else if (strncmp(arg, "--nice-name=", 12) == 0) {
            niceName = (arg + 12);
        } else if (strncmp(arg, "--", 2) != 0) {
            className = arg;
            break;
        } else {
            --i;
            break;
        }
    }
    
    if (!className.empty()) {
        // zygote模式不走此分支
    } else {
        // 创建/data/dalvik-cache/"ABI(cpu架构)"目录
        maybeCreateDalvikCache();
        
        // 将rc里的参数整理到args里
        if (startSystemServer) {
            args.add(String8("start-system-server"));
        }

        char prop[PROP_VALUE_MAX];
        if (property_get(ABI_LIST_PROPERTY, prop, NULL) == 0) {
            LOG_ALWAYS_FATAL("app_process: Unable to determine ABI list from property %s.",
                ABI_LIST_PROPERTY);
            return 11;
        }

        String8 abiFlag("--abi-list=");
        abiFlag.append(prop);
        args.add(abiFlag);

        // In zygote mode, pass all remaining arguments to the zygote
        // main() method.
        for (; i < argc; ++i) {
            args.add(String8(argv[i]));
        }
    }
    // 设置进程名
    if (!niceName.empty()) {
        runtime.setArgv0(niceName.c_str(), true /* setProcName */);
    }
    
    // 启动ZygoteInit,传入args参数
    if (zygote) {
        runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
    } else if (...) {
        ...
    }
    ...
}    

上面的代码做了几件事:

  1. 创建AppRuntime runtime
  2. 解析以‘-’开头的虚拟机参数,传给runtime
  3. 解析以‘--’开头的zygote参数
  4. 创建/data/dalvik-cache/目录
  5. 通过runtime.start启动ZygoteInit。

AppRuntime是AndroidRuntime的子类,直接看AndroidRuntime的start:

core/jni/AndroidRuntime.cpp

void AndroidRuntime::start(const char* className, const Vector<String8>& options, bool zygote)
{
    static const String8 startSystemServer("start-system-server");
    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)));
        }
    }
    
    ...
    // 初始化虚拟机对象
    JniInvocation jni_invocation;
    jni_invocation.Init(NULL);
    JNIEnv* env;
    if (startVm(&mJavaVM, &env, zygote, primary_zygote) != 0) {
        return;
    }
    
    onVmCreated(env);
    
    // 加载ZygoteInit类
    jclass stringClass;
    jobjectArray strArray;
    jstring classNameStr;

    stringClass = env->FindClass("java/lang/String");
    assert(stringClass != NULL);
    strArray = env->NewObjectArray(options.size() + 1, stringClass, NULL);
    assert(strArray != NULL);
    classNameStr = env->NewStringUTF(className);
    assert(classNameStr != NULL);
    /将第一个参数设置为类名
    env->SetObjectArrayElement(strArray, 0, classNameStr);

    for (size_t i = 0; i < options.size(); ++i) {
        jstring optionsStr = env->NewStringUTF(options.itemAt(i).c_str());
        assert(optionsStr != NULL);
        env->SetObjectArrayElement(strArray, i + 1, optionsStr);
    }

    /*
     * Start VM.  This thread becomes the main thread of the VM, and will
     * not return until the VM exits.
     */
    char* slashClassName = toSlashClassName(className != NULL ? className : "");
    jclass startClass = env->FindClass(slashClassName);
    if (startClass == NULL) {
        ALOGE("JavaVM unable to locate class '%s'\n", slashClassName);
        /* keep going */
    } else {
        /调用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 {
            env->CallStaticVoidMethod(startClass, startMeth, strArray);

#if 0
            if (env->ExceptionCheck())
                threadExitUncaughtException(env);
#endif
        }
    }
    free(slashClassName);
}

看下初始化虚拟机的函数startVm

int AndroidRuntime::startVm(JavaVM** pJavaVM, JNIEnv** pEnv, bool zygote, bool primary_zygote)
{
    JavaVMInitArgs initArgs;
    ...
    处理一系列参数
    ...
    if (JNI_CreateJavaVM(pJavaVM, pEnv, &initArgs) < 0) {
        ALOGE("JNI_CreateJavaVM failed\n");
        return -1;
    }
}

上面的代码,就是启动了一个虚拟机,加载ZygoteInit,执行其main方法。

看下ZygoteInit的main:

core/java/com/android/internal/os/ZygoteInit.java

public static void main(String[] argv) {
    // 在zygote中不可创建thread
    ZygoteHooks.startZygoteNoThreadCreation();
    // 一些在zygote fork前要做的工作,比如mimeType文件映射
    RuntimeInit.preForkInit();
    // 解析service参数
    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;
            // --abi-list=
        } else if (argv[i].startsWith(ABI_LIST_ARG)) {
            abiList = argv[i].substring(ABI_LIST_ARG.length());
            // --socket-name=
        } 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]);
        }
    }
    
    if (!enableLazyPreload) {
        ...
        // 预加载
    	 preload(bootTimingsTraceLog);
    }
    
    // 在fork前做一波gc
    gcAndFinalize();
    // 初始化zygote的native状态,包括获取socket的fd,初始化security properties,卸载 /storage目录,初始化用于cgroup设置的TaskProfiles对象等
    Zygote.initNativeState(isPrimaryZygote);
    
    // 解除不允许创建线程的限制
    ZygoteHooks.stopZygoteNoThreadCreation();
    
    // 初始化ZygoteServer。实际上是init.rc里那个服务端socket的封装
    zygoteServer = new ZygoteServer(isPrimaryZygote);
    
    // 开始孵化SystemServer
    if (startSystemServer) {
        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 (!= null) {
            r.run();
            return;
        }
    }
    
    // 监听sock请求,fork新的进程
    caller = zygoteServer.runSelectLoop(abiList);
    
}

在main方法中,主要做了以下事情:

  1. 通过RuntimeInit.preForkInit();初始化mimeType文件映射
  2. 在preload方法中作了一些预加载的工作,其中包括Locale、DecimalFormatData、SimpleDateFormatData的初始化;常用基础类的初始化;资源的初始化;android so库的加载等等。
  3. Zygote.initNativeState进行了native层面的一些初始化工作,如卸载/storage、初始化cgroup的TaskProfiles等
  4. 启动SystemServer
  5. 监听socket请求,收到请求后fork新的进程。
  • preload

看下比较重要的部分preload(bootTimingsTraceLog);

platform/frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

static void preload(TimingsTraceLog bootTimingsTraceLog) {
        Log.d(TAG, "begin preload");
        bootTimingsTraceLog.traceBegin("BeginPreload");
        // 初始化Locale、DecimalFormatData、SimpleDateFormatData等
        beginPreload();
        bootTimingsTraceLog.traceEnd(); // BeginPreload
        bootTimingsTraceLog.traceBegin("PreloadClasses");
        // 预加载类
        preloadClasses();
        bootTimingsTraceLog.traceEnd(); // PreloadClasses
        bootTimingsTraceLog.traceBegin("CacheNonBootClasspathClassLoaders");
        // 缓存非boot的class
        cacheNonBootClasspathClassLoaders();
        bootTimingsTraceLog.traceEnd(); // CacheNonBootClasspathClassLoaders
        bootTimingsTraceLog.traceBegin("PreloadResources");
        // 预加载资源
        Resources.preloadResources();
        bootTimingsTraceLog.traceEnd(); // PreloadResources
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadAppProcessHALs");
        // hal层初始化
        nativePreloadAppProcessHALs();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        Trace.traceBegin(Trace.TRACE_TAG_DALVIK, "PreloadGraphicsDriver");
        // 渲染引擎相关初始化
        maybePreloadGraphicsDriver();
        Trace.traceEnd(Trace.TRACE_TAG_DALVIK);
        preloadSharedLibraries();
        preloadTextResources();
        // Ask the WebViewFactory to do any initialization that must run in the zygote process,
        // for memory sharing purposes.
        WebViewFactory.prepareWebViewInZygote();
        endPreload();
        warmUpJcaProviders();
        Log.d(TAG, "end preload");

        sPreloadComplete = true;
    }
  1. 预加载类:preloadClasses(BootClassLoader)
private static final String PRELOADED_CLASSES = "/system/etc/preloaded-classes";

private static void preloadClasses() {
    ...
    is = new FileInputStream(PRELOADED_CLASSES);
    ...
    try {
        BufferedReader br = new BufferedReader(new InputStreamReader(is), Zygote.SOCKET_BUFFER_SIZE);
        ...
        String line;
        while ((line = br.readLine()) != null) {
            Class.forName(line, true, null);
            count++;
            ...
        }
     } catch (IOException e) {
            Log.e(TAG, "Error reading " + PRELOADED_CLASSES + ".", e);
    } finally {
       IoUtils.closeQuietly(is);
       // 当前并未有具体实现
       runtime.preloadDexCaches();
       
       if (isExperimentEnabled("profilebootclasspath")) {
           // 重置JitCounters,在预加载后,重新计算method counter,为profile提供依据。
           VMRuntime.resetJitCounters();
       }
    }
    

如上代码,预加载的类在/system/etc/preloaded-classes文件中声明,即所谓的BootClassPath类。读取该文件每行类名,通过Class.forName进行加载。

这里声明的只是类名,而不是类本身所在的dex。BootClassPath类本身所在的dex可通过环境变量$BOOTCLASSPATH查看。

首先,在虚拟机初始化时,Runtime::Init函数会通过OpenBootDexFiles加载$BOOTCLASSPATH指定的dex文件,随后如上Zygote启动时根据/preloaded-classes里的名单加载具体类。

我们通常说Android里的ClassLoader有三层:BootClassLoader、PathClassLoader、DexClassLoader。BootClassLoader加载了Java基础jre类,PathClassLoader加载了android的system系统类、Application应用所需基础类。DexClassClassLoader可以用来在app运行时动态加载dex,是用户层面的ClassLoader。而上面所描述的preloadClasses,就是BootClassLoader创建、启动、加载jre类的过程。至于PathClassLoader,我们在下面的SystemServer启动过程中可以看到。

  1. 预加载资源preloadResources
public static void preloadResources() {
    final Resources sysRes = Resources.getSystem();
    sysRes.startPreloading();
    TypedArray ar = sysRes.obtainTypedArray(
              com.android.internal.R.array.preloaded_drawables);
    int numberOfEntries = preloadDrawables(sysRes, ar);
    ar = sysRes.obtainTypedArray(com.android.internal.R.array.preloaded_color_state_lists);
    numberOfEntries = preloadColorStateLists(sysRes, ar);
    ar = sysRes.obtainTypedArray(com.android.internal.R.array.preloaded_freeform_multi_window_drawables);
    numberOfEntries = preloadDrawables(sysRes, ar);
}

首先,Resources.getSystem()中,加载了/system/framework/framework-res.apk

platform/frameworks/base/core/java/android/content/res/Resources.java

public static Resources getSystem() {
        synchronized (sSync) {
            Resources ret = mSystem;
            if (ret == null) {
                ret = new Resources();
                mSystem = ret;
            }
            return ret;
        }
    }
private Resources() {
        this(null);

        final DisplayMetrics metrics = new DisplayMetrics();
        metrics.setToDefaults();

        final Configuration config = new Configuration();
        config.setToDefaults();

        mResourcesImpl = new ResourcesImpl(AssetManager.getSystem(), metrics, config,
                new DisplayAdjustments());
    }

platform/frameworks/base/core/java/android/content/res/AssetManager.java

private static final String FRAMEWORK_APK_PATH = "/system/framework/framework-res.apk";

public static AssetManager getSystem() {
        synchronized (sSync) {
            createSystemAssetsInZygoteLocked(false, FRAMEWORK_APK_PATH);
            return sSystem;
        }
    }

随后,从platform/frameworks/base/core/res/res/values/arrays.xml下,预加载preloaded_drawables、preloaded_color_state_lists、preloaded_freeform_multi_window_drawables等资源。

  1. nativePreloadAppProcessHALs初始化hal层
  2. preloadSharedLibraries: 加载so
private static void preloadSharedLibraries() {
        Log.i(TAG, "Preloading shared libraries...");
        System.loadLibrary("android");
        System.loadLibrary("jnigraphics");

        // TODO(b/206676167): This library is only used for renderscript today. When renderscript is
        // removed, this load can be removed as well.
        if (!SystemProperties.getBoolean("config.disable_renderscript", false)) {
            System.loadLibrary("compiler_rt");F
        }
    }
  1. preloadTextResources 加载字体
  2. WebViewFactory.prepareWebViewInZygote(); webview预申请内存空间
  3. warmUpJcaProviders 安装Jca密码学架构 的provider

三、SystemServer的启动

  • forkSystemServer
private static Runnable forkSystemServer(String abiList, String socketName, ZygoteServer zygoteServer) {
    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,3005,3006,3007,3009,3010,3011,3012",
                "--capabilities=" + capabilities + "," + capabilities,
                // 进程名
                "--nice-name=system_server",
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                // SystemServer的启动类
                "com.android.server.SystemServer",
        };
    ZygoteArguments parsedArgs;

    int pid;

    try {
        ZygoteCommandBuffer commandBuffer = new ZygoteCommandBuffer(args);
        try {
            parsedArgs = ZygoteArguments.getInstance(commandBuffer);
        } catch (EOFException e) {
            throw new AssertionError("Unexpected argument error for forking system server", e);
        }
        commandBuffer.close();
        Zygote.applyDebuggerSystemProperty(parsedArgs);
        Zygote.applyInvokeWithSystemProperty(parsedArgs);
    
        pid = Zygote.forkSystemServer(
        ...
    } catch (IllegalArgumentException ex) {
        throw new RuntimeException(ex);
    }
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }

        zygoteServer.closeServerSocket();
        return handleSystemServerProcess(parsedArgs);
    }

首先,我们关注下args参数:

setgroups设定SystemServer的进程组,这个在调查SystemServer有那些权限的时候会需要。

nice-name设定进程名

com.android.server.SystemServer是入口类,在fork出一个新进程后,执行这个类才真正开始SystemServer的旅程。

我们看下Zygote.forkSystemServer做了什么:

platform/frameworks/base/core/java/com/android/internal/os/Zygote.java

static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
            int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ZygoteHooks.preFork();

        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits,
                permittedCapabilities, effectiveCapabilities);

        // Set the Java Language thread priority to the default value for new apps.
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);

        ZygoteHooks.postForkCommon();
        return pid;
    }

platform/frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

static jint com_android_internal_os_Zygote_nativeForkSystemServer(
        JNIEnv* env, jclass, uid_t uid, gid_t gid, jintArray gids,
        jint runtime_flags, jobjectArray rlimits, jlong permitted_capabilities,
        jlong effective_capabilities) {
        ...
          if (gUsapPoolEventFD != -1) {
            fds_to_close.push_back(gUsapPoolEventFD);
            fds_to_ignore.push_back(gUsapPoolEventFD);
          }
        ...
        pid_t pid = zygote::ForkCommon(env, true,
                                 fds_to_close,
                                 fds_to_ignore,
                                 true);
        
pid_t zygote::ForkCommon(JNIEnv* env, bool is_system_server,
                         const std::vector<int>& fds_to_close,
                         const std::vector<int>& fds_to_ignore,
                         bool is_priority_fork,
                         bool purge) {
         auto fail_fn = std::bind(zygote::ZygoteFailure, env,
                           is_system_server ? "system_server" : "zygote",
                           nullptr, _1);
         ...
         pid_t pid = fork();
         ...

本质上,调用了fork()创建了新进程

在fork了新进程后,调用handleSystemServerProcess来执行SystemServer:

private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {

    if (parsedArgs.mNiceName != null) {
        // 设置进程名system_server
        Process.setArgV0(parsedArgs.mNiceName);
    }
    
    // 获取SystemServer的classpath,也就是jar文件所在路径
    final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
    ...
    // 启动时SystemServer时不带这个参数
    if (parsedArgs.mInvokeWith != null) {
        ...
    } else {
        // 创建pathclassloader
        ClassLoader cl = getOrCreateSystemServerClassLoader();
        if (cl != null) {
	        Thread.currentThread().setContextClassLoader(cl);
        }

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

getOrCreateSystemServerClassLoader创建了一个SystemServerClassLoader,或者我们叫PathClassLoader,也就是上文我们提到的第二层ClassLoader。我们看下其创建过程:

private static ClassLoader getOrCreateSystemServerClassLoader() {
        if (sCachedSystemServerClassLoader == null) {
            final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
            if (systemServerClasspath != null) {
                sCachedSystemServerClassLoader = createPathClassLoader(systemServerClasspath,
                        VMRuntime.SDK_VERSION_CUR_DEVELOPMENT);
            }
        }
        return sCachedSystemServerClassLoader;
    }

Os.getenv("SYSTEMSERVERCLASSPATH")获取dex/jar文件所在路径。一般的值可能是这样的:

/system/framework/services.jar:/system/framework/ethernet-service.jar:/apex/com.android.appsearch/javalib/service-appsearch.jar:/apex/com.android.media/javalib/service-media-s.jar:/apex/com.android.permission/javalib/service-permission.jar

随后通过createPathClassLoader创建ClassLoader:

static ClassLoader createPathClassLoader(String classPath, int targetSdkVersion) {
	String libraryPath = System.getProperty("java.library.path");

	// We use the boot class loader, that's what the runtime expects at AOT.
	ClassLoader parent = ClassLoader.getSystemClassLoader().getParent();

	return ClassLoaderFactory.createClassLoader(classPath, libraryPath, libraryPath,
			parent, targetSdkVersion, true /* isNamespaceShared */, null /* classLoaderName */);
}

ClassLoader.getSystemClassLoader().getParent();返回的是BootClassLoader。看下ClassLoaderFactory.createClassLoader:

platform/frameworks/base/core/java/com/android/internal/os/ClassLoaderFactory.java

public static ClassLoader createClassLoader(String dexPath,
            String librarySearchPath, ClassLoader parent, String classloaderName,
            List<ClassLoader> sharedLibraries, List<ClassLoader> sharedLibrariesLoadedAfter) {
	ClassLoader[] arrayOfSharedLibraries = (sharedLibraries == null)
			? null
			: sharedLibraries.toArray(new ClassLoader[sharedLibraries.size()]);
	ClassLoader[] arrayOfSharedLibrariesLoadedAfterApp = (sharedLibrariesLoadedAfter == null)
			? null
			: sharedLibrariesLoadedAfter.toArray(
					new ClassLoader[sharedLibrariesLoadedAfter.size()]);
	if (isPathClassLoaderName(classloaderName)) {
		return new PathClassLoader(dexPath, librarySearchPath, parent, arrayOfSharedLibraries,
				arrayOfSharedLibrariesLoadedAfterApp);
	} else if (isDelegateLastClassLoaderName(classloaderName)) {
		return new DelegateLastClassLoader(dexPath, librarySearchPath, parent,
				arrayOfSharedLibraries, arrayOfSharedLibrariesLoadedAfterApp);
	}

	throw new AssertionError("Invalid classLoaderName: " + classloaderName);
}

最后会走到return new PathClassLoader(...这一步。以上步骤简言之,就是通过Os.getenv("SYSTEMSERVERCLASSPATH");所指定的dex/jar文件,构建了一个PathClassLoader。

回到handleSystemServerProcess, 接下来调用ZygoteInit.zygoteInit

    public static 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();
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }

看RuntimeInit.applicationInit这一步。注意这里将之前的classloader、参数argv传了进去:

platform/frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        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
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }

Arguments里,将之前的参数“com.android.server.SystemServer”解析了出来,放到了startClass属性里,因此findStaticMain的首个参数就是com.android.server.SystemServer

看下findStaticMain:

protected static Runnable findStaticMain(String className, String[] argv, ClassLoader classLoader) {
        ...
        cl = Class.forName(className, true, classLoader);
        ...
        m = cl.getMethod("main", new Class[] { String[].class });
        ...
        return new MethodAndArgsCaller(m, argv);
}

加载com.android.server.SystemServer类,然后调用其main方法。至此,SystemServer启动完毕。

总结一下文章来源地址https://www.toymoban.com/news/detail-835081.html

  1. init进程根据init.rc配置service zygote创建Zygote进程
  2. Zygote创建、初始化了虚拟机创建BootClassLoader
  3. 在preloadClasses中加载BootClassPathdex加载基础类
  4. preloadResource加载framework-res.apk加载一些基本的drawable等资源
  5. fork并启动了SystemServer
  6. Zygote进程创建socket服务端循环select检查客户端请求

到了这里,关于Android启动过程 - Zygote的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Android 12 源码分析 —— 应用层 二(SystemUI大体组织和启动过程)

    在前一篇文章中,我们介绍了SystemUI怎么使用IDE进行编辑和调试。这是分析SystemUI的最基础,希望读者能尽量掌握。 本篇文章,将会介绍SystemUI的大概组织架构,以及它的启动过程。本篇文章读完,将会知道: SystemUI为什么选择使用Dagger2 SystemUI怎么新建一个模块 SystemUI的启动

    2024年02月06日
    浏览(75)
  • Android Framework 之 启动流程

    Android 系统的启动流程 Android 系统的启动流程可以分为以下几个主要步骤: 引导加载器(Bootloader)启动 :当你打开一个 Android 设备时,首先启动的是引导加载器。引导加载器负责启动 Android 的核心操作系统。 Linux 内核启动 :引导加载器加载并启动 Linux 内核。Linux 内核负责

    2024年02月14日
    浏览(35)
  • Android Framework学习之Activity启动原理

    Android 13.0 Activity启动原理逻辑流程图如下:

    2024年02月05日
    浏览(52)
  • android framework之Applicataion启动流程分析

    Application启动流程框架分析 启动方式一:通过Launcher启动app 启动方式二:在某一个app里启动第二个app的Activity. 以上两种方式均可触发app进程的启动。但无论哪种方式,最终通过通过调用AMS的startActivity()来启动application的。    根据上图分析, 要启动一个Application,需要涉及五

    2024年02月11日
    浏览(44)
  • 【Android Framework系列】5章 AMS启动流程

    AMS(Activity Manager Service) 是 Android 中最核心的服务,管理着 四大组件的启动 、 切换 、 调度 及 应用进程的管理和调度 等工作。AndroidQ将Activity移到了 ActivityTaskManagerService 中,但也和AMS相关联。 AMS 通过使用一些系统资源和数据结构(如进程、任务栈、记录四大组件生命周期

    2024年02月15日
    浏览(52)
  • android framework之AMS的启动管理与职责

    AMS是什么? AMS管理着activity,Service, Provide, BroadcastReceiver android10后:出现ATMS,ActivityTaskManagerService:ATMS是从AMS中抽出来,单独管理着原来AMS中的Activity组件 。 现在我们对AMS的分析,也就包含对ATMS的分析了。 AMS如何被别人管理?---被SystemServer的SystemServiceManager所管理 AMS如何被人

    2024年02月10日
    浏览(37)
  • Android Framework 常见解决方案(24)屏蔽FallbackHome,去除 Android正在启动,直接进入Launcher

    开机以后,设备会有一个“android正在启动”这样的弹框,这个界面是一个叫FallbackHome的Activity来展示的。FallbackHome机制是Android系统启动过程中的一种降级处理机制。当系统启动时,如果默认的Launcher应用无法正常加载或出现错误,系统会自动启用FallbackHome来替代默认Launcher。

    2024年01月24日
    浏览(47)
  • Android Framework | AOSP源码下载及编译指南(基于Android13)

    AOSP(Android Open Source Project)是Android操作系统的开源项目,通过下载和编译AOSP源码,您可以获得原始的Android系统,并进行定制和开发。本教程将向您介绍如何下载AOSP源码并进行编译的步骤。 如何只是浏览查看AOSP源码,则没必要下载源码,可以使用google提供的Code Search工具进

    2024年01月16日
    浏览(54)
  • 【Android12】Android Framework系列---Adb和PMS安装apk源码流程

    通过adb install命令可以将apk安装到Android系统(注意:特定类型的apk,比如persist类型是无法通过adb安装的) 下述命令中adb解析install命令,并调用Android PackageManagerService进行apk安装。 基于Android12,分析从adb install到 PakcageManagerService安装apk的流程。 adb install命令的源码实现 Andro

    2024年01月22日
    浏览(60)
  • 添加资源到android源码中-修改framework层

    编译带有资源的jar包,需要更改frameworks层,方法如下: 一.增加png类型的图片资源 1.将appupdate模块所有用到的png格式图片拷贝到framework/base/core/res/res/drawable-mdpi里。但是要确保没有与原生的没有重名文件。 2.在framework/base/core/res/res/values/public.xml文件里增加对这些图片的声明。

    2024年02月16日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包