Android系统启动(三) — SystemServer处理过程

news2025/1/15 12:51:02

system_server 进程主要是用于创建系统服务,AMSWMSPMS 都是由它创建的。 具体来说,SystemServer 进程被创建后,主要做了以下工作:

  • 启动 Binder 线程池,这样就可以与其他进程进行通信;
  • 创建 SystemServiceManager,用于对系统服务进行创建、启动和生命周期管理;
  • 启动各种系统服务;

1 Zygote 处理 system_server 进程

在 Zygote进程启动过程 中讲到 ,在 ZygoteInit.main 方法中,通过调用 forkSystemServer 方法启动 system_server 进程,一些相关时序图:

图1

ZygoteInit.forkSystemServer 代码如下所示:

// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static Runnable forkSystemServer(String abiList, String socketName, 
                                         ZygoteServer zygoteServer) {
    ...
    /* For child process 当前运行在 system_server 进程中 */
    if (pid == 0) {
        if (hasSecondZygote(abiList)) {
            waitForSecondaryZygote(socketName);
        }
		// 关闭 Zygote 进程创建的 Socket
        zygoteServer.closeServerSocket(); // 1
        return handleSystemServerProcess(parsedArgs); // 2
    }

    return null;
}

system_server 进程复制了 Zygote 进程的地址空间,因此也会得到 Zygote 进程创建的 Socket,这个 Socket 对于 system_server 进程没有任何用处,因此,需要在注释 1 处关闭 Socket 接着,在注释 2 处调用 handleSystemServerProcess 方法来启动 system_server 进程。handleSystemServerProcess 方法的代码如下所示:

// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
private static Runnable handleSystemServerProcess(ZygoteArguments parsedArgs) {
    ...
    if (parsedArgs.mInvokeWith != null) {
        ...
    } else {
        createSystemServerClassLoader(); // 1
        ClassLoader cl = sCachedSystemServerClassLoader;
        if (cl != null) {
            Thread.currentThread().setContextClassLoader(cl);
        }

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

private static void createSystemServerClassLoader() {
    if (sCachedSystemServerClassLoader != null) {
        return;
    }
    final String systemServerClasspath = Os.getenv("SYSTEMSERVERCLASSPATH");
    // TODO: Should we run optimization here?
    if (systemServerClasspath != null) {
        sCachedSystemServerClassLoader = createPathClassLoader(
            systemServerClasspath, VMRuntime.SDK_VERSION_CUR_DEVELOPMENT);
    }
}

在注释 1 处创建了 ClassLoader。在注释 2 处调用了 ZygoteInit.zygoteInit 方法,代码如下所示:

// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static final Runnable zygoteInit(int targetSdkVersion, String[] argv,
                                        ClassLoader classLoader) {
    if (RuntimeInit.DEBUG) {
        Slog.d(RuntimeInit.TAG, "RuntimeInit: Starting application from zygote");
    }

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

    RuntimeInit.commonInit();
    // 启动 Binder 线程池
    ZygoteInit.nativeZygoteInit(); // 1
    // 进入 system_server 的 main 方法
    return RuntimeInit.applicationInit(targetSdkVersion, argv, classLoader); // 2
}

在注释 1 处调用 ZygoteInit.nativeZygoteInit 方法,此处调用的是 Native 层的代码,用来启动 Binder 线程池,这样 ,system_server 进程就可以使用 Binder 与其他进程进行通信。注释 2 处是用于进入 system_servermain 方法。

以下分别说明

1 启动 Binder 线程池

ZygoteInit.nativeZygoteInit() 是一个 Native 方法,首先要了解它对应的 JNI 文件,如下所示:

// /frameworks/base/core/jni/AndroidRuntime.cpp
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));
}

通过 JNImethods 数组,可以看出 nativeZygoteInit 方法对应的是 JNI 文件 AndroidRuntime.cppcom_android_internal_os_ZygoteInit_nativeZygoteInit 函数:

// /frameworks/base/core/jni/AndroidRuntime.cpp
static void com_android_internal_os_ZygoteInit_nativeZygoteInit(JNIEnv* env, jobject clazz)
{
    gCurRuntime->onZygoteInit();
}

gCurRuntimeAndroidRuntime 类型的指针,具体指向的是 AndroidRuntime 的子类 AppRuntime,在 app_main.cpp 中定义。接着来看 AppRuntime.onZygoteInit 方法,代码如下所示:

// /frameworks/base/cmds/app_process/app_main.cpp
virtual void onZygoteInit()
{
    sp<ProcessState> proc = ProcessState::self();
    ALOGV("App process: starting thread pool.\n");
    proc->startThreadPool(); // 1
}

注释 1 处的代码用来启动一个 Binder 线程池,这样 system_server 进程就可以使用 Binder 与其他进程通信了。因此,从这里可以知道 ZygoteInit.nativeZygoteInit() 函数主要是用来启动 Binder 线程池的。

2 进入 SystemServer.main 方法

查看 RuntimeInit.applicationInit 方法的源代码:

// /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable applicationInit(int targetSdkVersion, String[] argv,
                                          ClassLoader classLoader) {
    ...
    // Remaining arguments are passed to the start class's static main
    return findStaticMain(args.startClass, args.startArgs, classLoader);
}

RuntimeInit.applicationInit 方法中主要调用了 findStaticMain 方法:

// /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
protected static Runnable findStaticMain(String className, String[] argv,
                                         ClassLoader classLoader) {
    Class<?> cl;

    try {
        // 通过反射得到 SystemServer 类
        cl = Class.forName(className, true, classLoader); // 1
    } 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 }); // 2
    } catch (NoSuchMethodException ex) {
        throw new RuntimeException(
            "Missing static main on " + className, ex);
    } catch (SecurityException ex) {
        throw new RuntimeException(
            "Problem getting static main on " + className, ex);
    }

    int modifiers = m.getModifiers();
    if (! (Modifier.isStatic(modifiers) && Modifier.isPublic(modifiers))) {
        throw new RuntimeException(
            "Main method is not public and static on " + className);
    }

    
    return new MethodAndArgsCaller(m, argv); // 3
}

注释 1 处的 classNamecom.android.server.SystemServer,通过反射返回的 clSystemServer 类。在注释 2 处找到 SystemServer.main 方法。在注释 3 处将找到的 main 方法传入到 MethodAndArgsCaller 中。

// /frameworks/base/core/java/com/android/internal/os/ZygoteInit.java
public static void main(String argv[]) {
    ...
    try {
        ...
        if (startSystemServer) {
            Runnable r = forkSystemServer(abiList, zygoteSocketName, zygoteServer);

            // {@code r == null} in the parent (zygote) process, and {@code r != null} in the child (system_server) process.
            if (r != null) {
                r.run(); // 1
                return;
            }
        }
        ...
    } catch (Throwable ex) {
        Log.e(TAG, "System zygote died with exception", ex);
        throw ex;
    } finally {
        if (zygoteServer != null) {
            zygoteServer.closeServerSocket();
        }
    }
	...
}

通过注释 1 处的代码可以知道,在 ZygoteInit.main 方法中会获取 MethodAndArgsCaller 对象,并调用 MethodAndArgsCaller.run() 方法。MethodAndArgsCallerZygote 的静态内部类:

// /frameworks/base/core/java/com/android/internal/os/RuntimeInit.java
static class MethodAndArgsCaller implements Runnable {
    /** method to call */
    private final Method mMethod;

    /** argument array */
    private final String[] mArgs;

    public MethodAndArgsCaller(Method method, String[] args) {
        mMethod = method;
        mArgs = args;
    }

    public void run() {
        try {
            mMethod.invoke(null, new Object[] { mArgs }); // 1
        } 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);
        }
    }
}

注释 1 处的 mMethod 指的是 SystemServer.main 方法,调用了 mMethod.invoke 方法后,SystemServer.main 方法也会被动态调用。

2 解析 system_server 进程

以下是 SystemServer.main 方法:

// /frameworks/base/services/java/com/android/server/SystemServer.java 
public static void main(String[] args) {
    new SystemServer().run();
}

SystemServer.main 方法中只调用了 SystemServer().run() 方法:

// /frameworks/base/services/java/com/android/server/SystemServer.java 
private void run() {
    try {
        ...
        // 创建消息 Looper
        Looper.prepareMainLooper();
        Looper.getMainLooper().setSlowLogThresholdMs(
            SLOW_DISPATCH_THRESHOLD_MS, SLOW_DELIVERY_THRESHOLD_MS);

        // Initialize native services. 加载了动态库 libandroid_servers.so
        System.loadLibrary("android_servers"); // 1
		...
        // Initialize the system context. 创建系统的 Context
        createSystemContext();

        // Create the system service manager.
        mSystemServiceManager = new SystemServiceManager(mSystemContext); // 2
        mSystemServiceManager.setStartInfo(mRuntimeRestart, mRuntimeStartElapsedTime, 
                                           mRuntimeStartUptime);
        LocalServices.addService(SystemServiceManager.class, mSystemServiceManager);
        // Prepare the thread pool for init tasks that can be parallelized
        SystemServerInitThreadPool.get();
    } finally {
        traceEnd();  // InitBeforeStartServices
    }

    // Start services.
    try {
        traceBeginAndSlog("StartServices");
        startBootstrapServices(); // 3 启动引导服务
        startCoreServices(); // 4 启动核心服务
        startOtherServices(); // 5 启动其他服务
        SystemServerInitThreadPool.shutdown();
    } catch (Throwable ex) {
        Slog.e("System", "******************************************");
        Slog.e("System", "************ Failure starting system services", ex);
        throw ex;
    } finally {
        traceEnd();
    }

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

在注释 1 加载了动态库 libandroid_servers.so。在注释 2 处创建 SystemServiceManager,她会对系统服务进行创建、启动和生命周期管理。在注释 3 处的 startBootstrapServices() 方法中回用 SystemServiceManager 启动 ActivityManagerServicePowerManagerServicePackageManagerService 等服务。在注释 4 处的 startCoreServices() 方法中则启动 DropBoxManagerServiceBatteryServiceUsageStateServiceWebViewUpdateService。在注释 5 处的 startOtherServices() 方法中启动了 CameraServiceAlarmManagerServiceVrManagerService 等服务。

从注释 345 处可以 看出, 官方把系统服务分为三种类型,分别是引导服务、核心服务和其他服务,其中,其他服务是一些非要紧的和不需要立即启动的服务。 系统服务总共 100 多个,以下是其中的部分服务:

图2

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

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

相关文章

JDK9下载、安装和配置环境变量图解

下载 1.输入&#xff1a;https://www.oracle.com/ 2.选择“java download” 3.点击“java archive” 下拉找到 java9 4.点击进入&#xff0c;选择windows版本 5.勾选&#xff0c;下载。需要账号下载 安装 1.双击安装包&#xff0c;下一步 2.选择安装路径&#xff0c;…

旅游景区官网(网站、小程序)小开发可以实现哪些功能?

伴随着我们生活水平的提升和手上的余钱愈来愈多&#xff0c;绝大多数人一定会选取去不同地方开展旅游&#xff0c;旅游也成為了经济发展的一大支撑。将来便捷用户和旅游业的发展趋势&#xff0c;打造出旅游景区官网&#xff08;网站、H5、小程序等&#xff09;开发设计是十分关…

【UE4 第一人称射击游戏】50-用另一种方法实现僵尸随机漫游 僵尸攻击玩家时造成伤害

上一篇&#xff1a;【UE4 第一人称射击游戏】49-僵尸攻击动画本篇效果&#xff1a;使用另一种逻辑实现了僵尸的随机漫游僵尸攻击玩家时会对玩家造成实质上的伤害步骤&#xff1a;打开“SimpleAI”&#xff0c;当僵尸看见玩家时&#xff0c;设置变量“CanSeePlayer”为False我们…

深入了解 LinkedBlockingQueue阻塞队列,分析扩容机制以及小顶堆原理

1. 前言 今天的目的是为了深入了解下优先队列的机制。不过优先队列是基于大小顶堆实现的&#xff0c;但是其本质就是一个二叉树&#xff0c;所以今天会讲一些铺垫知识&#xff0c;好了&#xff0c;废话不多说了&#xff0c;让我们开始吧 2. 前置知识 2.1 大顶堆 完全二叉树&am…

1.2、操作系统的特征

1、并发 并发\color{red}并发并发&#xff1a;指两个或多个事件在同一时间间隔内发生。 这些事件宏观上是同时发生\color{red}宏观上是同时发生宏观上是同时发生的&#xff0c;但微观上是交替发生\color{red}微观上是交替发生微观上是交替发生的。 并行\color{red}并行并行&am…

STM32F103学习笔记(10)——I2C多路复用器TCA9548A使用

一、简介 TCA9548A 器件配有八个可通过 I2C 总线控制的双向转换开关。串行时钟/串行数据 (SCL/SDA) 上行对可扩展为 8 个下行对或通道。根据可编程控制寄存器的内容&#xff0c;可选择任一单独 SCn/SDn 通道或者通道组合。这些下游通道可用于解决 I2C 从器件地址冲突。例如&…

高精度加法【c++实现】超详细讲解

高精度存在的意义 大家一定都知道int和long long是有极限的&#xff08;如下表&#xff09;&#xff0c;如果超了就无法计算正确结果了&#xff0c;那该用什么方法来计算呢&#xff1f;这就是我们今天要说的算法———高精度算法。&#xff08;本文只讲加法&#xff09; 类型…

超级浏览器的防关联效果怎么样?

很多从事跨境电商业务的朋友&#xff0c;都尝试用各种手段来防止账号关联&#xff0c;现在有很多不要钱的超级浏览器可以下载使用&#xff0c;但是很多人却不敢把高价值的账号放在超级浏览器上面&#xff0c;今天我们就来详细聊聊这个问题。说超级浏览器之前&#xff0c;我们先…

抖音世界杯直播的低延迟是怎么做到的?

动手点关注干货不迷路世界杯已经结束了&#xff0c;梅西带领阿根廷时隔三十六年之后终于如愿捧杯。抖音直播提供的 4K 超高清超低延迟看播能力给亿万观众留下了深刻的印象&#xff0c;决赛的 PCU 达到 3700w&#xff0c;在这样大规模并发下&#xff0c;如何能稳定流畅地做到更低…

GO语言配置和基础语法应用(一)

一、golang的下载和安装 这一步比较简单&#xff0c;直接打开go的官网&#xff0c;点击download即可&#xff0c;个别人打开慢可以用中国的镜像网站&#xff0c;之后访问的速度和下载第三方库的速度会快很多&#xff0c;之后傻瓜式安装一路到底即可。 配置环境变量 注意&#…

经典文献阅读之--Multi-modal Semantic SLAM(多模态语义SLAM)

0. 简介 在复杂动态环境下&#xff0c;如何去建立一个稳定的SLAM地图是至关重要的。但是现在当前的SLAM系统主要是面向静态场景。目前相较于点云的分类与分割而言。视觉的识别与分割会更加容易。这就可以根据语义信息提高对环境的理解。文章《Multi-modal Semantic SLAM for C…

JavaScript 如何正确的读懂报错信息

文章目录前言一、查看报错1.控制台报错2.终端报错二、查找错误演示总结前言 一、查看报错 如何阅读报错信息, 根据信息快速锁定错误. 1.控制台报错 红色报错信息格式: xxxx Error: xxxxx报错信息xxxxx 最终报错文件:行编号 at 最终报错方法名 (最终报错文…

PySpark中RDD的数据输出详解

目录 一. 回顾 二.输出为python对象 collect算子 演示 reduce算子 演示 take算子 演示 count算子 演示 小结 三.输出到文件中 savaAsTextFile算子 演示 配置Hadoop依赖 修改rdd分区为1个 小结 四.练习案例 需求&#xff1a; 代码 一. 回顾 数据输入: sc.paralle…

Transformer-XL: Attentive Language Models Beyond a Fixed-Length Context_学习笔记

Transformer-XL学习笔记 一、Transformer-XL出现的原因 首先说明Transformer的变形版本Transformer-XL出现的原因&#xff1a; transformer作为一种特提取器&#xff0c;在NLP中有广泛的应用&#xff0c;但是transformer需要对输入的序列设置固定的长度&#xff0c;例如在Ber…

(考研湖科大教书匠计算机网络)第一章概述-第四节:计算机网络的性能指标

文章目录&#xff08;1&#xff09;速率&#xff08;2&#xff09;带宽&#xff08;3&#xff09;吞吐量&#xff08;4&#xff09;时延①&#xff1a;基本概念②&#xff1a;计算公式&#xff08;5&#xff09;时延带宽积&#xff08;6&#xff09;往返时间RTT&#xff08;7&a…

dp(六) 线性dp整合 最长(公共子串、公共子序列、上升子序列、回文子串)

1、最大公共子串_牛客题霸_牛客网​编辑 2、最长上升子序列(一)_牛客题霸_牛客网 3、最长回文子串_牛客题霸_牛客网 4、最长公共子序列(二)_牛客题霸_牛客网 #include <iostream> using namespace std; #include<vector>int main() {string str1,str2;cin>>…

mysql数据迁移报错问题

mysql8.0.17备份数据库到mysql5.7.26的There was error(s) while executing the queries问题解决&#xff08;数据库高版本向低版本数据迁移解决&#xff09; 问题背景 要将本地的mysql数据库导入到linux中的mysql中&#xff0c;其中&#xff0c;本地mysql数据库的版本是8.0.…

数字硬件建模SystemVerilog-时序逻辑建模(1)RTL时序逻辑的综合要求

数字门级电路可分为两大类&#xff1a;组合逻辑和时序逻辑。锁存器是组合逻辑和时序逻辑的一个交叉点&#xff0c;在后面会作为单独的主题处理。组合逻辑描述了门级电路&#xff0c;其中逻辑块的输出直接反映到该块的输入值的组合&#xff0c;例如&#xff0c;双输入AND门的输出…

N5247A网络分析仪

18320918653 N5247A Agilent N5247A 网络分析仪主要特性与技术指标 10 MHz 至 67 GHz2 端口或 4 端口&#xff0c;具有两个内置信号源可提供 4 端口 110 GHz 单次扫描解决方案110 dB 系统动态范围&#xff0c;32001 个点&#xff0c;32 个通道&#xff0c;5 MHz 中频带宽高输…

MySQL中深入浅出索引

文章目录前言一、索引的常见模型二、InnoDB的索引模型三、索引的维护四、索引的优化覆盖索引联合索引最左前缀原则索引下推前言 我们在看书的时候&#xff0c;打算回看某一个桥段的内容时。这是你肯定会是先翻看书的目录&#xff0c;从目录确定这段内容的位置&#xff0c;然后…