深入Android S(12.0) 探索 Android Framework 之 SystemServer 进程启动详解

news2024/11/26 12:20:07

深入学习 Android Framework

第三:深入Android S(12.0) 探索 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/1219331.html

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

相关文章

草图大师SketchUp Pro 2023

SketchUp Pro 2023 for Mac&#xff08;草图大师&#xff09;是一款三维建模软件&#xff0c;由Trimble Inc.开发。它可以用于创建、修改和分享3D模型&#xff0c;包括建筑、家具、景观等。 SketchUp Pro 2023 for Mac提供了简单易学的用户界面和强大的工具集&#xff0c;使用…

数据库表数据类型datetime 和 timestamp区别,以及优缺点

datetime和timestamp都是用于表示日期和时间的数据类型&#xff0c;但它们在存储和使用上有一些区别。 数据范围&#xff1a;datetime数据类型的有效范围是从1000年到9999年&#xff0c;精度为秒。timestamp数据类型的有效范围是从1970年到2038年&#xff0c;精度为秒。存储空…

element-china-area-data插件vue3做省市区的下拉选择,用3个独立的el-select实现

第1版&#xff0c;选择下拉没有优化 第2版&#xff0c;选择下拉时&#xff0c;做了优化

<蓝桥杯软件赛>零基础备赛20周--第6周--数组和队列

报名明年4月蓝桥杯软件赛的同学们&#xff0c;如果你是大一零基础&#xff0c;目前懵懂中&#xff0c;不知该怎么办&#xff0c;可以看看本博客系列&#xff1a;备赛20周合集 20周的完整安排请点击&#xff1a;20周计划 每周发1个博客&#xff0c;共20周&#xff08;读者可以按…

SystemVerilog学习 (10)——线程控制

一、概述 在实际硬件中,时序逻辑通过时钟沿来激活,组合逻辑的输出则随着输人的变化而变化。所有这些并发的活动在Verilog 的寄存器传输级上是通过initial和 always块语句、实例化和连续赋值语句来模拟的。为了模拟和检验这些语句块,测试平台使用许多并发执行的线程。在测试平台…

Python 集成 Nacos 配置中心

Python 集成 Nacos 配置中心 下载 Nacos 官方 pyhton 库 pip install nacos-sdk-python # 指定国内阿里云镜像源 pip3 install nacos-sdk-python -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com配置 Nacos 相关信息 Global:nacos:port: 8848…

线下保薪班开启

大家都知道我们有线上班&#xff0c;对于想技能提升的同学来说&#xff0c;线上足以满足技能提升需求&#xff0c;对于想转行找工作&#xff0c;或者学生想就业的同学来说&#xff0c;线上却并不是一个好的选择&#xff0c;担心的可能有:担心自身基础较弱怕学不懂&#xff0c;担…

一文搞懂 Prompt 编程

大家好&#xff0c;我是木川 一、什么是 Prompt 编程 Prompt 编程是一种基于自然语言处理的编程方式&#xff0c;属于一种创新的编程范式&#xff0c;通过向大模型提供 Prompt&#xff08;提示词&#xff09;&#xff0c;引导其生成特定的文本输出。 与传统的编码方式相比&…

开发知识点-Git

团队协作-Git Giteegitee 创建仓库打开项目所在目录&#xff0c;右键选择Git Bush Here(你要确定电脑上已经安装了Git&#xff09;初始化本地仓库配置验证信息。 完美解决github访问速度慢介绍Git 与 SVN 区别IDEA 添加 gitee Gitee Git Gitee 大家都知道国内访问 Github 速度…

简单认识泛型【java】

目录 1.什么是泛型 2.引出泛型 2.1语法 3. 泛型类的使用 3.1 语法 4 泛型如何编译的 4.1 擦除机制 5.泛型的上下界 5.1 语法 6.注意 1.什么是泛型 一般的类和方法&#xff0c;只能使用具体的类型: 要么是基本类型&#xff0c;要么是自定义的类。如果要编写可以应用于…

PS 吸管工具基本使用方法

这里 我们先打开PS软件 我们 在左侧 导航来中 找到 有吸管工具的这一组工具 这边 我们先选择这个 吸管工具 选择之后呢 左上角 属性配置 第一个是 取样大小 这个 我们之前学魔棒工具时 是有接触过的 这里 我们选择 取样点 然后 后面一个是样本 这个 用的最多的是 所有图层 …

postgresql:记录表膨胀引起的io问题的处理

文章目录 1. io异常2.查看profile报告2.1 生成事发时间段的pgprofile2.2 查看报告 3.检查table是否膨胀4.执行vacuum full5.总结 1. io异常 iostat -x 1 20 Device r/s w/s rkB/s wkB/s rrqm/s wrqm/s %rrqm %wrqm r_await w_await aqu-sz rareq…

【环境准备】NodeJs(压缩包版本)安装与配置

一、NodeJs(压缩包版本)安装与配置 1、下载、解压 访问 NodeJs官网,选择Window版本的.zip格式进行下载&#xff0c;下载完成后进行解压&#xff08;ps: 本人解压路径为D:\nodejs&#xff09; 2、 环境变量配置 配置环境变量&#xff0c;找到系统变量下的path并选中&#xf…

009.网络配置

Rocky Linux的定位是提供服务的网络型操作系统&#xff0c;所以为其配置完整的网络参数至关重要。通常&#xff0c;Linux可以通过两种方式为系统配置网络参数&#xff1a;一种是通过命令行配置&#xff0c;另一种是通过修改系统配置文件来配置。下面分别介绍这两种配置网络参数…

腾讯云服务器新用户优惠活动有哪些?腾讯云新用户优惠活动汇总

对于新用户来说&#xff0c;腾讯云服务器提供了许多优惠活动&#xff0c;让你享受到超值的优惠。下面我们就来一起看看&#xff0c;腾讯云服务器新用户优惠活动有哪些吧&#xff01; 1、腾讯云双十一领9999代金券&#xff08;https://1111.mian100.cn&#xff09; 腾讯云双十…

深度探讨丨关于工作量证明的常见误解

有一种基本误解认为&#xff0c;工作量证明机制在本质上是不可扩展的&#xff0c;并且会产生过度的能源耗费。 按照工作量证明区块链的最初设计&#xff0c;以及BSV区块链协会的推广&#xff0c;这一技术旨在实现可扩容性&#xff0c;同时确保高效能系统内的安全性和互操作性。…

调整Windows键盘上只能看到拼音而无法看到实际的文本以及关闭输入法悬浮窗方法

一、输入法设置 如果您在键盘上只能看到拼音而无法看到实际的文本&#xff0c;这可能是因为您的输入法设置为中文拼音输入法或其他仅显示拼音的输入法。 要解决这个问题&#xff0c;您可以尝试以下方法&#xff1a; 1. 切换输入法&#xff1a;按下 Shift Alt 组合键或 Wind…

yolo增加Inner-IoU,一文搞定(Inner-SIoU,Inner-WIoU,Inner-EIoU,Inner-MPDIoU)

论文&#xff1a;https://arxiv.org/pdf/2311.02877.pdf 简介 随着检测器的迅速发展, 边框回归取得了巨大的进步。然而&#xff0c;现有的基于 IoU 的边框回归仍聚焦在通过加入新的损失项来加速收敛&#xff0c;忽视 IoU 损失项其自身的限制。尽管理论上 IoU 损失能够有效描述…

linux systemd start stop enable disable命令区别

一、systemd 的服务在三个文件件下 /lib/systemd/system /etc/systemd/system /usr/lib/systemd/system 终于明白这几个命令的区别 systemd star systemd stop systemd enable systemd disable 二、 1、用ssh服务为例&#xff0c;&#xff0c;ssh是客户端&#xff0c;远程ss…

OCC教学:拓扑

拓扑&#xff1a;1.介绍 几何限制 OCCT 曲面支持矩形修剪。布尔运算后可能会出现非矩形域。 如何存储剪切操作的结果&#xff1f; 拓扑的目的 一般来说&#xff0c;拓扑是描述对象局限性的一种手段。 OCC拓扑被用于用于描述&#xff1a; 物体的边界&#xff1b;对象之…