文章目录
-
- 一、preface
- 二、Binder框架图
-
- 1、对等通信
- 2、binder三大角色
- 3、Binder各层级关键类!在这里插入图片描述(https://i-blog.csdnimg.cn/direct/e1e2b2a664884d5bad8797bab653af3d.png)
- [4、AIDL/HIDL binder](#4、AIDL/HIDL binder)
- 5、通信架构图
- [三、Binder 基础模型](#三、Binder 基础模型)
-
- [3.1 Binder 全栈架构图(应用 → framework → native → libbinder → 内核)](#3.1 Binder 全栈架构图(应用 → framework → native → libbinder → 内核))
- [3.2 核心概念](#3.2 核心概念)
- [3.3 引用计数(强/弱)](#3.3 引用计数(强/弱))
- [3.4 BC / BR 协议](#3.4 BC / BR 协议)
- 四、源码目录
-
- [4.1 内核侧](#4.1 内核侧)
- [4.2 用户态](#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 | ftrace binder 类别所有 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 桩 |