2. 系统服务层架构
2.1 本章定位与组件边界
系统服务层是AOSP组件化架构的基石,它向上支撑Java Framework与Native Framework,向下通过Binder驱动完成跨进程通信。本章聚焦于三个核心实体:ServiceManager(服务注册中心)、系统服务注册与发现机制(服务生命周期管理)、Binder驱动(传输通道)。组件边界如下图所示:
2.2 模块职责与系统分层
| 模块 | 所处层级 | 核心职责 |
|---|---|---|
| ServiceManager | Native 框架层(用户态) | 维护服务名称 → Binder 句柄的映射表,提供 addService / getService / checkService 接口 |
| Binder 驱动 | 内核层 | 管理 Binder 节点、线程池、内存映射(mmap)、传递事务包(BC/BR协议) |
| 系统服务进程 | System Server(Java / Native) | 实现具体服务接口,启动时向 ServiceManager 注册;运行时通过 Binder 接收客户端调用 |
| 客户端进程 | 应用 / 框架进程 | 通过 ServiceManager 查询服务句柄,构造 Binder 调用并返回结果 |
所有进程间的通信数据流都必须经过 Binder 驱动,ServiceManager 本身也是一个特殊服务,其 Binder 句柄固定为 0。系统服务层通过这种“中央注册 + 驱动路由”的架构,实现了位置透明和运行时解耦。
2.3 数据流 / 控制流 / 信任链路
2.3.1 服务注册流程
- 服务进程启动后,通过
defaultServiceManager()获取 ServiceManager 引用,发送addService(name, binder)请求。 - 请求经 Binder 驱动转发至 ServiceManager 用户态;ServiceManager 将服务名与句柄存入映射表。
- ServiceManager 通过驱动返回注册成功标志。
2.3.2 服务发现流程
- 客户端同样获取 ServiceManager 引用,调用
getService(name)。 - ServiceManager 查找映射表,返回目标服务的 Binder 句柄(其实是代理对象)。
- 客户端使用该句柄直接发起跨进程方法调用;后续通信不再经过 ServiceManager。
2.3.3 信任链路
信任模型:Binder 驱动在底层校验进程UID/PID,确保只有系统进程(UID=1000以上或拥有系统签名)才能向 ServiceManager 注册系统服务。ServiceManager 本身不执行服务认证,而是将认证委托给驱动层。这种设计避免了用户态绕过的风险。
- 注册端:必须拥有
SYSTEM_UID或系统权限,否则驱动拒绝分配服务节点。 - 查询端:任意进程均可查询,但只能获取到服务句柄,句柄本身受驱动保护,无法伪造。
2.4 选型权衡:为什么用 Binder 而不是其他 IPC?
| 对比维度 | Binder | Socket | 共享内存 + 信号量 |
|---|---|---|---|
| 传输性能 | 高(内存拷贝1次,mmap) | 低(2次以上拷贝) | 极高(但同步复杂) |
| 对象传递能力 | 支持Binder对象跨进程传递 | 不支持对象传递 | 需序列化 |
| 安全管理 | 驱动层UID/PID校验 | 需应用层认证 | 无内置安全机制 |
| 回调模式 | 原生支持死亡通知、异步回调 | 需自行实现 | 困难 |
| 适配Android度 | 专为移动端设计,Android核心 | 通用但臃肿 | 不适合复杂服务调用 |
Google选择Binder的核心原因是:性能(mmap零拷贝)+ 安全性(驱动层身份校验)+ 面向对象的跨进程接口。虽然Binder协议复杂度较高,但作为Android生态的“骨”,这一权衡在系统稳定性与开发效率上取得了平衡。
2.5 风险点与避坑
- ServiceManager 单点瓶颈:所有服务注册/查询均通过它,但查询仅在首次发生,后续调用不经过,因此风险可控。需要留意 ServiceManager 崩溃会导致整个系统服务不可发现。
- Binder 线程池耗尽:每个进程有默认最大线程数(通常16个),高并发时可能出现“Binder transaction failed”错误。避坑:在系统服务中合理使用异步回调,避免同步调用阻塞线程。
- 服务注册顺序依赖:部分服务启动时依赖其他服务,若 ServiceManager 尚未提供服务,会导致死循环。AOSP通过
SystemServiceManager调度启动顺序,但在自定义系统服务时需显式处理依赖。 - 驱动兼容性问题:早期版本 binder 驱动名称不同(如 /dev/binder 与 /dev/hwbinder),多版本共存时可能混淆。需根据项目 API 版本选择正确的驱动节点。
2.6 落地步骤(面向架构设计者)
- 确定服务注册策略:根据安全等级,决定服务是否需要在 ServiceManager 中注册(如核心系统服务必须注册,纯 native 服务可选)。
- 定义服务接口 AIDL:明确方法签名、回调、权限标签。
- 实现 Binder 服务端:继承
BnInterface,重写onTransact;注册时通过ServiceManager::addService()。 - 客户端绑定与查询:使用
IServiceManager代理查询,按需处理服务死亡通知。 - 压力测试与线程调优:监控 Binder 事务次数,调整
/sys/kernel/debug/binder相关参数,必要时增加线程池上限。 - 集成 sepolicy 权限:为服务注册路径编写 SELinux 规则,确保只有指定进程可注册。
2.7 验收标准
以下标准用于判定系统服务层架构设计是否合格:
| 检查项 | 预期结果 | 验证方式 |
|---|---|---|
| 服务注册成功率 | 系统启动后所有预期服务均出现在 ServiceManager 列表中 | 执行 service list 或 dumpsys service |
| 客户端正常获取服务 | 在3秒内完成查询并成功调用方法 | 编写测试用例调用 getService 并执行远程方法 |
| 死服务及时通报 | 服务进程死亡后客户端收到 linkToDeath 回调 |
杀死服务进程,检查客户端日志 |
| 安全性 | 非授权进程无法注册系统服务 | 以普通应用进程执行 addService,应返回 PERMISSION_DENIED |
| 性能基线 | 服务调用延迟 ≤ 2ms(同进程回退) / ≤ 5ms(跨进程) | 使用 ftrace 或 binderThroughputTest |