第1章 Binder 架构与进程模型

本章从操作系统进程隔离的基本原理出发,剖析 Android 选择 Binder 作为跨进程通信(IPC)主通道的根本原因,并深入 Binder 驱动的角色定位和 ServiceManager 的启动流程,为后续章节打下扎实的底层认知基础。

1.1 进程隔离原理

现代操作系统基于进程(Process)提供资源隔离与保护。每个进程拥有独立的虚拟地址空间,用户空间的代码不能直接访问其他进程的地址空间,也无法直接操纵内核数据结构。这种隔离通过 CPU 的硬件保护机制(如 ARM 的异常级别、x86 的 Ring 0‑3)与内核协同实现。

隔离维度实现机制IPC 的突破口
地址空间隔离页表 + MMU,每个进程独立页表必须通过内核空间中转或共享内存
权限隔离用户态/内核态模式切换(系统调用)只有内核能跨越进程边界
资源隔离文件描述符表、信号处理器等独立需内核协助传递句柄
关键理解: Android 用户空间进程(App、System Server、ServiceManager)之间不能直接调用方法或共享对象。任何跨进程数据传递都必须将数据拷贝到内核空间,再由内核路由到目标进程。Binder 驱动就是承担这一“内核”角色的核心组件。

1.2 Binder 驱动角色

Binder 驱动(/dev/binder)是一个 Linux 字符设备驱动,驻留在内核空间。它不是普通的设备驱动(不管理任何物理硬件),而是一个 软件数据交换引擎。其核心职责包括:

  • 数据传递: 通过 ioctl() 接口接收用户空间的 Binder 事务数据,完成跨进程拷贝(一次拷贝优化)。
  • 线程管理: 维护 Binder 线程池,将待处理事务投递到目标进程的工作队列。
  • 引用计数: 管理 Binder 对象的跨进程引用计数,避免内存泄漏。
  • 死亡通知: 监听 Binder 服务端进程退出,向客户端发送死亡回调。
  • 服务查找: 配合 ServiceManager 完成服务注册与查询的底层转发。

Binder 驱动的设备节点在 Android 启动时由内核创建,应用层通过标准文件操作访问:

# 检查 binder 设备节点是否存在
ls -l /dev/binder

# 典型输出(root 下)
crw-rw-rw- 1 root root 10, 57 2025-01-01 00:00 /dev/binder
# 主设备号 10,次设备号 57

Binder 驱动提供的 ioctl 命令主要包括:

命令功能
BINDER_WRITE_READ核心命令,写入事务并读取回复
BINDER_SET_CONTEXT_MGR将当前进程注册为 context manager(ServiceManager)
BINDER_THREAD_EXIT通知驱动当前 Binder 线程退出
BINDER_ENABLE_ONEWAY_SPAM_DETECTION单向事务反垃圾控制
性能提示: Binder 驱动在一次 IPC 中最多只需进行 1 次 数据拷贝(从发送端用户空间到接收端内核空间,再直接映射到接收端用户空间),而传统 Unix Socket 或管道至少需要 2 次拷贝。这是 Binder 在 Android 移动设备上表现出更低延迟和更少内存占用的根本原因。

1.3 ServiceManager 启动流程

ServiceManager 是 Android 系统的“服务黄页”,负责管理所有注册到 Binder 的服务名与服务句柄。它本身也是一个 Binder 服务,但具有特殊身份——context manager。其启动流程如下:

  1. init 进程拉起: System 分区 /system/bin/servicemanager 由 init 进程根据 servicemanager.rc 启动。
  2. 打开 Binder 驱动: 调用 open("/dev/binder", O_RDWR) 获得文件描述符。
  3. 注册自身为 context manager: 通过 ioctl(fd, BINDER_SET_CONTEXT_MGR, NULL) 告知 Binder 驱动本进程是唯一的服务管理者。
  4. 进入循环处理: 不断调用 ioctl(fd, BINDER_WRITE_READ, ...) 读取客户端发来的服务注册/查询请求并响应。
  5. 注册默认服务: ServiceManager 初始化后,会注册自身的管理接口(如 addService、getService)供系统服务使用。
// servicemanager 核心启动伪代码(简化)
int main() {
    int fd = open("/dev/binder", O_RDWR);      // 打开 binder 驱动
    ioctl(fd, BINDER_SET_CONTEXT_MGR, NULL);   // 成为 context manager
    struct binder_write_read bwr = {0};
    while (1) {
        ioctl(fd, BINDER_WRITE_READ, &bwr);    // 等待并处理事务
        // 解析事务,调用 svcmgr_handler()
    }
    close(fd);
    return 0;
}
常见错误: 如果 /dev/binder 不存在或权限不足(例如在非 root 容器中运行),ServiceManager 无法启动,系统将停留在无服务注册状态,所有依赖 Binder 的系统服务(如 SurfaceFlinger、ActivityManager)都会崩溃。使用 dmesg | grep binder 可检查驱动加载情况。
Binder 架构与进程模型示意 Binder 跨进程通信架构 用户空间 内核空间 进程 A (App / System Server) 进程 B (App / System Server) Binder 驱动 /dev/binder ServiceManager context manager 系统调用 ioctl / mmap Binder 一次拷贝: 用户 → 内核(直接映射)

1.4 本章小结

进程隔离是 Android 安全的基石,Binder 驱动是打破隔离的合法“桥梁”,ServiceManager 是这座桥上唯一的“交通警察”。理解这三者关系,就抓住了 Android 跨进程通信的命脉。下一章将深入 Binder 数据包的结构——Parcel 序列化与事务协议。