深入学习 Android Framework 之 SystemServer 进程启动详解

news2025/1/23 17:47:31

深入学习 Android Framework

第三:深入学习 Android Framework 之 SystemServer 进程启动详解


文章目录

  • 深入学习 Android Framework
  • 前言
  • 一、Android 系统的启动流程
    • 1. 流程图
    • 2. 启动流程概述
  • 二、源码详解
    • 1. 时序图
    • 2. 源代码
      • 1、ZygoteInit # main()
      • 2、ZygoteInit # forkSystemServer()
        • 2.1、Zygote # forkSystemServer()
          • 2.1.1、Zygote # nativeForkSystemServer()
          • 2.1.2、Zygote # ForkCommon()
          • 2.1.3、Zygote # SpecializeCommon()
        • 2.2、ZygoteInit # handleSystemServerProcess()
        • 2.3 ZygoteInit # zygoteInit()
          • 2.3.1 ZygoteInit # nativeZygoteInit()
          • 2.3.2 app_main # main()
          • 2.3.3 RuntimeInit # applicationInit()
          • 2.3.4 RuntimeInit # findStaticMain()
          • 2.3.5 MethodAndArgsCaller # run()
      • 3 SystemServer # main()
        • 3.1 SystemServer # performPendingShutdown()
        • 3.2 SystemServer # createSystemContext()
        • 3.3 SystemServiceManager
        • 3.4 SystemServer # startBootstrapServices()
        • 3.5 SystemServer # startCoreServices()
        • 3.5 SystemServer # startOtherServices()
  • 三、SystemServer 启动的服务及其作用
    • 1、引导服务
    • 2、核心服务
    • 3、其他服务
  • 总结


前言

Zygote 的纸面意思 “受精卵”,由他孵化出 Android 系统的其他进程。SystemServer 和其他所有 Dalivik 虚拟机进程都是由 Zygote 经过 fork 复制而来。SystemServer 作为 Zygote 进程 fork 出的第一个进程,其进程名为:system_server。其承载着整个 Framework 的核心服务,如创建并启动 ActivityManagerService、PowerManagerService、DisplayManagerService、PackageManagerService、WindowManagerService、LauncherAppsService、InputManagerService 等 90 多个核心系统服务。接下来一起深入学习一下 SystemServer 进程的创建与启动流程。


一、Android 系统的启动流程

1. 流程图

Android系统启动流程图

2. 启动流程概述

结合上面的流程图,先概述一下 Android 系统的总体启动流程:

  1. Android 系统按下电源键开机时,系统的引导芯片代码将从预定义的地方 ( 在ROM ) 开始执行,并去加载引导程序 BootLoaderRAM 中,然后执行 BootLoader
  2. 引导程序是 Android 系统被拉起来之前的一个程序,其作用是把 Android 系统拉起运行,也就是把 Linux 内核启动起来。
  3. 当 Linux 内核启动后会初始化各种软硬件环境、加载驱动程序、挂载根文件系统等,待到加载工作准备完毕后,开始加载一些特定的程序(进程),第一个加载的是 init 进程init 进程Linux 系统中用户空间的第一个进程,进程号固定位 1
  4. 内核启动后,在用户空间启动 init 进程,并调用 init 的 main() 方法。其作用有:创建目录、挂载分区;解析 init.rc 配置文件;启动解析 init.rc 配置文件获取到的服务(如:Zygote进程ServiceManager等);守护解析后启动的服务;
  5. 创建启动 Zygote 进程,首先会创建一个 Java 虚拟机实例,然后注册所有 Framework 相关的系统 JNI 接口,为 Java 世界做好准备。通过 JNI 调用进入 Java 世界,并调用 ZygoteInit.main() 方法,给 Zygote 注册 Socket 用于进程间通信,同时预加载一些常用的 Java 类库和系统资源(如:system/etc/preloaded-c]asses 文件中的类、drawable和 color 资源、opengl 等),执行 gc() 清理内存,为 fork 子进程做好准备。然后 fork 出子进程,并在子进程中初始化 SystemServer 进程,初始化的过程中启动 Android 系统所有的 Service 服务(其中包括输入系统服务 IMS);
  6. Zygote 进程启动后,在后台持续监听 Socket 等待新的应用启动请求,并且监听 SystemServer 的 SIGHID 信号,如果 SystemServer 挂掉,立即 kill 掉 Zygote 自己,然后 init 会重启 Zygote,再启动 SystemServer,使系统恢复正常(如果不能重新起来,将会导致手机重启)。
  7. ActivityManagerService 以后简称 AMS 执行 startService() 启动服务,并调用其 systemReady() 方法后,寻找系统的 “Startup” Application,并向 Zygote 发送请求,Zygote fork 出 “Startup” Application,也就是启动 Launcher 应用,然后将已经安装的应用程序图标显示到桌面上,完成 Android 系统启动。

二、源码详解

接下来,就让我们深入 Android 系统源码,通过源码来详细的分析学习 SystemServer 的启动流程。首先看一下 SystemServer 进程启动的时序图,即先总览全局,再深入细节,便于理解代码。

1. 时序图

Zygote 启动 SystemServer 时序图

2. 源代码

在分析 Zygote 进程启动流程中可知, system_server 进程是在 ZygoteInit # main() 函数进入循环等待之前启动的,进入代码一探究竟

1、ZygoteInit # main()

xref: /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public class ZygoteInit {
	......
	@UnsupportedAppUsage
    public static void main(String[] argv) {
        ZygoteServer zygoteServer = null;
        ......
        Runnable caller;
        try {
            ...... // 解析传入参数
            zygoteServer = new ZygoteServer(isPrimaryZygote);
            if (startSystemServer) {
            	// 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.
                // 如果返回值 r 为空则是在父进程,即 Zygote 进程,如果 r 不为空则是在子进程,即 system_server 进程
                if (r != null) {
                    r.run(); // 启动 SystemServer,调用 SystemServer # main() 方法,即入口函数
                    return; // 在Android 8.0之前是通过抛异常的方式来启动,这里是直接return出去,用来清空栈,提高栈帧利用率
                }
            }
            ......
            // 开启 loop 循环,在后台持续监听 client socket 发来的消息,等待新的应用启动请求
            caller = zygoteServer.runSelectLoop(abiList);
        } catch (Throwable ex) {
            Log.e(TAG, "System zygote died with fatal exception", ex);
            throw ex;
        } finally {
            if (zygoteServer != null) {
                zygoteServer.closeServerSocket();
            }
        }
        // 若fork出系统进程,则加入到列表,然后继续阻塞等待;若 fork 出子进程,则退出loop循环,返回创建的应用子进程,并执行子进程的启动。
        if (caller != null) {
            caller.run();
        }
    }
    ......
}

首先解析传入参数,新建 ZygoteServer 实例对象,然后调用 ZygoteInit # forkSystemServer() 方法来 fork 出 system_server 进程,如果返回值 Runnable r 不为空则是在子进程,即通过 fork 复制出的 system_server 进程,随后调用 Runnable # run() 方法启动 SystemServer,调用 SystemServer # main() 方法,即入口函数。之后开启 Loop 循环,在后台持续监听 client socket 发来的消息,等待新的应用启动请求,如果 fork 出系统进程,则加入到列表,然后继续阻塞等待;如果 fork 出子进程,则退出 Loop 循环,返回创建的应用子进程,并执行子进程的启动。继续跟进源码去查看一下

2、ZygoteInit # forkSystemServer()

xref: /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public class ZygoteInit {
	......
    // 准备参数,然后 fork 出 system_server 进程
    // 返回一个 Runnable 并提供进入子进程 system_server 的入口点,如果返回空则是在父进程,即 Zygote 进程
	private static Runnable forkSystemServer(String abiList, String socketName,
                                             ZygoteServer zygoteServer) {
        ......
        // 创建 args 数组,保存 system_server 启动的参数,uid 和 gid 都为 1000
        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", // 进程名为 system_server
                "--runtime-args",
                "--target-sdk-version=" + VMRuntime.SDK_VERSION_CUR_DEVELOPMENT,
                "com.android.server.SystemServer", // 启动的类名为:com.android.server.SystemServer
        };
        ZygoteArguments parsedArgs = null;
        int pid;
        try { // 按 ZygoteArguments 的格式解析封装上面保存的参数
            parsedArgs = new ZygoteArguments(args);
            Zygote.applyDebuggerSystemProperty(parsedArgs);
            Zygote.applyInvokeWithSystemProperty(parsedArgs);
            ......
            // fork 出系统服务进程 system_server
            pid = Zygote.forkSystemServer(
                    parsedArgs.mUid, parsedArgs.mGid,
                    parsedArgs.mGids,
                    parsedArgs.mRuntimeFlags,
                    null,
                    parsedArgs.mPermittedCapabilities,
                    parsedArgs.mEffectiveCapabilities);
        } catch (IllegalArgumentException ex) {
            throw new RuntimeException(ex);
        }
        if (pid == 0) { // 进入子进程 system_server 进程
            if (hasSecondZygote(abiList)) {
                waitForSecondaryZygote(socketName); // 需等待第二个 Zygote 创建完成
            }
            zygoteServer.closeServerSocket(); // fork 时会copy socket,Zygote 原有的 socket 需要关闭
            return handleSystemServerProcess(parsedArgs); // system_server 进程处理自己的工作
        }
        return null;
    }
    ......
}

ZygoteInit # forkSystemServer() 方法主要执行了以下几个任务:

  1. 创建 args 数组,保存 system_server 启动的参数,然后调用 Zygote # forkSystemServer()方法 fork 出 system_server 进程。
  2. 如果系统初始化了 SecondaryZygote,则需等待第二个 zygote 创建完成。
  3. 由于 fork 的过程会拷贝 socket,因此在 fork 出 system_server 进程后,需要关闭从 zygote 进程复制过来的 socket 连接。
  4. 最后调用 ZygoteInit # handleSystemServerProcess() 方法处理 system_server 进程的初始化过程。
2.1、Zygote # forkSystemServer()

xref: /frameworks/base/core/java/com/android/internal/os/Zygote.java

public class Zygote {
	......
	static int forkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
                                int[][] rlimits, long permittedCapabilities, long effectiveCapabilities) {
        ZygoteHooks.preFork();
        // 调用 native 层的方法来fork system_server 进程
        int pid = nativeForkSystemServer(
                uid, gid, gids, runtimeFlags, rlimits,
                permittedCapabilities, effectiveCapabilities);
        // 当前线程的优先级设置为新应用程序的默认值
        Thread.currentThread().setPriority(Thread.NORM_PRIORITY);
        ZygoteHooks.postForkCommon();
        return pid;
    }
    
     private static native int nativeForkSystemServer(int uid, int gid, int[] gids, int runtimeFlags,
             int[][] rlimits, long permittedCapabilities, long effectiveCapabilities);
    ......
}

调用 native 层方法 nativeForkSystemServer() 来 fork 出 system_server 进程,最终通过 JNI 调用到 native 层的:com_android_internal_os_Zygote_nativeForkSystemServer() 方法,该方法在 com_android_internal_os_Zygote.cpp 文件中,继续跟踪源码查看

2.1.1、Zygote # nativeForkSystemServer()

xref: /frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

    static const JNINativeMethod gMethods[] = { // JIN 注册的映射关系
            ......
            {"nativeForkSystemServer", "(II[II[[IJJ)I", 
             (void*)com_android_internal_os_Zygote_nativeForkSystemServer},
            ......
    };
    ......
	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) {
		......
		// 继续通过 ForkCommon 方法来进行 fork
        pid_t pid = zygote::ForkCommon (env, true,
                fds_to_close,
                fds_to_ignore,
                true);
        if (pid == 0) {
            // 进入子进程,由于 system_server 进程不需要数据隔离,所以不需要知道 pkg_data_info_list,因此传 nullptr
            SpecializeCommon(env, uid, gid, gids, runtime_flags, rlimits, permitted_capabilities,
                    effective_capabilities, MOUNT_EXTERNAL_DEFAULT, nullptr, nullptr, true,
                    false, nullptr, nullptr, /* is_top_app= */ false,
                    /* pkg_data_info_list */ nullptr,
                    /* allowlisted_data_info_list */ nullptr, false, false);
        } else if (pid > 0) { // 继续进入父进程,即 Zygote 进程
            // Zygote 进程检查子进程是否已经死亡
            ALOGI("System server process %d has been created", pid); // system_server 进程已创建
            gSystemServerPid = pid;	// 将子进程 system_server 的 pid 存在 Zygote 进程的全局变量中
            // 有轻微的窗口提示表明系统服务进程已经挂掉,但因为还未发布该进程的 pid,因此没有注意到,所以在这里重新检查以确保其正常
            int status;
            // 函数使用详解见下面的引用介绍,通过 waitpid 函数获取状态发生变化的子进程 pid,设置 options 标志为 WNOHANG,即非阻塞
            // 如果 pid 指定的子进程没有结束,则立即返回 0,而非阻塞等待;如果结束了,则返回该子进程的进程号,即 pid
            if (waitpid(pid, & status,WNOHANG) ==pid){
            	// 当 system_server 进程死亡后,重启 Zygote 进程
                ALOGE("System server process %d has died. Restarting Zygote!", pid);
                RuntimeAbort(env, __LINE__, "System server process has died. Restarting Zygote!");
            }
			......
        }
        return pid;
    }
    ......

方法中继续调用 Zygote :: ForkCommon() 方法来 fork 出 system_server 进程,同时根据 Zygote :: ForkCommon() 方法返回的进程 pid 进行判断,如果 pid > 0 则继续进入父进程,即 Zygote 进程;如果 pid = 0 表示 system_server 子进程创建成功,进入 system_server 进程,继续调用 SpecializeCommon() 方法。

2.1.2、Zygote # ForkCommon()

xref: /frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

	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) {
		// 注册子进程信号监听器 SigChldHandler,监听子进程的死亡,当子进程死亡后,会产生一个信号,Zygote 进程收到
		// 该信号后就会调用 SigChldHandler() 函数进行处理
        SetSignalHandlers();
		......
		// 通过 Linux 的 fork() 系统调用创建一个新的进程,即创建当前进程的一个副本,使得两个进程在执行相同的代码
		// 但是在不同的内存空间中运行
        pid_t pid = fork();
        if (pid == 0) {	// 子进程,这里指 system_server 进程
            if (is_priority_fork) { // 根据条件设置进程优先级
                setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MAX);
            } else {
                setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_MIN);
            }
            // 预先设置进程的一些属性,如设置 M_SET_ZYGOTE_CHILD 表示自己不是 Zygote 进程 等
            PreApplicationInit();
            // 关闭并清除文件描述符
	        DetachDescriptors(env, fds_to_close, fail_fn);
            ......
        } else {
            ALOGD("Forked child process %d", pid);
        }
		......
        return pid;
    }

分析代码可知,首先通过 SetSignalHandlers() 方法注册子进程信号监听器 SigChldHandler,用来监听子进程的死亡,当子进程死亡后,会产生一个信号,Zygote 进程收到该信号后就会调用 SigChldHandler() 方法进行处理。需要注意的是:Zygote 的信号监听器,关注的是 Zygote fork 出的所有的子进程,而不只是 system_server 进程(每次创建一个新的进程时,Zygote 都会注册对应的监听器)。

然后通过 Linux 的 fork() 系统调用创建一个新的进程,即创建当前进程的一个副本,使得两个进程在执行相同的代码,但是在不同的内存空间中运行。其中的拷贝复制过程,这里不再详述,感兴趣的童鞋可以去查一些 Linux 相关的资料。

2.1.3、Zygote # SpecializeCommon()

xref: /frameworks/base/core/jni/com_android_internal_os_Zygote.cpp

	static void SpecializeCommon(JNIEnv*env, uid_t uid, gid_t gid, jintArray gids, jint runtime_flags,
                                 jobjectArray rlimits, jlong permitted_capabilities,
                                 jlong effective_capabilities, jint mount_external,
                                 jstring managed_se_info, jstring managed_nice_name,
                                 bool is_system_server, bool is_child_zygote,
                                 jstring managed_instruction_set, jstring managed_app_data_dir,
                                 bool is_top_app, jobjectArray pkg_data_info_list,
                                 jobjectArray allowlisted_data_info_list, bool mount_data_dirs,
                                 bool mount_storage_dirs) {
        const char*process_name = is_system_server ? "system_server" : "zygote"; // 进程名
		......
        if (!is_system_server && getuid() == 0) {
        	// 对于非 system_server 子进程,则需创建进程组 group
            const int rc = createProcessGroup(uid, getpid());
            if (rc == -EROFS) {
                ALOGW("createProcessGroup failed, kernel missing CONFIG_CGROUP_CPUACCT?");
            } else if (rc != 0) {
                ALOGE("createProcessGroup(%d, %d) failed: %s", uid, /* pid= */ 0, strerror(-rc));
            }
        }
        SetGids(env, gids, is_child_zygote, fail_fn); // 设置进程 group
        SetRLimits(env, rlimits, fail_fn);	// 设置资源 limit

        if (need_pre_initialize_native_bridge) {
            android::PreInitializeNativeBridge (app_data_dir.has_value() ? app_data_dir.value().c_str()
                    : nullptr,
                    instruction_set.value().c_str());
        }

        if (is_system_server) {
            // 如果是 system_server 则预加载 system_server 的类加载器,并绑定 system_server selinux 域
            env -> CallStaticObjectMethod(gZygoteInitClass, gGetOrCreateSystemServerClassLoader);
            if (env -> ExceptionCheck()) {
                env -> ExceptionClear();
            }
        }
		......
        const char*se_info_ptr = se_info.has_value() ? se_info.value().c_str() : nullptr;
        const char*nice_name_ptr = nice_name.has_value() ? nice_name.value().c_str() : nullptr;
		// selinux 上线文环境 context
        if (selinux_android_setcontext(uid, is_system_server, se_info_ptr, nice_name_ptr) == -1) {
            fail_fn(CREATE_ERROR("selinux_android_setcontext(%d, %d, \"%s\", \"%s\") failed", uid,
                    is_system_server, se_info_ptr, nice_name_ptr));
        }
        // 设置线程名为: system_server,方便调试
        if (nice_name.has_value()) {
            SetThreadName(nice_name.value());
        } else if (is_system_server) {
            SetThreadName("system_server");
        }
		......
        if (is_system_server) {
        	// 调用对应 Zygote.java 的 callPostForkSystemServerHooks() 方法
            env -> CallStaticVoidMethod(gZygoteClass, gCallPostForkSystemServerHooks, runtime_flags);
            if (env -> ExceptionCheck()) {
                fail_fn("Error calling post fork system server hooks.");
            }
            // TODO(b/117874058): Remove hardcoded label here.
            static const char*kSystemServerLabel = "u:r:system_server:s0";
            if (selinux_android_setcon(kSystemServerLabel) != 0) {
                fail_fn(CREATE_ERROR("selinux_android_setcon(%s)", kSystemServerLabel));
            }
        }
		......
        env -> CallStaticVoidMethod(gZygoteClass, gCallPostForkChildHooks, runtime_flags,
                is_system_server, is_child_zygote, managed_instruction_set);
        // 进程优先级设置为默认值
        setpriority(PRIO_PROCESS, 0, PROCESS_PRIORITY_DEFAULT);
        ......
    }
    ......

对新创建的 system_server 进程进行配置,如进程名、进程 group 、资源 limit、预加载 system_server 的类加载器,并绑定 system_server selinux 域,最后设置进程优先级为默认值。

2.2、ZygoteInit # handleSystemServerProcess()

xref: /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public class ZygoteInit {
	......
    private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
        Os.umask(S_IRWXG | S_IRWXO); // 为用户文件创建权限掩码
        if (parsedArgs.mNiceName != null) {
            Process.setArgV0(parsedArgs.mNiceName); // 设置进程名为 system_server
        }
        // 加载指定路径下的 SystemServer 文件
        final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
        if (systemServerClasspath != null) {
        	// 路径不为空则加载执行 dex 优化操作,其内部工作是通过 AIDL 通信将命令参数传给 Installd 来完成的
            performSystemServerDexOpt(systemServerClasspath); 
            // Capturing profiles is only supported for debug or eng builds since selinux normally prevents it.
            if (shouldProfileSystemServer() && (Build.IS_USERDEBUG || Build.IS_ENG)) {
                try {
                    Log.d(TAG, "Preparing system server profile");
                    prepareSystemServerProfile(systemServerClasspath); // 加载 SystemServer 属性配置文件
                } catch (Exception e) {
                    Log.wtf(TAG, "Failed to set up system server profile", e);
                }
            }
        }

        if (parsedArgs.mInvokeWith != null) {
            String[] args = parsedArgs.mRemainingArgs;
            // 如果 SystemServer 类路径不为空,则需将其拼接到前面封装的 ZygoteArguments 的后面
            if (systemServerClasspath != null) { 
                String[] amendedArgs = new String[args.length + 2];
                amendedArgs[0] = "-cp";
                amendedArgs[1] = systemServerClasspath;
                System.arraycopy(args, 0, amendedArgs, 2, args.length);
                args = amendedArgs;
            }
			// 调用 WrapperInit # execApplication 方法使用包装器命令启动并执行运行时应用程序进程
            WrapperInit.execApplication(parsedArgs.mInvokeWith,
                    parsedArgs.mNiceName, parsedArgs.mTargetSdkVersion,
                    VMRuntime.getCurrentInstructionSet(), null, args);
            throw new IllegalStateException("Unexpected return from WrapperInit.execApplication");
        } else {
        	// 构建获取 SystemServer 类加载器,并设置给当前的线程
            ClassLoader cl = getOrCreateSystemServerClassLoader();
            if (cl != null) {
                Thread.currentThread().setContextClassLoader(cl);
            }
            // 将剩余参数交给 ZygoteInit.zygoteInit() 方法完成 SystemServer 进程的初始化
            return ZygoteInit.zygoteInit(parsedArgs.mTargetSdkVersion,
                    parsedArgs.mDisabledCompatChanges,
                    parsedArgs.mRemainingArgs, cl);
        }
    }
    ......
}

首先,为用户文件创建权限掩码,并设置进程名为:system_server。然后,加载指定路径下的 SystemServer 文件,并执行 dex 优化操作。最后构建获取 SystemServer 类加载器并设置给当前的线程,最后将剩余参数交给 ZygoteInit # zygoteInit() 方法完成 SystemServer 进程的初始化。

2.3 ZygoteInit # zygoteInit()

xref: /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java

public class 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(); // 重定向 log 日志输出
		// 进程初始化配置,如设置异常捕获 Handler、时区、重置 LogManager 等等
        RuntimeInit.commonInit();
        // native 层初始化 -- 打开/dev/binder 驱动,映射内核的地址空间,创建 binder 线程用于 IPC 通信
        ZygoteInit.nativeZygoteInit();
        return RuntimeInit.applicationInit(targetSdkVersion, disabledCompatChanges, argv,
                classLoader);
    }
    ......
    private static native void nativeZygoteInit();
}

方法流程如下:

  1. 日志流重定向,将系统输出和系统错误重定向到 Android 日志。
  2. 进程初始化配置,如设置异常捕获 Handler、时区、重置 LogManager 等等。
  3. native 层初始化,打开 /dev/binder 驱动,映射内核的地址空间,创建 binder 线程用于 IPC 通信。
  4. 调用 RuntimeInit # applicationInit() 方法,返回创建的 Runnable 对象。
2.3.1 ZygoteInit # nativeZygoteInit()

ZygoteInit # nativeZygoteInit() 方法,通过 JNI 调用到 native 层的:com_android_internal_os_ZygoteInit_nativeZygoteInit() 方法,该方法在 AndroidRuntime.cpp 文件中,跟踪源码查看

	......
	static AndroidRuntime* gCurRuntime = NULL;
	......
    static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv*env, jobject clazz) {
    	// gCurRuntime 在 AndroidRuntime.cpp 中定义并赋值的,但其实现是在其子类 AppRuntime 类中
        gCurRuntime -> onZygoteInit();
    }
    ......
    int register_com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv*env) {
        const JNINativeMethod methods[] = {
            {"nativeZygoteInit", "()V",
               ( void*)com_android_internal_os_ZygoteInit_nativeZygoteInit },
        };
        return jniRegisterNativeMethods(env, "com/android/internal/os/ZygoteInit",
                methods, NELEM(methods));
    }
    ......
    AndroidRuntime::AndroidRuntime(char*argBlockStart, const size_t argBlockLength) :
            mExitWithoutCleanup(false),
            mArgBlockStart(argBlockStart),
            mArgBlockLength(argBlockLength) {
        init_android_graphics();
        // Pre-allocate enough space to hold a fair number of options.
        mOptions.setCapacity(20);
        assert (gCurRuntime == NULL);        // one per process
        gCurRuntime = this;
    }
    ......

在方法中继续调用 gCurRuntime :: onZygoteInit() 方法,可以看到 gCurRuntime 是 AndroidRuntime 类型的指针,并且在 AndroidRuntime 的构造方法中将自身 this 赋值给 gCurRuntime,即 AndroidRuntime 初始化时将 gCurRuntime 指向对象自身,那么 AndroidRuntime 是在何时初始化的呢?

2.3.2 app_main # main()

我们知道,app_main.cpp 的 main() 函数是 App 进程的主入口,启动解释的运行时,然后启动应用程序,进到源码中查看
xref: /frameworks/base/cmds/app_process/app_main.cpp

 	class AppRuntime : public AndroidRuntime 
 	{
    public:
        AppRuntime( char*argBlockStart, const size_t argBlockLength)
                  :AndroidRuntime(argBlockStart, argBlockLength)
                , mClass(NULL)
        {
        }
        ......
        virtual void onZygoteInit ()
        {	// 获取进程唯一实例,内部首先判断是否变量为NULL,非NULL则直接返回,反之才会调用其构造函数创建ProcessState实例
            // 因此同一进程有且只有一个 ProcessState 实例
            sp<ProcessState> proc = ProcessState::self ();
            ALOGV("App process: starting thread pool.\n");
            // 启动 Binder 线程池,方法内部继续调用 spawnPooledThread() 函数真正去启动线程池
            proc -> startThreadPool(); 
        }
		......
        String8 mClassName;
        Vector<String8> mArgs;
        jclass mClass;
    };
    ......
    int main(int argc, char*const argv[]) {
        ......
        // 创建 AppRuntime
        AppRuntime runtime (argv[0], computeArgBlockSize(argc, argv));
        ......
        if (!niceName.isEmpty()) {
            runtime.setArgv0(niceName.string(), true /* setProcName */);
        }

        if (zygote) {
            runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
        } else if (className) {
            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.");
        }
    }

在 app_main.cpp 的 main() 函数中创建了 AppRuntime,继续查看可知 AppRuntime 是 AndroidRuntime 的子类,在初始化过程中,构建 AppRuntime 的同时调用 AndroidRuntime 的构造函数来进行初始化,并将自身 this 赋值给 gCurRuntime。

因此经过分析可知,上一小节的 gCurRuntime 指向的就是 AppRuntime 对象,也即调用的是 AppRuntime # onZygoteInit() 方法,其方法内首先通过 ProcessState::self () 方法获取进程唯一实例,然后调用 ProcessState::startThreadPool() 方法启动 Binder 线程池,进而 SystemServer 进程就可以使用 Binder 与其他进程进行通信。

ProcessState: 继承自RefBase,其在同一进程内是唯一的,主要用于初始化 Binder 设备( 即打开 binder 设备文件/dev/binder节点) ,并将设备文件映射到进程的地址空间。Binder 线程池中的每一个线程都可以通过它与 Binder 驱动程序建立连接。简言之,其主要工作是调用 open() 函数打开 /dev/binder 驱动设备,再利用 mmap() 映射内核的地址空间, 将 Binder 驱动fd 赋值 ProcessState 对象中的变量 mDriverFD,用于交互操作。

2.3.3 RuntimeInit # applicationInit()

xref: /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public class RuntimeInit {
	......
	private static final native void nativeSetExitWithoutCleanup(boolean exitWithoutCleanup);
	......
	protected static Runnable applicationInit(int targetSdkVersion, long[] disabledCompatChanges,
            String[] argv, ClassLoader classLoader) {
        // true 代表应用程序退出时不调用 AppRuntime.onExit(),否则会在退出前调用,将导致剩余的运行线程在进程实际退出之前崩溃
        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);
        // 余下的参数传给即将要启动的类的静态 main 方法
        return findStaticMain(args.startClass, args.startArgs, classLoader);
    }
	......
}

首先调用 native 层的 nativeSetExitWithoutCleanup() 方法,且入参为 true,true 表示应用程序退出时不调用 AppRuntime.onExit() 方法,否则将会在退出前调用,导致剩余的运行线程在进程实际退出之前崩溃。然后解析参数,并继续调用 RuntimeInit # findStaticMain() 方法,将参数传给即将要启动的类的静态 main() 方法。

2.3.4 RuntimeInit # findStaticMain()

xref: /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public class RuntimeInit {
	......
	protected static Runnable findStaticMain(String className, String[] argv,
            ClassLoader classLoader) {
        Class<?> cl;
        try { // 通过反射机制得到 SystemServer 类
            cl = Class.forName(className, true, classLoader);
        } catch (ClassNotFoundException ex) {
            throw new RuntimeException("Missing class when invoking static main " + className, ex);
        }
        Method m;
        try { // 获取 SystemServer # main() 方法
            m = cl.getMethod("main", new Class[]{String[].class});
        } catch (NoSuchMethodException ex) {
            throw new RuntimeException("Missing static main on " + className, ex);
        } catch (SecurityException ex) {
            throw new RuntimeException("Problem getting static main on " + className, ex);
        }
		// 判断 main 方法是不是 public static 类型
        int modifiers = m.getModifiers();
        if (!(Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
            throw new RuntimeException("Main method is not public and static on " + className);
        }
        // 将获取的 Method 和参数封装成 MethodAndArgsCaller 对象返回,MethodAndArgsCaller 实现了 Runnable 接口
        return new MethodAndArgsCaller(m, argv);
    }
	......
}

首先,此处启动的类名为 fork 子进程时保存到 args 数组中的:com.android.server.SystemServer,并通过反射机制得到 SystemServer 类,然后通过 Class # getMethod() 方法获取 SystemServer 类的 main() 方法,再通过 Method # getModifiers() 方法获取方法的权限修饰,如果不是 public static 类型的则抛出异常,最后将获取的 Method 和参数封装成 MethodAndArgsCaller 对象返回,即返回到 1 ZygoteInit # main() 这节中 ZygoteInit # main() 方法中 forkSystemServer() 方法返回的 Runnable r,如果 r!=null 会调用这个 Runnable # run() 方法。

2.3.5 MethodAndArgsCaller # run()

xref: /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java

public class RuntimeInit {
	......
	 static class MethodAndArgsCaller implements Runnable {
        // 待反射调用的方法
        private final Method mMethod;
		// 待反射调用方法的参数数组
        private final String[] mArgs;
        public MethodAndArgsCaller(Method method, String[] args) {
            mMethod = method;
            mArgs = args;
        }
        public void run() {
            try { // 通过反射机制调用的是 SystemServer # main() 方法并传入传递过来的参数
                mMethod.invoke(null, new Object[]{mArgs});
            } catch (IllegalAccessException ex) {
                throw new RuntimeException(ex);
            } catch (InvocationTargetException ex) {
                Throwable cause = ex.getCause();
                if (cause instanceof RuntimeException) {
                    throw (RuntimeException) cause;
                } else if (cause instanceof Error) {
                    throw (Error) cause;
                }
                throw new RuntimeException(ex);
            }
        }
    }
}

MethodAndArgsCaller # run() 方法中使用了 invoke 反射调用,通过反射机制调用的是 SystemServer # main() 方法并传入传递过来的参数,至此 SystemServer 的 main() 方法得以执行,继续查看源码

3 SystemServer # main()

xref: /frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer implements Dumpable {
	......
	// Zygote 启动 SystemServer 的主要入口
    public static void main(String[] args) {
    	// 初始 SystemServer 对象,再调用其 run() 方法
        new SystemServer().run();
    }
    ......
    private void run() {
        TimingsTraceAndSlog t = new TimingsTraceAndSlog();
        try {
            t.traceBegin("InitBeforeStartServices");
            // 记录进程启动的信息
            SystemProperties.set(SYSPROP_START_COUNT, String.valueOf(mStartCount));
            ......
            // 如果未设置,则将时区属性默认为GMT
            String timezoneProperty = SystemProperties.get("persist.sys.timezone");
            if (!isValidTimeZoneId(timezoneProperty)) {
                Slog.w(TAG, "persist.sys.timezone is not valid (" + timezoneProperty + "); setting to GMT.");
                SystemProperties.set("persist.sys.timezone", "GMT");
            }
			......
            // 设置虚拟机的库文件,在 Android6.0 上用的是 libart.so
            SystemProperties.set("persist.sys.dalvik.vm.lib.2", VMRuntime.getRuntime().vmLibrary());
            // 清除 vm 内存增长上限,由于启动过程需要较多的虚拟机内存空间
            VMRuntime.getRuntime().clearGrowthLimit();
            // 针对部分设备依赖于运行时就产生指纹信息,因此需在开机完成前定义好
            Build.ensureFingerprintProperty();
            // 在 system_server 中,访问环境路径前,需要明确地指定用户
            Environment.setUserRequired(true);
            // 在 system_server 中,需对传入的 bundle 进行解压缩,以避免抛出 BadParcelableException 异常
            BaseBundle.setShouldDefuse(true);
            // 在 system_server 中,当对异常进行打包时,应包括堆栈跟踪
            Parcel.setStackTraceParceling(true);
            // Ensure binder calls into the system always run at foreground priority.
            // 确保当前系统进程的 binder 调用,总是以前台优先级运行
            BinderInternal.disableBackgroundScheduling(true);
            // 在 system server 中,增加 binder 线程的数量,最大值为 31
            BinderInternal.setMaxThreads(sMaxBinderThreads);
            // 为主 Looper thread 做准备
            android.os.Process.setThreadPriority(
                    android.os.Process.THREAD_PRIORITY_FOREGROUND);
            android.os.Process.setCanSelfBackground(false);
            Looper.prepareMainLooper(); // 创建消息 Looper
            Looper.getMainLooper().setSlowLogThresholdMs(
                    SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);
            SystemServiceRegistry.sEnableServiceNotFoundWtf = true;
            // 加载 android_servers.so 库,该库包含的源码在frameworks/base/services/目录下
            System.loadLibrary("android_servers");
            initZygoteChildHeapProfiling();
            // debug 模式下,构建并生成一个线程来监视 fd 泄漏
            if (Build.IS_DEBUGGABLE) {
                spawnFdLeakCheckThread();
            }
            // 检测上次关机过程是否失败,该方法可能不会返回
            performPendingShutdown();
            // 初始化系统上下文
            createSystemContext();
            // 调用每个进程主线模块初始化
            ActivityThread.initializeMainlineModules();
            // 设置转储服务
            ServiceManager.addService("system_server_dumper", mDumper);
            mDumper.addDumpable(this);
            // 创建系统服务管理 SystemServiceManager,对系统服务进行创建、启动和生命周期管理
            mSystemServiceManager = new SystemServiceManager(mSystemContext);
            mSystemServiceManager.setStartInfo(mRuntimeRestart,
                    mRuntimeStartElapsedTime, mRuntimeStartUptime);
            mDumper.addDumpable(mSystemServiceManager);
			// 将 mSystemServiceManager 添加到本地服务的成员 sLocalServiceObjects 中
			// LocalServices 通过用静态 Map 变量 sLocalServiceObjects,来保存以服务类名为key,以具体服务对象为value的Map结构
            LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
            // 为可以并行化的 init 任务准备线程池
            SystemServerInitThreadPool tp = SystemServerInitThreadPool.start();
            mDumper.addDumpable(tp);
            // 为 system server 加载预安装的系统字体,以便 WMS 等服务可以开始使用Typeface。
            // 注意,字体不仅用于文本渲染,还用于某些文本操作(例如textutils . makesafeforpresentation())
            if (Typeface.ENABLE_LAZY_TYPEFACE_INITIALIZATION) {
                Typeface.loadPreinstalledSystemFontMap();
            }
            // 如果这是一个可调试的构建并且设置了系统属性,则附加 JVMTI 代理
            if (Build.IS_DEBUGGABLE) {
                ......
            }
        } finally {
            t.traceEnd();  // InitBeforeStartServices
        }
        // 设置默认的应用 WTF Handler
        RuntimeInit.setDefaultApplicationWtfHandler(SystemServer::handleEarlySystemWtf);
        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); // 为当前的虚拟机初始化 VmPolicy
		......// 省略记录和日志输出等
        // 开启 Looper 循环,一直循环执行
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }
    ......
}

作为 SystemServer 的入口方法,SystemServer # main() 方法很简单,初始 SystemServer 对象并调用其 run() 方法,配置属性、启动服务等任务都在 SystemServer # run() 方法中,这个方法很长,其主要执行了以下任务:

  1. 记录进程启动的信息,配置各种属性信息,然后创建当前线程 Looper 对象,通过 System # loadLibrary() 方法加载静态库 android_servers.so;
  2. 调用 SystemServer # performPendingShutdown() 方法,检测上次关机过程是否失败;
  3. 调用 SystemServer # createSystemContext() 方法创建并初始化系统上下文;
  4. 创建 SystemServiceManager 对象,用来管理系统服务 (SystemService) 的创建、启动和其他生命周期事件的;
  5. 创建服务初始化线程池 SystemServerInitThreadPool,为可以并行化的 init 任务准备线程池,使得系统服务的初始化过程可并行;
  6. 启动引导服务、核心服务以及其他服务;
  7. 通过 Looper # loop() 方法开启循环,等待消息队列 MessageQueue 中的消息到来,则马上进入执行状态。
3.1 SystemServer # performPendingShutdown()

xref: /frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer implements Dumpable {
	......
	private void performPendingShutdown() {
		// 读取系统属性配置 ShutdownThread.SHUTDOWN_ACTION_PROPERTY
        final String shutdownAction = SystemProperties.get(
                ShutdownThread.SHUTDOWN_ACTION_PROPERTY, "");
        if (shutdownAction != null && shutdownAction.length() > 0) {
            boolean reboot = (shutdownAction.charAt(0) == '1');
            final String reason;
            if (shutdownAction.length() > 1) {
                reason = shutdownAction.substring(1, shutdownAction.length());
            } else {
                reason = null;
            }
			// 重启保护,如果需重启恢复以更新应用,应确保在需要时正确执行uncrypt,且如果'/cache/recovery/block.map'没被创建则停止重启
            if (reason != null && reason.startsWith(PowerManager.REBOOT_RECOVERY_UPDATE)) {
                File packageFile = new File(UNCRYPT_PACKAGE_FILE);
                if (packageFile.exists()) {
                    String filename = null;
                    try {
                        filename = FileUtils.readTextFile(packageFile, 0, null);
                    } catch (IOException e) {
                        Slog.e(TAG, "Error reading uncrypt package file", e);
                    }
                    if (filename != null && filename.startsWith("/data")) {
                        if (!new File(BLOCK_MAP_FILE).exists()) {
                            Slog.e(TAG, "Can't find block map file, uncrypt failed or " +
                                    "unexpected runtime restart?");
                            return;
                        }
                    }
                }
            }
            Runnable runnable = new Runnable() {
                @Override
                public void run() {
                    synchronized (this) { 
                    	// 当"sys.shutdown.requested"值为 1 时,则会重启,值不为空时,且不为 1 时,则会关机
                        ShutdownThread.rebootOrShutdown(null, reboot, reason);
                    }
                }
            };
            // ShutdownThread 必须运行在一个能够显示 UI 的 Looper 上,即 UI 主线程上启动 ShutdownThread 的rebootOrShutdown
            Message msg = Message.obtain(UiThread.getHandler(), runnable);
            msg.setAsynchronous(true);
            UiThread.getHandler().sendMessage(msg);
        }
    }
	......
}

读取系统属性配置 ShutdownThread.SHUTDOWN_ACTION_PROPERTY,如果获取到的值为 1 时,则会重启;值不为空且不为 1 时,则会关机。

注意ShutdownThread 必须运行在一个能够显示 UI 的 Looper 上,即 UI 主线程上。

3.2 SystemServer # createSystemContext()

xref: /frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer implements Dumpable {
	......
	private void createSystemContext() {
		// 创建获取 system_server 进程的上下文信息,并设置默认主题
        ActivityThread activityThread = ActivityThread.systemMain();
        mSystemContext = activityThread.getSystemContext();
        mSystemContext.setTheme(DEFAULT_SYSTEM_THEME);
		// 创建获取 SystemUi 的上下文信息并设置默认主题
        final Context systemUiContext = activityThread.getSystemUiContext();
        systemUiContext.setTheme(DEFAULT_SYSTEM_THEME);
    }
	......
}

首先在 ActivityThread # systemMain() 方法中创建获取 ActivityThread 实例对象,然后调用 ActivityThread # attach() 方法,过程中会创建 InstrumentationContextImplApplication 等实例对象。ActivityThread # getSystemContext() 方法中通过 ContextImpl # createSystemContext() 方法创建 system_server 进程的上下文信息等,然后再给上下文设置默认主题信息,具体代码比较易懂,感兴趣的同学自行跟踪查看代码。

3.3 SystemServiceManager

xref: /frameworks/base/services/core/java/com/android/server/SystemServiceManager.java

public final class SystemServiceManager implements Dumpable {
	......
	private final Context mContext;
	// Services that should receive lifecycle events.
    private final ArrayList<SystemService> mServices = new ArrayList<SystemService>();
    ......
    SystemServiceManager(Context context) {
    	mContext = context;
    }
    // 启动 Service,入参为待启动的服务类名,返回服务的实例
    public SystemService startService(String className) {
    	// 内部通过反射调用获取到待启动服务的类
        final Class<SystemService> serviceClass = loadClassFromLoader(className,
                this.getClass().getClassLoader());
        return startService(serviceClass); // 启动获取到的待启动服务类
    }
    ......
    public <T extends SystemService> T startService(Class<T> serviceClass) {
        try {
            ......// 创建待启动服务类的实例对象
            final T service;
            try {
                Constructor<T> constructor = serviceClass.getConstructor(Context.class);
                service = constructor.newInstance(mContext);
            } catch (InstantiationException ex) {
            	...... // 异常捕获并抛出
            }
            startService(service); // 启动服务类
            return service;
        } finally {
            Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
        }
    }
   public void startService(@NonNull final SystemService service) {
        mServices.add(service); // 将启动的服务注册到已启动的服务列表中
        long time = SystemClock.elapsedRealtime();
        try {
            service.onStart(); // 服务启动后,回调其 Service # onStart() 方法
        } catch (RuntimeException ex) {
            throw new RuntimeException("Failed to start service " + service.getClass().getName()
                    + ": onStart threw an exception", ex);
        }
        warnIfTooLong(SystemClock.elapsedRealtime() - time, service, "onStart");
    }
    ......
}

SystemServiceManager 是用来管理系统服务 (SystemService) 的创建、启动和其他生命周期事件的。其内部的 mServices 用来存储启动的 Service 的列表,回调 services 的 onStart() 和 onBootPhase() 生命周期时都需要遍历该 List。

3.4 SystemServer # startBootstrapServices()

xref: /frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer implements Dumpable {
	......
	private void startBootstrapServices(@NonNull TimingsTraceAndSlog t) {
        t.traceBegin("startBootstrapServices");
        // 启动 Watchdog 监控启动引导服务时是否会死锁
        t.traceBegin("StartWatchdog");
        final Watchdog watchdog = Watchdog.getInstance();
        watchdog.start();
        t.traceEnd();
        ...... // 平台配套服务由 AMS、PMS 以及将来可能的其他服务使用
        t.traceBegin("PlatformCompat");
        PlatformCompat platformCompat = new PlatformCompat(mSystemContext);
        ServiceManager.addService(Context.PLATFORM_COMPAT_SERVICE, platformCompat);
        ServiceManager.addService(Context.PLATFORM_COMPAT_NATIVE_SERVICE,
                new PlatformCompatNative(platformCompat));
        AppCompatCallbacks.install(new long[0]);
        t.traceEnd();

        // FileIntegrityService 响应来自应用程序和系统的请求。需在资源准备好之后,在应用程序(或系统中的第一个客户)运行之前运行
        t.traceBegin("StartFileIntegrityService");
        mSystemServiceManager.startService(FileIntegrityService.class);
        t.traceEnd();

        t.traceBegin("StartInstaller"); // 阻塞等待 Installd 服务启动完成且与其建立 socket 通道
        Installer installer = mSystemServiceManager.startService(Installer.class);
        t.traceEnd();

        // 在某些情况下,在启动应用程序后,需要访问设备标识符,因此要在 activity manager 之前注册
        t.traceBegin("DeviceIdentifiersPolicyService");
        mSystemServiceManager.startService(DeviceIdentifiersPolicyService.class);
        t.traceEnd();

        t.traceBegin("UriGrantsManagerService"); // 启动 Uri 授权管理服务
        mSystemServiceManager.startService(UriGrantsManagerService.Lifecycle.class);
        t.traceEnd();

        t.traceBegin("StartPowerStatsService"); // 启动 PowerStatsService 服务,用于功率统计
        mSystemServiceManager.startService(PowerStatsService.class);
        t.traceEnd();

        t.traceBegin("StartIStatsService");
        startIStatsService(); // 阻塞调用,启动 IStats 服务
        t.traceEnd();

        // 在 ActivityManager 之前启动 MemtrackProxyService 服务,以免调用 Memtrack::getMemory() 方法失败
        t.traceBegin("MemtrackProxyService");
        startMemtrackProxyService();
        t.traceEnd();

        // Activity manager 负责显示
        t.traceBegin("StartActivityManager"); // 启动 ActivityTaskManagerService 服务
		// ATMS 是 Android 10 中新增的,本来都是 ActivityManagerService 来管理
		// Google考虑到AMS职责太多、代码太庞大,所以单独拆出来ATMS用于管理Activity及其容器类如Task、Stack、Display等,分担部分职责
        ActivityTaskManagerService atm = mSystemServiceManager.startService(
                ActivityTaskManagerService.Lifecycle.class).getService();
        mActivityManagerService = ActivityManagerService.Lifecycle.startService(
                mSystemServiceManager, atm); // 启动 ActivityManagerService 服务
        mActivityManagerService.setSystemServiceManager(mSystemServiceManager); // AMS 设置 SystemServiceManager
        mActivityManagerService.setInstaller(installer); // AMS 设置 Installer
        mWindowManagerGlobalLock = atm.getGlobalLock(); // 获取 ATMS 的成员 mGlobalLock 赋值给 mWindowManagerGlobalLock
        t.traceEnd();

        // DataLoaderManagerService 数据加载器管理服务需要在包管理服务之前启动
        t.traceBegin("StartDataLoaderManagerService");
        mDataLoaderManagerService = mSystemServiceManager.startService(
                DataLoaderManagerService.class);
        t.traceEnd();

        // IncrementalService 服务需要在包管理服务之前启动
        t.traceBegin("StartIncrementalService");
        mIncrementalServiceHandle = startIncrementalService();
        t.traceEnd();

        // 因有其他业务需要用到,因此 PowerManagerService 电源管理服务要尽早启动
        t.traceBegin("StartPowerManager");
        mPowerManagerService = mSystemServiceManager.startService(PowerManagerService.class);
        t.traceEnd();

        t.traceBegin("StartThermalManager");
        mSystemServiceManager.startService(ThermalManagerService.class);
        t.traceEnd();

        t.traceBegin("StartHintManager");
        mSystemServiceManager.startService(HintManagerService.class);
        t.traceEnd();

        // 电源管理服务已经启动,Activity Manager 初始化电源管理特性
        t.traceBegin("InitPowerManagement");
        mActivityManagerService.initPowerManagement();
        t.traceEnd();

        // 启动恢复系统,以防需要重启
        t.traceBegin("StartRecoverySystemService");
        mSystemServiceManager.startService(RecoverySystemService.Lifecycle.class);
        t.traceEnd();

        // 已经启动并运行了操作系统的基本要素,但须注意,有可能会陷入运行时重启循环
        RescueParty.registerHealthObserver(mSystemContext);
        PackageWatchdog.getInstance(mSystemContext).noteBoot();

        t.traceBegin("StartLightsService"); // 启动 LightsService 服务,管理 LED 和显示
        mSystemServiceManager.startService(LightsService.class);
        t.traceEnd();

        t.traceBegin("StartSidekickService");
        if (SystemProperties.getBoolean("config.enable_sidekick_graphics", false)) {
            mSystemServiceManager.startService(WEAR_SIDEKICK_SERVICE_CLASS);
        }
        t.traceEnd();
        
        // 启动 DisplayManagerService 服务,需在包管理服务之前启动,用于提供显示
        t.traceBegin("StartDisplayManager");
        mDisplayManagerService = mSystemServiceManager.startService(DisplayManagerService.class);
        t.traceEnd();

        // 在初始化包管理服务之前,我们需要默认的显示
        t.traceBegin("WaitForDisplay");
        mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_DEFAULT_DISPLAY);
        t.traceEnd();
		......
        t.traceBegin("StartDomainVerificationService");
        DomainVerificationService domainVerificationService = new DomainVerificationService(
                mSystemContext, SystemConfig.getInstance(), platformCompat);
        mSystemServiceManager.startService(domainVerificationService);
        t.traceEnd();

        t.traceBegin("StartPackageManagerService");
        try { // 启动包管理服务 PackageManagerService
            Watchdog.getInstance().pauseWatchingCurrentThread("packagemanagermain");
            mPackageManagerService = PackageManagerService.main(mSystemContext, installer,
                    domainVerificationService, mFactoryTestMode != FactoryTest.FACTORY_TEST_OFF,
                    mOnlyCore);
        } finally {
            Watchdog.getInstance().resumeWatchingCurrentThread("packagemanagermain");
        }

        // 包管理服务已经启动,注册 dex load reporter 捕获系统服务加载的任何 dex 文件,这些 dex 文件将被后台dexoptservice优化
        SystemServerDexLoadReporter.configureSystemServerDexReporter(mPackageManagerService);

        mFirstBoot = mPackageManagerService.isFirstBoot(); // 是否第一次启动
        mPackageManager = mSystemContext.getPackageManager();
        t.traceEnd();
        if (!mRuntimeRestart && !isFirstBootOrUpgrade()) {
            FrameworkStatsLog.write(FrameworkStatsLog.BOOT_TIME_EVENT_ELAPSED_TIME_REPORTED,
                    FrameworkStatsLog
                            .BOOT_TIME_EVENT_ELAPSED_TIME__EVENT__PACKAGE_MANAGER_INIT_READY,
                    SystemClock.elapsedRealtime());
        }
        ......
        t.traceBegin("StartUserManagerService"); // 启动 UserManagerService 服务
        mSystemServiceManager.startService(UserManagerService.LifeCycle.class);
        t.traceEnd();

        t.traceBegin("InitAttributerCache");
        AttributeCache.init(mSystemContext); // 初始化用于缓存从包中获取的属性缓存
        t.traceEnd();

        // 为系统进程设置 Application 实例并开始
        t.traceBegin("SetSystemProcess");
        mActivityManagerService.setSystemProcess();
        t.traceEnd();

        // PackageReceiver 依赖于 Activity Service 服务来注册
        platformCompat.registerPackageReceiver(mSystemContext);

        // 使用 ActivityManager 实例完成 Watchdog 设置,并侦听重新启动
        // 只有在 ActivityManagerService 作为系统进程且正确启动后才能执行此操作
        t.traceBegin("InitWatchdog");
        watchdog.init(mSystemContext, mActivityManagerService);
        t.traceEnd();
        
        // DisplayManagerService 需要设置与显示调度相关的策略,因为setSystemProcess()会因为setProcessGroup而覆盖策略
        mDisplayManagerService.setupSchedulerPolicies();

        // 启动 OverlayManagerService 服务,用于管理叠加包
        t.traceBegin("StartOverlayManagerService");
        mSystemServiceManager.startService(new OverlayManagerService(mSystemContext));
        t.traceEnd();
		// 启动 SensorPrivacyService 服务,传感器有关如重力加速、光线等
        t.traceBegin("StartSensorPrivacyService");
        mSystemServiceManager.startService(new SensorPrivacyService(mSystemContext));
        t.traceEnd();

        if (SystemProperties.getInt("persist.sys.displayinset.top", 0) > 0) {
            // 更新 DisplayManagerService 服务
            mActivityManagerService.updateSystemUiContext();
            LocalServices.getService(DisplayManagerInternal.class).onOverlayChanged();
        }

        // 启动 SensorService 传感器服务,其需要访问包管理服务、应用ops服务和权限服务,因此我们在它们之后启动它
        t.traceBegin("StartSensorService"); 
        mSystemServiceManager.startService(SensorService.class);
        t.traceEnd();
        t.traceEnd(); // startBootstrapServices
    }
	......
}

代码比较长,方法中按序启动了很多的引导服务,有:Installer、ActivityTaskManagerService、ActivityManagerService、PowerManagerService、LightsService、DisplayManagerService、PackageManagerService、UserManagerService、OverlayManagerService 和 SensorService 等服务,具体可查看代码注释。

3.5 SystemServer # startCoreServices()

xref: /frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer implements Dumpable {
	......
	private void startCoreServices(@NonNull TimingsTraceAndSlog t) {
        t.traceBegin("startCoreServices");

        // 启动 SystemConfigService 系统配置服务
        t.traceBegin("StartSystemConfigService");
        mSystemServiceManager.startService(SystemConfigService.class);
        t.traceEnd();

        t.traceBegin("StartBatteryService");
        // 启动 BatteryService 电池服务,用于统计电池电量,需结合 LightService
        mSystemServiceManager.startService(BatteryService.class);
        t.traceEnd();

        // 启动 UsageStatsService 服务,用于统计应用使用情况
        t.traceBegin("StartUsageService");
        mSystemServiceManager.startService(UsageStatsService.class);
        mActivityManagerService.setUsageStatsManager(
                LocalServices.getService(UsageStatsManagerInternal.class));
        t.traceEnd();

        // 启动 WebViewUpdateService 服务,用于观察可更新的 WebView 是否处于就绪状态,并监视更新安装
        if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_WEBVIEW)) {
            t.traceBegin("StartWebViewUpdateService");
            mWebViewUpdateService = mSystemServiceManager.startService(WebViewUpdateService.class);
            t.traceEnd();
        }

        // 启动 CachedDeviceStateService 服务,用于追踪和缓存设备状态
        t.traceBegin("StartCachedDeviceStateService");
        mSystemServiceManager.startService(CachedDeviceStateService.class);
        t.traceEnd();

        // 启动 BinderCallsStatsService 服务,用于追踪在 binder 调用中花费的 cpu 时间
        t.traceBegin("StartBinderCallsStatsService");
        mSystemServiceManager.startService(BinderCallsStatsService.LifeCycle.class);
        t.traceEnd();

        // 启动 LooperStatsService 服务,用于追踪在处理程序中处理消息所花费的时间
        t.traceBegin("StartLooperStatsService");
        mSystemServiceManager.startService(LooperStatsService.Lifecycle.class);
        t.traceEnd();

        // 启动 RollbackManagerService 服务,用于管理 apk 安装包的回滚
        t.traceBegin("StartRollbackManagerService");
        mSystemServiceManager.startService(ROLLBACK_MANAGER_SERVICE_CLASS);
        t.traceEnd();

        // 启动 NativeTombstoneManagerService 服务,用于追踪 native tombstones
        t.traceBegin("StartNativeTombstoneManagerService");
        mSystemServiceManager.startService(NativeTombstoneManagerService.class);
        t.traceEnd();

        // 启动 BugreportManagerService 服务,用于捕获并报告 bug
        t.traceBegin("StartBugreportManagerService");
        mSystemServiceManager.startService(BugreportManagerService.class);
        t.traceEnd();

        // 启动 GPU 和 GPU 驱动服务,用于为 GPU 和 GPU 驱动程序提供服务
        t.traceBegin("GpuService");
        mSystemServiceManager.startService(GpuService.class);
        t.traceEnd();

        t.traceEnd(); // startCoreServices
    }
	......
}

该方法用于启动一些在启动引导服务过程中没有相互依赖的基本服务,如:SystemConfigService、BatteryService、BinderCallsStatsService、BugreportManagerService 等服务,这些服务很少或基本不依赖于别的服务。

3.5 SystemServer # startOtherServices()

xref: /frameworks/base/services/java/com/android/server/SystemServer.java

public final class SystemServer implements Dumpable {
	......
	private ContentResolver mContentResolver;
	......
	private void startOtherServices(@NonNull TimingsTraceAndSlog t) {
        t.traceBegin("startOtherServices");
        final Context context = mSystemContext;
        WindowManagerService wm = null;
        ......
        InputManagerService inputManager = null;
        ......
        try {
        	......
            t.traceBegin("StartKeyAttestationApplicationIdProviderService");
            ServiceManager.addService("sec_key_att_app_id_provider",
                    new KeyAttestationApplicationIdProviderService(context));
            ......
            mContentResolver = context.getContentResolver(); // 获取 ContentResolver 实例对象
            ...... // 安装 ContentProvider
        	mActivityManagerService.getContentProviderHelper().installSystemProviders();
        	......
            t.traceBegin("StartInputManagerService"); // 启动 InputManagerService 服务
        	inputManager = new InputManagerService(context);
        	......
        	t.traceBegin("StartWindowManagerService"); // 启动 WindowManagerService 服务
        	mSystemServiceManager.startBootPhase(t, SystemService.PHASE_WAIT_FOR_SENSOR_SERVICE);
        	wm = WindowManagerService.main(context, inputManager, !mFirstBoot, mOnlyCore,
                	new PhoneWindowManager(), mActivityManagerService.mActivityTaskManager);
        	ServiceManager.addService(Context.WINDOW_SERVICE, wm, /* allowIsolated= */ false,
                	DUMP_FLAG_PRIORITY_CRITICAL | DUMP_FLAG_PROTO);
        	ServiceManager.addService(Context.INPUT_SERVICE, inputManager,
                	/* allowIsolated= */ false, DUMP_FLAG_PRIORITY_CRITICAL);
        	t.traceBegin("SetWindowManagerService"); // ActivityManagerService 设置 WindowManagerService
        	mActivityManagerService.setWindowManager(wm);
			......
        } catch (Throwable e) {
        	......// 日志输出并抛出异常
        }
        ......
        t.traceBegin("MakeDisplayReady");
        try {
            wm.displayReady();
        } catch (Throwable e) {
            reportWtf("making display ready", e);
        }
        t.traceEnd();
        ......
        t.traceBegin("MakeInputManagerServiceReady");
        try {
            if (inputManagerF != null) {
                inputManagerF.systemRunning();
            }
        } catch (Throwable e) {
            reportWtf("Notifying InputManagerService running", e);
        }
        ......
        // 准备好上面启动过的服务,如 WMS、PMS、DMS等
        t.traceBegin("MakeWindowManagerServiceReady");
        try {
            wm.systemReady();
        } catch (Throwable e) {
            reportWtf("making Window Manager Service ready", e);
        }
        mActivityManagerService.systemReady(() -> {
        	Slog.i(TAG, "Making services ready");
        	
        }, t);
        ......
		t.traceEnd(); // startOtherServices
    }
	......
}

该方法代码太多,主要是启动一些非紧要和不需要立即启动的服务,如:CameraService、AlarmManagerService、InputManagerService、WindowManagerService、…、AndioServcie 等,然后准备好这些启动过的服务,等待后续客户端的调用。


三、SystemServer 启动的服务及其作用

在 system_server 进程启动中,将系统服务分为三大类:引导服务核心服务其他服务。下面简单的罗列下这些在 Android 系统中常见的服务及其作用。

1、引导服务

Installer :系统安装 APK 时的一个服务类,启动完成 Installer 服务之后才能启动其他的系统服务
ActivityManagerService :负责四大组件的启动、切换、调度
PowerManagerService :计算系统中与 Power 相关的计算,然后决策系统应该如何反应
LightsService :管理和显示背光 LED
DisplayManagerService :用来管理所有显示设备
UserManagerService :多用户模式管理
SensorService :为系统提供各种感应器服务
PackageManagerService :对 APK 进行安装、解析、删除、卸载等操作
等等

2、核心服务

DropBoxManagerService:用于生成和管理系统运行时的一些日志文件
BatteryService:管理电池相关的服务
UsageStatsService:收集用户使用每一个 App 的频率、使用时长
WebViewUpdateService:WebView 更新服务
等等

3、其他服务

CameraService:摄像头相关服务
AlarmManagerService:全局定时器管理服务
InputManagerService:管理输入事件
WindowManagerService:窗口管理服务
VrManagerService:VR模式管理服务
BluetoothService:蓝牙管理服务
LocationManagerService:定位管理服务,GPS、定位等
AndioServcie:音频相关管理服务
LockSettingsService:屏幕锁定服务,管理每个用户的相关锁屏信息
DeviceIdleController:Doze模式的主要驱动
DevicePolicyManagerService:提供一些系统级别的设置及属性
StatusBarManagerService:状态栏管理服务
ClipboardService:系统剪切板服务
NetworkManagementService:网络管理服务
TextServicesManagerService:文本服务,例如文本检查等
NetworkScoreService:网络评分服务
NetworkStatsService:网络状态服务
NetworkPolicyManagerService:网络策略服务
WifiP2pService:Wifi Direct服务
WifiService:Wifi服务
WifiScanningService:Wifi扫描服务
RttService:Wifi相关
EthernetService:以太网服务
ConnectivityService:网络连接管理服务
NsdService:网络发现服务
NotificationManagerService:通知栏管理服务
DeviceStorageMonitorService:磁盘空间状态检测服务
CountryDetectorService:检测用户国家
SearchManagerService:搜索管理服务
DropBoxManagerService:用于系统运行时日志的存储于管理
WallpaperManagerService:壁纸管理服务
AudioService:AudioFlinger的上层管理封装,主要是音量、音效、声道及铃声等的管理
DockObserver:如果系统有个座子,当手机装上或拔出这个座子的话,就得靠他来管理了
WiredAccessoryManager:监视手机和底座上的耳机
UsbService:USB服务
SerialService:串口服务
TwilightService:指出用户当前所在位置是否为晚上,被 UiModeManager 等用来调整夜间模式
BackupManagerService:备份服务
AppWidgetService:提供Widget的管理和相关服务
VoiceInteractionManagerService:语音交互管理服务
DiskStatsService:磁盘统计服务,供dumpsys使用
SamplingProfilerService:用于耗时统计等
NetworkTimeUpdateService:监视网络时间,当网络时间变化时更新本地时间。
CertBlacklister:提供一种机制更新SSL certificate blacklist
DreamManagerService:屏幕保护
PrintManagerService:打印服务
HdmiControlService:HDMI控制服务
FingerprintService:指纹服务
等等


总结

SystemServer 进程是 Zygote 启动后 fork 出的第一个进程,其本质是通过 Linux 的 fork() 系统调用来创建的。SystemServer 进程在启动过程中,先初始化系统变量、加载系统类库、创建 Context 上线文对象等。然后创建 SystemServiceManager 对象用于对系统的服务进程创建、启动和生命周期管理。之后通过 SystemServiceManager 启动系统中的引导服务、核心服务和其它服务。

注意SystemServer 在启动服务前,会尝试与 Zygote 建立 Socket 通信,通信成功后才去启动服务,且启动的服务都单独运行在SystemServer 的各自线程中,同属于 SystemServer 进程。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1209830.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu 17.10 “Artful Aardvark” 发布首个 Beta

Ubuntu 17.10 “Artful Aardvark” 首个 Beta 版已发布。 按照 Ubuntu 17.10 的发布日程 &#xff0c;Ubuntu 17.10 首个 beta 版按时发布了。不过参与本次测试版的没有 Ubuntu 官方风味版本&#xff08;要尝试的话可以考虑每日构建 ISO&#xff09;&#xff0c;包括了 Kubunt…

MySQL学习day02

一、SQL通用语法 1&#xff09;SQL语句可以单行或多行书写&#xff0c;以分号结尾 2&#xff09;SQL语句可以使用空格/缩进来增强语句的可读性 3&#xff09;MySQL数据库的SQL语句不区分大小写&#xff0c;关键字建议使用大写 4&#xff09;注释&#xff1a; a)单行注释&#x…

Day30力扣打卡

打卡记录 最长回文子序列&#xff08;区间DP&#xff09; 链接 class Solution:def longestPalindromeSubseq(self, s: str) -> int:n len(s)f [[0] * n for _ in range(n)]max lambda x, y: x if x > y else yfor i in range(n - 1, -1, -1):f[i][i] 1for j in ra…

leetcode二分查找算法题

目录 1.二分查找2.在排序数组中查找元素的第一个和最后一个位置3.x的平方根4.搜索插入位置5.山脉数组的峰顶索引6. 寻找峰值7.寻找旋转排序数组中的最小值8.8.0~n-1中缺失的数字 1.二分查找 二分查找 class Solution { public:int search(vector<int>& nums, int …

掉瓶子小游戏

欢迎来到程序小院 掉瓶子 玩法&#xff1a;旋转的瓶子&#xff0c;根据瓶子方向&#xff0c;点击鼠标左键瓶子掉落&#xff0c;从桌面中间掉下即得1分&#xff0c;卡在桌边瓶子碎了游戏结束&#xff0c;快去掉瓶子吧^^。开始游戏https://www.ormcc.com/play/gameStart/203 htm…

第1关:简单查询

任务描述相关知识 检索数据表的内容编程要求测试说明 任务描述 本关任务&#xff1a; 用 SELECT 语句检索数据表中指定字段的数据&#xff1b; 用 SELECT 语句检索数据表中所有字段的数据。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;1.如何获取数据表…

从0到0.01入门 Webpack| 001.精选 Webpack面试题

&#x1f90d; 前端开发工程师&#xff08;主业&#xff09;、技术博主&#xff08;副业&#xff09;、已过CET6 &#x1f368; 阿珊和她的猫_CSDN个人主页 &#x1f560; 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 &#x1f35a; 蓝桥云课签约作者、已在蓝桥云…

深度学习 植物识别算法系统 计算机竞赛

文章目录 0 前言2 相关技术2.1 VGG-Net模型2.2 VGG-Net在植物识别的优势(1) 卷积核&#xff0c;池化核大小固定(2) 特征提取更全面(3) 网络训练误差收敛速度较快 3 VGG-Net的搭建3.1 Tornado简介(1) 优势(2) 关键代码 4 Inception V3 神经网络4.1 网络结构 5 开始训练5.1 数据集…

Python基础入门----使用Pipenv工具时产生的Pipfile和Pipfile.lock文件有什么区别以及有什么作用

文章目录 PipfilePipfile.lock实操示例当我们使用 Pipenv 工具进行 Python 项目的依赖管理时,会遇到两个重要的文件:Pipfile 和 Pipfile.lock。这两个文件在项目中扮演着不同但又相互补充的角色。接下来,我将详细介绍这两个文件的区别和作用,并提供一些具体的使用示例。 P…

机器视觉系统中工业光源选型避坑指南

光源的作用&#xff1a; 照亮目标&#xff0c;提高目标亮度 形成有利于图像处理的效果&#xff0c;提升对比度 克服环境光干扰&#xff0c;保证图像的稳定性 光源的选型思路&#xff1a; ①颜色 ②外形  ③打光方式  ④亮度 选颜色 通过选择合适颜色的光源&#xff0c;…

城市内涝对策,万宾科技内涝积水监测仪使用效果

随着城市化进程的加速&#xff0c;城市道路积水问题明显越来越多&#xff0c;给人们的出行和生活带来更多的不便。内涝积水监测仪作为高科技产品能够实时监测道路积水情况&#xff0c;为城市排水系统的管理和维护提供重要的帮助。 在城市生命线的基础设施规划之中&#xff0c;地…

(论文阅读32/100)Flowing convnets for human pose estimation in videos

32.文献阅读笔记 简介 题目 Flowing convnets for human pose estimation in videos 作者 Tomas Pfister, James Charles, and Andrew Zisserman, ICCV, 2015. 原文链接 https://arxiv.org/pdf/1506.02897.pdf 关键词 Human Pose Estimation in Videos 研究问题 视频…

并发编程由浅及深(一)

并发编程重要吗&#xff1f;当然重要&#xff0c;因为并发在我们的项目中真实存在&#xff0c;如果你不能充分了解它那么很可能造成严重的生产事故。最近隔壁项目组出了一个问题&#xff0c;每次请求接口之后都发现线程固定增加了5个&#xff0c;而且线程数一直增加没有减少&am…

【Java笔试强训】Day11(CM24 最近公共祖先、HJ86 求最大连续bit数)

CM24 最近公共祖先 链接&#xff1a;最近公共祖先 题目&#xff1a; 将一棵无穷大满二叉树的结点按根结点一层一层地从左往右编号&#xff0c;根结点编号为1。现给定a&#xff0c;b为两个结点。设计一个算法&#xff0c;返回a、b最近的公共祖先的编号。注意其祖先也可能是结…

CodeWhisperer 使用经验分享

今天给大家分享一下 Amazon CodeWhisperer 编程工具&#xff08;免费哦&#xff09;&#xff0c;使用这个软件后我的编码质量提升不少&#xff0c;给大家分享一下我的经验。希望大家支持哦。 Amazon CodeWhisperer 是亚⻢逊出品的一款基于机器学习的 AI 编程助手&#xff0c;可…

No210.精选前端面试题,享受每天的挑战和学习

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云课上架的前后端实战课程《Vue.js 和 Egg.js 开发企业级健康管理项目》、《带你从入…

软件测试/测试开发丨​利用人工智能ChatGPT批量生成测试数据

点此获取更多相关资料 简介 测试数据是指一组专注于为测试服务的数据&#xff0c;既可以作为功能的输入去验证输出&#xff0c;也可以去触发各类异常场景。 测试数据的设计尤为重要&#xff0c;等价类、边界值、正交法等测试用例设计方法都是为了更全面地设计对应的测试数据…

大数据Doris(二十二):数据查看导入

文章目录 数据查看导入 数据查看导入 Broker load 导入方式由于是异步的,所以用户必须将创建导入的 Label 记录,并且在查看导入命令中使用 Label 来查看导入结果。查看导入命令在所有导入方式中是通用的,具体语法可执行 HELP SHOW LOAD 查看。 show load order by create…

三大开源向量数据库大比拼

向量数据库具有一系列广泛的好处&#xff0c;特别是在生成式人工智能方面&#xff0c;更具体地说&#xff0c;是在大语言模型&#xff08;LLM&#xff09;方面。这些好处包括先进的索引和精确的相似度搜索&#xff0c;有助于交付强大的先进项目。 本文将对三种开源向量数据库&…

快照snapshot要点记录

目录 COW快照ROW快照 snapshot&#xff1a;快照 快照分为&#xff1a;COW快照、ROW快照 COW&#xff1a;Copy On Write 指写前复制技术 ROW&#xff1a;Redirect On Write 指写时重定向技术 COW快照 性能无法达到最高&#xff0c;因为每次都要与COW共享映射表进行比对。存储中…