当前位置: 首页 > news >正文

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各层级关键类![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/e1e2b2a664884d5bad8797bab653af3d.png)
      • 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 与框架、甚至dumpsysservice 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零拷贝,但需自加锁、无内核仲裁,安全隐患大
Binder1mmap把接收方地址映射进内核,发送方copy_from_user一次即达
pipe / FIFO2copy_from_user发送方 +copy_to_user接收方
UNIX socket2同上
消息队列(msgget)2同上
信号0只能传一个信号编号,不能传数据

Binder 的关键:接收进程在open(/dev/binder)mmapPROT_READ)一段空间,内核在该进程页表里建立"内核页 ↔ 用户页"同一物理页映射(vm_insert_page)。一次 transaction 时,内核把发送方数据copy_from_user进这个内核页,接收进程用户态直接读到——省掉了传统 IPC 的第二次copy_to_user

(2)综合能力对比

维度BinderSocket共享内存pipe/FIFO消息队列信号D-Bus
拷贝次数120222
CS / 面向对象
内核安全仲裁✅ SELinux△(用户态)
死亡通知
强/弱引用计数
fd/对象传递
跨域策略(Treble 三域)

(3)为何 Binder “更高效”——不只是少一次拷贝

  1. 一次拷贝(核心):对中小消息(< mmap 上限,单端默认 1MB−2页),相比 socket/pipe 的两次拷贝减少约一半内核态拷贝开销;相比共享内存仅多一次拷贝,却换来内核仲裁与安全。
  2. 面向对象 + 引用计数:通信单元是"对象引用"(binder node → handle),一次getService拿到 handle 后续调用复用,不必每次编解码地址/连接;强/弱引用 + 死亡通知让对象生命周期与进程解耦,无需应用层心跳。
  3. 线程池 + 优先级继承:服务端单进程多 binder 线程(默认 15),应对高并发场景,驱动按需BR_SPAWN_LOOPER扩容;同步调用时发送方优先级继承到服务端线程binder_transaction_priority),保证 UI 线程发起的调用能及时在服务端响应,避免优先级反转。
  4. 内核内同步语义:同步 transaction 天然阻塞发送方等BR_REPLY,省去应用层等待/超时协议;oneway 则零等待异步投递(node 级串行化)。
  5. fd/对象直传flat_binder_objectBINDER_TYPE_FD在内核里直接binder_alloc_fd把 fd 转移到目标进程(如 Surface/ashmem 句柄),无需序列化文件路径。
  6. 统一服务管理 + 安全模型: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/binderframeworklibbinderservicemanager应用/框架进程 ↔ 框架系统服务
/dev/hwbinderhwbinderlibhwbinderhwservicemanagerHIDL HAL(Treble 前风格)
/dev/vndbindervendorlibbinder(VNDK)vndservicemanagervendor 进程间

三者是三个独立的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::transactIPCThreadState::transactBC_TRANSACTIONioctl(BINDER_WRITE_READ)。每一层只做一件事:上层打包参数,下层搬数据。
  • 跨进程在内核发生:客户端到内核是普通ioctl,内核binder_transaction把数据一次拷贝进服务端 mmap 空间、唤醒服务端线程——服务端进程这才参与(BR_TRANSACTIONBBinder::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_objectParcel 中"对象的扁平表示"——把一个强/弱 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_TRANSACTIONBC_REPLYBC_ACQUIREBC_ENTER_LOOPERBC_FREE_BUFFERBC_REQUEST_DEATH_NOTIFICATION
  • BR_(Binder Return):驱动→用户态,读自read_buffer。如BR_TRANSACTIONBR_REPLYBR_TRANSACTION_COMPLETEBR_DEAD_REPLYBR_SPAWN_LOOPERBR_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.c6187核心驱动:open/mmap/ioctl、transaction、node/ref/thread 管理、debugfs
binder_alloc.c1244每进程 buffer 分配器 + 一次拷贝页管理(LRU/shrinker)
binder_alloc.h187struct binder_alloc/binder_buffer/binder_lru_page
binderfs.c~770per-namespace 伪文件系统,动态创建 binder 设备节点 +binder-control
binder_internal.h146binder_context/binder_device、transaction-log、debug seq_file 声明
binder_trace.h~415ftracebinder类别所有TRACE_EVENT

4.2 用户态

路径说明
libbinderframeworks/native/libs/binder/通用 Binder IPC:用于应用与系统服务(System Server)、应用之间等的常规进程间通信
关键类:ProcessStateIPCThreadStateBpBinderBBinderIServiceManagerParcel
libhwbindersystem/libhwbinder/硬件 Binder IPC:专门用于 Android 框架(Framework)与硬件抽象层(HAL) 之间的通信
servicemanagerframeworks/native/cmds/servicemanager/main.cpp/ServiceManager.cpp(BnServiceManager) /Access.cpp(SELinux ACL)
hwservicemanagersystem/hwservicemanager硬件 Binder IPC
aidl-gensystem/tools/aidl/.aidl生成 BnXXX/BpXXX(C++/Java/NDK)
hidl-gensystem/tools/hidl/.hal生成 HIDL 桩
http://www.gsyq.cn/news/1602629.html

相关文章:

  • 技术桥接中的抽象分离与实现独立
  • 终极内存检测指南:5步彻底解决电脑蓝屏和死机问题
  • Dalín X 意识框架实测数据报告
  • 如何三步获取阿里云盘Refresh Token?解锁云盘自动化管理新体验
  • A股量化,单策略真的不够用了:我开源了一个双策略自动切换框架
  • 星皓 MDM.Plus 是什么?面向手机租赁和企业设备管理的一站式 MDM 解决方案
  • 5分钟零基础入门:Kafka-UI可视化集群管理终极指南
  • 技术写作的价值与技巧
  • Kafka集群管理太复杂?这款开源Web UI让你5分钟上手
  • Jellyfin Bangumi插件完整指南:打造智能动漫库的终极方案
  • 3分钟掌握B站缓存视频转换:m4s转MP4完整教程
  • LeetCode 287. 寻找重复数:从直觉到 Floyd 判圈的完整推导
  • Python的__init_subclass__验证
  • 操作系统内存管理
  • 猫抓:如何解决网页视频无法下载的三大难题?
  • 哈夫曼编码和香农-范诺编码的性能对比 P124302171陈新阳
  • 欺诈检测化技术行为分析模型与实时规则引擎
  • Bitget发布Web3人才报告:54%求职者受困「经验门槛」,AI与区块链融合成最热职业方向
  • 深度掌控AMD Ryzen:专业级SMU调试工具完全指南
  • TestDisk终极指南:5步快速恢复丢失分区与数据
  • Paperclip - 多Agent编排管理平台详细介绍
  • Hermes - AI Agent 运行时框架详细介绍
  • 零食折扣店收银系统哪个牌子好?扫码快、上手简单才是关键
  • esp32开发与应用(esp和wch芯片的配合)
  • AFE5808A超声模拟前端芯片ADC与VCA寄存器配置实战指南
  • 为什么选择OmenSuperHub?一个免费开源工具彻底解决惠普游戏本性能限制问题
  • Nginx从入门到精通:一文搞懂这款高性能Web服务器的核心原理与实战配置
  • 完成发射班的焊接及调试
  • 【Flutter零基础入门 | Day03】常用功能与滚动组件
  • 安全组网建设怎么选