一文学习Android系统核心服务ServiceManager

ServiceManager 是 Android 系统中核心的系统服务注册与发现机制,它在 Android Framework 层扮演服务注册中心的角色。它允许进程通过它注册、查询和使用系统服务,实现进程间通信 (IPC) 的基础架构。

ServiceManager 的作用

  1. 服务注册:应用程序或系统组件可以将一个 Binder 对象作为服务注册到 ServiceManager 中。
  2. 服务发现:客户端可以通过 ServiceManager 查询所需服务的 Binder 接口。
  3. IPC 中转:它为 Android 的 Binder IPC 提供了一个全局目录,用于绑定客户端和服务端。

在这里插入图片描述

工作原理

  1. ServiceManager 的启动
  • 在 Android 系统启动过程中,init 进程启动 servicemanager 可执行文件(实现是 C++ 代码)。
  • servicemanager 会在内核中注册为一个 Binder 服务,并接受来自其他进程的服务注册和查询请求。
  1. 服务注册
  • 服务端(通常是系统服务,如 ActivityManagerService)通过 addService() 方法向 ServiceManager 注册服务。
  • ServiceManager 将服务的名称与对应的 Binder 引用存储在内部表中。
  1. 服务查询
  • 客户端通过 getService() 方法向 ServiceManager 查询服务。
  • 如果服务存在,ServiceManager 返回对应的 Binder 引用;如果不存在,则客户端可以选择等待服务的注册。
  1. 服务使用
  • 客户端通过得到的 Binder 引用直接与服务端通信,不需要再经过 ServiceManager。

ServiceManager 的核心接口

1. 注册服务
IBinder myBinder = new MyBinder();
ServiceManager.addService("my_service_name", myBinder);
  • addService(String name, IBinder service) 方法用于将服务注册到 ServiceManager。
2. 查询服务
IBinder binder = ServiceManager.getService("my_service_name");
  • getService(String name) 方法用于根据服务名获取对应的 Binder 接口。
3. 列举所有服务
String[] serviceList = ServiceManager.listServices();
  • listServices() 方法返回当前已注册服务的名称列表。

ServiceManager 的架构图

+----------------+
|   Client App   |
+----------------+||  getService("service_name")v
+----------------+
| ServiceManager |
+----------------+||  addService("service_name", IBinder)v
+--------------------+
|  System Services   |
| (e.g., AMS, WMS)   |
+--------------------+

ServiceManager 的重要特点

  1. 全局唯一性:整个 Android 系统中只有一个 ServiceManager 实例,确保服务注册和查询的一致性。
  2. Binder 支持:作为 Android IPC 的核心机制,ServiceManager 利用 Binder 进行服务端和客户端的连接。
  3. 按需启动:只有当客户端尝试访问未启动的服务时,ServiceManager 会通知系统启动该服务。

源码分析

ServiceManager 的核心实现主要分为两个部分:

  1. Native 实现:通过 servicemanager 守护进程,用 C++ 实现。
    • 源码位置:frameworks/native/cmds/servicemanager/
  2. Java 层接口:提供给应用开发者使用的 ServiceManager 类。
    • 源码位置:frameworks/base/core/java/android/os/ServiceManager.java
示例代码

ServiceManager 的内部实现依赖于 Binder 机制:

// 注册服务
public static void addService(String name, IBinder service) {try {getIServiceManager().addService(name, service, false);} catch (RemoteException e) {throw e.rethrowFromSystemServer();}
}// 查询服务
public static IBinder getService(String name) {try {return getIServiceManager().getService(name);} catch (RemoteException e) {return null;}
}

总结

ServiceManager 是 Android 系统中连接系统服务与客户端的桥梁,其稳定性直接影响整个系统的运行。理解其工作机制有助于更深入地掌握 Android 的服务框架以及 IPC 的实现原理。

以下详细介绍下ServiceManager的启动过程

init 进程启动 servicemanager 的过程

init 是 Android 系统的第一个用户态进程,它的主要职责之一是启动系统所需的各种服务,包括 servicemanager。以下是 init 启动 servicemanager 的详细过程。

1. init 进程的角色

  • init 是 Android 的启动管理器,负责解析 init.rc 文件中的配置信息并启动所需服务。
  • servicemanager 是一个核心守护进程,通过 init.rc 的配置由 init 直接启动。

2. init.rc 文件的配置

servicemanager 的启动方式是在 Android 的 init.rc 文件中定义的。具体配置内容如下:

service servicemanager /system/bin/servicemanagerclass coreuser systemgroup systemcriticalonrestart restart zygote
配置说明:
  • service servicemanager:定义服务名称为 servicemanager。
  • /system/bin/servicemanager:指向 servicemanager 可执行文件的路径。
  • class core:表示这是一个核心服务,系统启动时优先运行。
  • user system:以 system 用户身份运行。
  • group system:属于 system 用户组。
  • critical:标记为关键服务,如果退出会触发系统重启。
  • onrestart restart zygote:如果 servicemanager 重启,zygote 也会随之重启。

3. 启动过程分析

步骤 1:init 进程启动
  • Android 启动时,内核加载并启动 init 进程。
  • init 进程会解析默认的 init.rc 文件。
步骤 2:解析 init.rc
  • init.rc 文件包含服务的启动定义,包括 servicemanager。
  • 当 init 遇到 service servicemanager 条目时,会按照配置创建并启动 servicemanager。
步骤 3:启动 servicemanager
  • init 使用以下步骤启动 servicemanager:Fork 一个新进程。在子进程中执行 /system/bin/servicemanager 二进制文件。配置进程的用户和组权限。
步骤 4:servicemanager 的初始化
  • servicemanager 启动后,完成以下任务:初始化 Binder 驱动并注册自己为 Binder 服务(BINDER_SERVICE_MANAGER)。开始监听客户端请求,处理服务注册和查询。

4. ServiceManager 初始化细节

/system/bin/servicemanager 的主要功能是初始化 Binder 并启动服务循环:

核心代码片段

servicemanager 的主要逻辑在 frameworks/native/cmds/servicemanager/ 中:

int main(int argc, char** argv) {sp proc = ProcessState::self();sp sm = new ServiceManager();// 注册自己为 BINDER_SERVICE_MANAGERproc->setContextObject(sm);// 启动 Binder 线程池proc->startThreadPool();// 等待客户端请求IPCThreadState::self()->joinThreadPool();return 0;
}
关键步骤:
  1. 创建 Binder 驱动实例
  • 通过 ProcessState::self() 获取 Binder 驱动的全局实例。
  1. 注册 ServiceManager
  • 使用 setContextObject() 将 ServiceManager 注册为 Binder 驱动的上下文对象。
  1. 启动线程池
  • 调用 startThreadPool() 开启 Binder IPC 线程池,准备处理请求。
  1. 进入服务循环
  • joinThreadPool() 方法阻塞进程,等待处理客户端的服务注册或查询请求。

5. 服务启动的完整时序图

+----------------+      +------------------+      +---------------------+
| Kernel         | ---> | init             | ---> | servicemanager      |
| (启动 init)    |      | (解析 init.rc)   |      | (启动并注册 Binder) |
+----------------+      +------------------+      +---------------------+1. Kernel 启动 init
2. init 解析 init.rc 文件
3. 根据 service 配置启动 /system/bin/servicemanager
4. servicemanager 初始化 Binder,并进入服务循环

总结

init 通过解析 init.rc 文件中的 service 配置来启动 servicemanager,这一过程奠定了 Android 服务架构的基础。作为系统服务的注册和发现中心,servicemanager 的启动是 Android 系统正常运行的重要环节。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DMA理论篇

DMA理论篇 简介 传统的数据传输都是需要CPU来实现,从一个地方拷贝到另一个地方;而DMA(Direct Memory Access)则不完全依赖CPU,DMA更新芯片SOC的一个控制器,他可以控制数据从内存中传输到另一个地方(外设、soc其它模块)&#xff…

SpringBoot 集成 html2Pdf

一、概述&#xff1a; 1. springboot如何生成pdf&#xff0c;接口可以预览可以下载 2. vue下载通过bold如何下载 3. 一些细节&#xff1a;页脚、页眉、水印、每一页得样式添加 二、直接上代码【主要是一个记录下次开发更快】 模板位置 1. 导入pom包 <dependency><g…

IDEA怎么定位java类所用maven依赖版本及引用位置

在实际开发中&#xff0c;我们可能会遇到需要搞清楚代码所用依赖版本号及引用位置的场景&#xff0c;便于排查问题&#xff0c;怎么通过IDEA实现呢&#xff1f; 可以在IDEA中打开项目&#xff0c;右键点击maven的pom.xml文件&#xff0c;或者在maven窗口下选中项目&#xff0c;…

webStorm安装

一、webStorm安装 简介 Webstorm是一款非常受欢迎的优秀开发工具&#xff0c;跟vscode同誉为卧龙凤雏编辑器&#xff0c;是97%开发人员的理想编辑器&#xff0c; 尤其是webstorm&#xff0c;焕然一新的外观&#xff0c;新的导航功能&#xff0c;githob拉取等&#xff0c;更是备…

案例研究|阿特斯的JumpServer分布式部署和多组织管理实践

苏州阿特斯阳光电力科技有限公司&#xff08;以下简称为阿特斯&#xff09;是一家集太阳能光伏组件制造和为全球客户提供太阳能应用产品研发、设计、制造、销售的专业公司。 阿特斯集团总部位于加拿大&#xff0c;中国区总部位于江苏省苏州市。通过全球战略和多元化的市场布局…

数字信号处理(Digital Signal Procession)总结

0、导入库 import numpy as np import matplotlib.pyplot as plt import numpy as np from matplotlib import pyplot as plt from scipy.signal import find_peaks1、创建时域信号 创建时间序列 T 0.01 # 采样间隔 fs 100 # 采样频率 L 1000 # 采样点数 tl 0 # 起始时间…

医院信息化与智能化系统(22)

医院信息化与智能化系统(22) 这里只描述对应过程&#xff0c;和可能遇到的问题及解决办法以及对应的参考链接&#xff0c;并不会直接每一步详细配置 如果你想通过文字描述或代码画流程图&#xff0c;可以试试PlantUML&#xff0c;告诉GPT你的文件结构&#xff0c;让他给你对应…

01Web3.0行业

目录 一、什么是Web 3.0? 二、Web 1.0 vs Web 2.0 vs Web 3.0 三、为什么选择Web 3.0 四、从法律角度观察Web 3.0 1. Web 3.0前时代的数字身份 问题1&#xff1a;个人信息的过度收集 问题2&#xff1a;个人信息的泄露和滥用 2. Web 3.0的解决方案及其法律问题 问题一&…

width设置100vh但出现横向滚动条的问题

在去做flex左右固定,中间自适应宽度的布局时, 发现这样一个问题: 就是我明明是宽度占据整个视口, 但是却多出了横向的滚动条 效果是这样的 把width改成100%,就没有滚动条了 原因: body是有默认样式的, 会有一定的默认边距, 把默认边距清除就是正常的了 同时, 如果把高度设…

opencv undefined reference to `cv::noarray()‘ 。window系统配置opencv,找到opencv库,但连接不了

之前都是在ubuntu里用opencv&#xff0c;今天为了方便在平时用Window10系统也用下c版的cv&#xff0c;就想配置一下vscode的cv环境&#xff0c;直接下载了一个编译好的opencv库&#xff08;带build文件夹的&#xff09;&#xff0c;刚开始用的是visual studio的编译器&#xff…

php常用伪协议整理

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文整理php常见的伪协议 php伪协议介绍 直观点&#xff0c;就是php可以识别的协议。 类似于我们访问网站的http协议&#xff0c;我们用浏览器访问我们自己本地文件的file协议等。 php可以识别这些协议&#xf…

神经网络(系统性学习二):单层神经网络(感知机)

此前篇章&#xff1a; 神经网络中常用的激活函数 神经网络&#xff08;系统性学习一&#xff09;&#xff1a;入门篇 单层神经网络&#xff08;又叫感知机&#xff09; 单层网络是最简单的全连接神经网络&#xff0c;它仅有输入层和输出层&#xff0c;没有隐藏层。即&#x…

后端:事务

文章目录 1. 事务2. Spring 单独配置DataSource3. 利用JdbcTemplate操作数据库4. 利用JdbcTemplate查询数据5. Spring 声明式事务6. 事务的隔离级别6.1 脏读6.2 不可重复读6.3 幻读6.4 不可重复读和幻读的区别6.5 三种方案的比较 7. 事务的传播特性8. 设置事务 只读(readOnly)9…

Fakelocation Server服务器/专业版 Windows11

前言:需要Windows11系统 Fakelocation开源文件系统需求 Windows11 | Fakelocation | 任务一 打开 PowerShell&#xff08;以管理员身份&#xff09;命令安装 Chocolatey Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProto…

MySQL系列之身份鉴别(安全)

导览 前言Q&#xff1a;如何保障MySQL数据库身份鉴别的有效性一、有效性检查1. 用户唯一2. 启用密码验证3. 是否存在空口令用户4. 是否启用口令复杂度校验5. 是否设置口令的有效期6. 是否限制登录失败尝试次数7. 是否设置&#xff08;超过尝试次数&#xff09;锁定的最小时长8.…

MySQL面试题补

内连接和外连接的区别&#xff1a; ○1.功能和用法不同&#xff1a;内连接是连接两表都满足情况的数据&#xff1b;而外连接是以一边的表为主表&#xff0c;另一个表只显示匹配的行&#xff1b; ○2.用途&#xff1a;内连接一般是用于检索不同表需要根据共同的列值进行匹配的&a…

线程(三)【线程互斥(下)】

目录 4. 互斥锁4.1 解决数据不一致问题 5. 锁的原理5.1 加锁5.2 解锁 6. 可重入 vs 线程安全 4. 互斥锁 NAMEpthread_mutex_destroy, pthread_mutex_init - destroy and initialize a mutex // 创建、释放锁SYNOPSIS#include <pthread.h>// pthread_mutex_t: 线程库提供…

如何使用AWS Lambda构建一个云端工具(超详细)

首发地址&#xff08;欢迎大家访问&#xff09;&#xff1a;如何使用AWS Lambda构建一个云端工具&#xff08;超详细&#xff09; 1 前言 1.1 无服务器架构 无服务器架构&#xff08;Serverless Computing&#xff09;是一种云计算服务模型&#xff0c;它允许开发者构建和运行…

网络爬虫总结与未来方向

通过深入学习和实际操作&#xff0c;网络爬虫技术从基础到进阶得以系统掌握。本节将全面总结关键内容&#xff0c;并结合前沿技术趋势与最新资料&#xff0c;为开发者提供实用性强的深度思考和方案建议。 1. 网络爬虫技术发展趋势 1.1 趋势一&#xff1a;高性能分布式爬虫 随…