Android binder(RPC) 通信概念与架构
文章目录
- 一、preface
- 1、资料快车
- 2、概述
- 1.1 Binder与其它 IPC 的效率对比
- 1.2 区分RPC与IPC
- 1.3 三大 binder 域(Treble 后)
- 1.4 mmap内存技术
- 3、基础概念
- 二、Binder框架图
- 1、对等通信
- 2、binder三大角色
- 3、Binder各层级关键类
- 4、AIDL/HIDL binder
- 5、通信架构图
- 三、Binder 基础模型
- 3.1 Binder 全栈架构图(应用 → framework → native → libbinder → 内核)
- 3.2 核心概念
- 3.3 引用计数(强/弱)
- 3.4 BC / BR 协议
- 四、源码目录
- 4.1 内核侧
- 4.2 用户态
一、preface
1、资料快车
1、Framework篇 - 彻底理解Binder通信架构
https://blog.csdn.net/u014294681/article/details/88094088
2、Framework-进程间通信之Binder机制AIDL
https://blog.csdn.net/blankmargin/article/details/126787525
3、Framework源码(Binder驱动解析)
https://zhuanlan.zhihu.com/p/542058702
4、Framework层的Binder(源码分析篇)
https://www.zhihu.com/tardis/zm/art/554115552?source_id=1005
5、书籍 - Android系统源代码情景分析
6、AIDL的使用详解(APP):https://blog.csdn.net/u014294681/article/details/88126988
2、概述
Binder是 Android 的核心 IPC/RPC 机制,几乎承载了 Android 所有的跨进程通信:应用与系统服务、系统服务之间、HAL 与框架、甚至dumpsys、service list都建立在它之上。理解 Binder 是理解 Android 整个系统框架的前提。
本平台(RK3568 Android 11)的 Binder 实现是纯 AOSP 内核栈(drivers/android/binder.c,约 6187 行),RK 没有对其做功能性改动——唯一的平台相关点是rockchip_defconfig打开了CONFIG_ANDROID_BINDERFS=y,三个设备节点(/dev/binder、/dev/hwbinder、/dev/vndbinder)由 binderfs 创建并通过 init.rc 建立符号链接。
1)binder在哪里使用?发生在用户态的各个层级-- APP/framework/native/JNI/driver
2)使用的形式 – aidl/hidl,无论是java/c++,都是getserver(client/Stub.proxy) / addserver(server/stub) 形式;
3)我们应该关注最顶层的实现,底层是恒定不变,只要简单识别即可,且工具已经帮我们实现封装(这里为什么不用代码来封装?工具如此不直观,纯写代码仍然有一定工作量并且都是重复代码,工具可以让我们集中精力定义和实现接口)
3)binder系统的复杂之处在于上层的层层复杂封装;
1.1 Binder与其它 IPC 的效率对比
Android 几乎所有跨进程通信都走 Binder,而非 Linux 原生的 pipe/socket/共享内存/消息队列。原因不只是"快",而是效率、安全、易用三者的综合最优。
(1)数据拷贝次数对比(核心)
| IPC 方式 | 内核拷贝次数 | 说明 |
|---|---|---|
| 共享内存(shm/mmap) | 0 | 零拷贝,但需自加锁、无内核仲裁,安全隐患大 |
| Binder | 1 | mmap把接收方地址映射进内核,发送方copy_from_user一次即达 |
| pipe / FIFO | 2 | copy_from_user发送方 +copy_to_user接收方 |
| UNIX socket | 2 | 同上 |
| 消息队列(msgget) | 2 | 同上 |
| 信号 | 0 | 只能传一个信号编号,不能传数据 |
Binder 的关键:接收进程在open(/dev/binder)后mmap(PROT_READ)一段空间,内核在该进程页表里建立"内核页 ↔ 用户页"同一物理页映射(vm_insert_page)。一次 transaction 时,内核把发送方数据copy_from_user进这个内核页,接收进程用户态直接读到——省掉了传统 IPC 的第二次copy_to_user。
(2)综合能力对比
| 维度 | Binder | Socket | 共享内存 | pipe/FIFO | 消息队列 | 信号 | D-Bus |
|---|---|---|---|---|---|---|---|
| 拷贝次数 | 1 | 2 | 0 | 2 | 2 | — | 2 |
| CS / 面向对象 | ✅ | △ | ✗ | △ | △ | ✗ | ✅ |
| 内核安全仲裁 | ✅ SELinux | ✗ | ✗ | ✗ | ✗ | ✗ | △(用户态) |
| 死亡通知 | ✅ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| 强/弱引用计数 | ✅ | ✗ | ✗ | ✗ | ✗ | ✗ | ✗ |
| fd/对象传递 | ✅ | △ | ✗ | ✗ | ✗ | ✗ | ✗ |
| 跨域策略(Treble 三域) | ✅ | ✗ | ✗ | ✗ | ✗ | ✗ | △ |
(3)为何 Binder “更高效”——不只是少一次拷贝
- 一次拷贝(核心):对中小消息(< mmap 上限,单端默认 1MB−2页),相比 socket/pipe 的两次拷贝减少约一半内核态拷贝开销;相比共享内存仅多一次拷贝,却换来内核仲裁与安全。
- 面向对象 + 引用计数:通信单元是"对象引用"(binder node → handle),一次
getService拿到 handle 后续调用复用,不必每次编解码地址/连接;强/弱引用 + 死亡通知让对象生命周期与进程解耦,无需应用层心跳。 - 线程池 + 优先级继承:服务端单进程多 binder 线程(默认 15),应对高并发场景,驱动按需
BR_SPAWN_LOOPER扩容;同步调用时发送方优先级继承到服务端线程(binder_transaction_priority),保证 UI 线程发起的调用能及时在服务端响应,避免优先级反转。 - 内核内同步语义:同步 transaction 天然阻塞发送方等
BR_REPLY,省去应用层等待/超时协议;oneway 则零等待异步投递(node 级串行化)。 - fd/对象直传:
flat_binder_object的BINDER_TYPE_FD在内核里直接binder_alloc_fd把 fd 转移到目标进程(如 Surface/ashmem 句柄),无需序列化文件路径。 - 统一服务管理 + 安全模型:servicemanager 提供按名字寻址,SELinux 在
security_binder_transaction处对每次调用做"谁能调谁"判定,集中可控;socket/shm 要应用自行实现鉴权。
一句话:共享内存最快但不安全也不好用;socket/pipe 通用但慢且无对象语义。Binder 用一次内核拷贝 + 内核仲裁 + 面向对象引用,在"足够快"和"安全/易用"之间取得 Android 需要的平衡——这是它取代传统 IPC 的根本原因。
1.2 区分RPC与IPC
1、RPC和IPC IPC(Inter-process communication 进程间通信)只搬数据;RPC(Remote Procedure call远程过程调用)在 IPC 之上再封装"调用哪个对象、哪个方法、什么参数、什么返回值"。Binder 底层是 IPC(一次 transaction 搬一个 binder_transaction_data),但 libbinder/AIDL 层把它包装成了 RPC——`transact(handle, code, data, reply) 2、RPC四要素 handle : 调用哪个服务 code : 调用哪个接口 data : 入参数据 reply : 出参数据1.3 三大 binder 域(Treble 后)
| 设备 | 域 | 库 | context manager | 用途 |
|---|---|---|---|---|
/dev/binder | framework | libbinder | servicemanager | 应用/框架进程 ↔ 框架系统服务 |
/dev/hwbinder | hwbinder | libhwbinder | hwservicemanager | HIDL HAL(Treble 前风格) |
/dev/vndbinder | vendor | libbinder(VNDK) | vndservicemanager | vendor 进程间 |
三者是三个独立的binder_device,各持一个独立的binder_context(独立的 context manager 节点),互不可见。
libbinder 在 VNDK 编译时(__ANDROID_VNDK__)默认打开/dev/vndbinder。
1.4 mmap内存技术
本质上就是 开辟一个特区内容空间 - 不区分用户空间和内核空间,用户态和内核态都可以畅通访问!
3、基础概念
1、Bn/Bp Bn (binder native) - CPP服务端implement BB (Base binder) - native服务端 Bp (binder proxy) - 客户端 2、RPC/IPC IPC : Inter-process commuication RPC : Remote Procedure call - 在IPC基础上再封装一层 3. AIDL : Android interface Defintion Language ,Android 接口定义语言,用于应用层进程间通信(IPC), Service与客户端跨进程调用(双向通信) HIDL : HAL interface Definition Language HAL 接口定义语言 4、 defer : 延迟 5、shrinker -Linux内核的内存回收机制 shrinker - 内存收缩器 LRU - last Recently Used 最近最少使用 reclaim - 释放不活跃的内存 kswapd - 内核交换守护进程二、Binder框架图
1、对等通信
1)
2)
2、binder三大角色
3、Binder各层级关键类![]()
4、AIDL/HIDL binder
1)https://blog.csdn.net/yangwen123/article/details/79836109
2)普通Binder架构在这里插入图片描述
3)HIDL Binder架构
5、通信架构图
1)通信架构图
2)关键代码流程
客户端调用 getService: App 进程 │ ▼ BpServiceManager::getService(name) │ ▼ BpRefBase::remote() → BpBinder(handle=0) │ ▼ BpBinder::transact(GET_SERVICE, data, reply) │ ▼ IPCThreadState::transact(handle=0, GET_SERVICE, ...) │ ▼ ioctl(BINDER_WRITE_READ) ──────→ Binder Driver │ ▼ 查找 handle=0 对应的进程 │ ▼ System Server 进程 │ ▼ BBinder::onTransact(GET_SERVICE, ...) │ ▼ BnServiceManager::onTransact(GET_SERVICE, ...) │ ▼ ServiceManager::getService(name) // 本地实现 │ ▼ 返回结果 ←─────── IPCThreadState ──────── Binder Driver │ ▼ 客户端收到 reply三、Binder 基础模型
3.1 Binder 全栈架构图(应用 → framework → native → libbinder → 内核)
自上而下五层,每层标注该层的关键技术;客户端调用沿箭头下沉到内核,内核一次拷贝 + 跨进程投递到服务端,服务端onTransact自下而上执行。右列是各层对应的源码位置。
应用层 App / Java · Kotlin ┌───────────────────────────────────────────────────────────────────┐ │ • AIDL 接口 • Stub.Proxy(客户端 Bp) / Stub(服务端 Bn) │ app/src/**/aidl │ • ServiceConnection.bindService • IBinder / Binder.java │ android.os.* │ • ServiceManager.getService / addService(系统服务) │ └───────────────────────────────────────────────────────────────────┘ │ JNI:android_util_Binder.cpp(Java ↔ native) ▼ Framework 层 frameworks/base(Java) ┌───────────────────────────────────────────────────────────────────┐ │ • android.os.Binder(服务端)/ BinderProxy(客户端代理) │ frameworks/base/core/java/android/os │ • android.os.Parcel(Java) • IServiceManager.aidl │ └───────────────────────────────────────────────────────────────────┘ │ Parcel 跨 JNI 下沉到 C++ ▼ Native / C++ 层 libbinder ┌───────────────────────────────────────────────────────────────────┐ │ • BpBinder(handle, transact) ── 客户端代理 │ libs/binder/BpBinder.cpp │ • BBinder(onTransact) ── 服务端桩 │ libs/binder/Binder.cpp │ • IInterface / asInterface() / DECLARE_META_INTERFACE │ libs/binder/IInterface.h │ • IServiceManager + defaultServiceManager() • Parcel(C++) │ libs/binder/IServiceManager.cpp │ • AIDL 生成的 BnXXX/BpXXX 即此层;HIDL → libhwbinder │ └───────────────────────────────────────────────────────────────────┘ │ transact → writeTransactionData(BC_TRANSACTION) ▼ libbinder 运行时 frameworks/native/libs/binder ┌───────────────────────────────────────────────────────────────────┐ │ • ProcessState::self() open(/dev/binder) + mmap(PROT_READ) │ libs/binder/ProcessState.cpp │ setThreadPoolMaxThreadCount(默认 15) │ │ • IPCThreadState::self() talkWithDriver → ioctl(BINDER_WRITE_READ) │ libs/binder/IPCThreadState.cpp │ BC/BR 主循环 + executeCommand(BR_*) │ │ joinThreadPool(BC_ENTER/REGISTER_LOOPER) │ └───────────────────────────────────────────────────────────────────┘ │ ioctl(/dev/binder, BINDER_WRITE_READ, {BC_TRANSACTION, …}) ▼ 内核 binder 驱动 drivers/android/binder.c(~6200 行) ┌───────────────────────────────────────────────────────────────────┐ │ • 数据结构:binder_proc / thread / node / ref / buffer / txn │ binder.c / binder_alloc.c │ • binder_transaction(): handle → ref → node → target_proc │ │ ① security_binder_transaction SELinux 仲裁 │ │ ② binder_alloc_new_buf 在 target mmap 空间分配 buffer│ │ ③ ★ 一次拷贝 copy_from_user 发送方 → target buffer │ │ ④ fixup flat_binder_object binder↔handle / fd 转移 │ │ ⑤ 入 target todo + 唤醒线程 → 对端 BR_TRANSACTION │ │ • 引用计数(强/弱) • 死亡通知 • 优先级继承 • BR_SPAWN_LOOPER 线程池 │ ├───────────────────────────────────────────────────────────────────┤ │ • binderfs: /dev/binder /dev/hwbinder /dev/vndbinder │ binderfs.c │ (三域 = 三个独立 binder_context / context manager,Treble 隔离) │ └───────────────────────────────────────────────────────────────────┘读图:
- 五层从上到下封装厚度递减:应用层最厚(AIDL 自动生成 Stub/Proxy,开发者只写接口),libbinder 运行时最薄(直接 ioctl),内核是真正的"搬运工"。
- 下沉路径(客户端):
foo.方法()→ Stub.Proxytransact→ JNI →BpBinder::transact→IPCThreadState::transact写BC_TRANSACTION→ioctl(BINDER_WRITE_READ)。每一层只做一件事:上层打包参数,下层搬数据。 - 跨进程在内核发生:客户端到内核是普通
ioctl,内核binder_transaction把数据一次拷贝进服务端 mmap 空间、唤醒服务端线程——服务端进程这才参与(BR_TRANSACTION→BBinder::onTransact→ 业务),全程对应用透明。 - 三大域:图中
/dev/binder|hwbinder|vndbinder是三个独立 binderfs 设备,物理隔离 framework/hw/vendor 三套服务空间(见 1.3)。 - 本图是"分层栈"视角;1.3 是同一条链路的"调用时序"视角(Client/Server/Driver 三列),两者互补。
对照显示侧:libbinder 之于 binder ≈ libdrm 之于 DRM;AIDL 之于 libbinder ≈ “驱动自动生成胶水”(详见 Linux DRM 文档)。
3.2 核心概念
| 概念 | 说明 |
|---|---|
| binder node | 内核中代表"一个可被跨进程调用的对象"。服务端BBinder首次传递给驱动时创建,挂在binder_proc->nodes(按ptr排序的红黑树)。 |
| binder ref | 客户端对某个 node 的"句柄引用"。binder_ref->data.desc即用户态看到的 handle(0 表示 context manager)。同一进程对同一 node 只有一个 ref。 |
| handle | 用户态的 32 位引用号。handle==0特指 servicemanager(context manager node)。 |
| binder_buffer | 在接收进程 mmap 空间里切出的一段缓冲,承载一次 transaction 的数据。用完由用户态BC_FREE_BUFFER归还。 |
| binder_proc / binder_thread | 一个打开/dev/binder的进程 / 一个 binder 线程。 |
| flat_binder_object | Parcel 中"对象的扁平表示"——把一个强/弱 binder、handle、fd 等塞进数据流,驱动在 transaction 时改写它(binder↔handle 翻译、fd 转移)。 |
3.3 引用计数(强/弱)
binder node 同时被内核(internal_strong_refs)和用户态(local_strong_refs)引用,强弱两套独立计数。用户态通过BC_ACQUIRE/RELEASE/INCREFS/DECREFS显式增减;驱动在 transaction 期间临时增持,完成后归还。当强引用归零且无弱引用时,node 被释放;客户端在此之前用BC_REQUEST_DEATH_NOTIFICATION注册的死亡通知会以BR_DEAD_BINDER投递。
3.4 BC / BR 协议
- BC_(Binder Command):用户态→驱动,写在
binder_write_read.write_buffer。如BC_TRANSACTION、BC_REPLY、BC_ACQUIRE、BC_ENTER_LOOPER、BC_FREE_BUFFER、BC_REQUEST_DEATH_NOTIFICATION。 - BR_(Binder Return):驱动→用户态,读自
read_buffer。如BR_TRANSACTION、BR_REPLY、BR_TRANSACTION_COMPLETE、BR_DEAD_REPLY、BR_SPAWN_LOOPER、BR_NOOP。
一次ioctl(BINDER_WRITE_READ)同时携带一批 BC 与读出一批 BR。
四、源码目录
4.1 内核侧
1.源码 kernel/drivers/android/* 2.UAPI 1)kernel/include/uapi/linux/android/binder.h(542 行,所有 ioctl 号、BC/BR、flat_binder_object 等) 2)kernel/include/uapi/linux/android/binderfs.h| 文件 | 行数 | 角色 |
|---|---|---|
binder.c | 6187 | 核心驱动:open/mmap/ioctl、transaction、node/ref/thread 管理、debugfs |
binder_alloc.c | 1244 | 每进程 buffer 分配器 + 一次拷贝页管理(LRU/shrinker) |
binder_alloc.h | 187 | struct binder_alloc/binder_buffer/binder_lru_page |
binderfs.c | ~770 | per-namespace 伪文件系统,动态创建 binder 设备节点 +binder-control |
binder_internal.h | 146 | binder_context/binder_device、transaction-log、debug seq_file 声明 |
binder_trace.h | ~415 | ftracebinder类别所有TRACE_EVENT |
4.2 用户态
| 层 | 路径 | 说明 |
|---|---|---|
| libbinder | frameworks/native/libs/binder/ | 通用 Binder IPC:用于应用与系统服务(System Server)、应用之间等的常规进程间通信 关键类: ProcessState、IPCThreadState、BpBinder、BBinder、IServiceManager、Parcel |
| libhwbinder | system/libhwbinder/ | 硬件 Binder IPC:专门用于 Android 框架(Framework)与硬件抽象层(HAL) 之间的通信 |
| servicemanager | frameworks/native/cmds/servicemanager/ | main.cpp/ServiceManager.cpp(BnServiceManager) /Access.cpp(SELinux ACL) |
| hwservicemanager | system/hwservicemanager | 硬件 Binder IPC |
| aidl-gen | system/tools/aidl/ | 将.aidl生成 BnXXX/BpXXX(C++/Java/NDK) |
| hidl-gen | system/tools/hidl/ | 将.hal生成 HIDL 桩 |
