Android中一次完整的ipc通信过程
一、Binder IPC通信完整流程
1. Client端发起调用
- 数据封装:Client将方法标识(如
TRANSACTION_test
)、参数等封装为Parcel
对象,并通过BinderProxy
调用transact()
方法。 - 驱动层交互:通过
ioctl
系统调用向Binder驱动发送BC_TRANSACTION
命令协议,携带包含目标Binder句柄(如Service的引用)、事务码(如code
)、数据缓冲区地址等信息的binder_transaction_data
结构体。
2. Binder驱动转发
- 事务队列处理:驱动根据目标Binder句柄找到对应服务端进程的
binder_proc
结构,将事务添加到服务端的todo
队列,并唤醒其空闲线程。 - 内存映射优化:数据通过内核缓冲区映射到服务端用户空间,仅需一次拷贝(客户端→内核),服务端通过
mmap
直接访问内核缓冲区。
3. 服务端处理请求
- 线程池调度:服务端进程的Binder线程池(默认16线程)中,空闲线程通过
IPCThreadState
从驱动读取BR_TRANSACTION
指令,解析出目标Binder对象和方法标识。 - 事务执行:调用服务实现的
onTransact()
方法,执行具体逻辑(如数据库操作),并将结果写入Parcel
,通过驱动返回给Client。
4. 结果返回与同步
- 驱动回传数据:驱动将服务端返回的
Parcel
数据拷贝至Client进程的内核缓冲区,并通过BR_REPLY
指令唤醒Client的等待线程。 - 同步机制:Binder通信是同步的,Client调用
transact()
后会阻塞,直到服务端处理完成并返回结果。
二、Binder IPC通信协议
1. 协议命令分类
- 控制命令(BC/BR协议):
- 客户端命令:
BC_TRANSACTION
(发起事务)、BC_REPLY
(响应事务)。 - 驱动响应命令:
BR_TRANSACTION
(驱动转发请求)、BR_REPLY
(驱动返回结果)。 - 线程管理命令:
BC_REGISTER_LOOPER
(线程注册)、BR_SPAWN_LOOPER
(驱动通知创建新线程)。
- 客户端命令:
2. 数据封装与传输
- 数据结构:核心为
binder_transaction_data
,包含目标句柄、事务码、数据缓冲区指针、偏移量等字段。 - 零拷贝支持:通过
mmap
映射,服务端直接操作内核缓冲区,避免数据二次拷贝(传统IPC如Socket需两次拷贝)。
3. 同步与优先级机制
- 同步调用:Client线程阻塞等待
BR_REPLY
,服务端线程处理完成后才返回。 - 优先级继承:驱动将Client线程的优先级传递给服务端处理线程,确保高优先级请求优先执行(如系统关键服务)。
流程与协议关联示例
以Client调用ServiceManager.getService()
为例:
- Client发送
BC_TRANSACTION
:携带Parcel
数据,请求查询服务。 - 驱动路由:根据句柄
BINDER_SERVICE_MANAGER
(固定值0)定位到ServiceManager进程。 - ServiceManager处理:查询服务表,返回对应Binder引用。
- 驱动返回
BR_REPLY
:Client获取引用后,通过代理对象发起后续调用。
三、应对面试描述
1. 通信流程核心步骤
-
① 客户端(Client)发起请求
- Client通过
BinderProxy
调用transact()
方法,将请求数据(方法标识、参数等)封装为BC_TRANSACTION
命令,发送到Binder驱动。 - Client线程进入休眠状态,等待结果返回(同步阻塞)。
- Client通过
-
② Binder驱动路由与转发
- 驱动解析
BC_TRANSACTION
,根据目标Binder句柄找到对应的Server进程,将请求转换为BR_TRANSACTION
命令,并放入Server的待处理队列(todo
队列)。 - 驱动向Client返回
BR_TRANSACTION_COMPLETE
,表示事务已提交(非最终结果)。
- 驱动解析
-
③ 服务端(Server)处理请求
- Server的空闲Binder线程被唤醒,从队列中取出
BR_TRANSACTION
指令,通过BBinder
调用onTransact()
方法执行具体逻辑(如数据库操作)。 - 处理完成后,将结果封装为
BC_REPLY
命令,通过驱动返回。
- Server的空闲Binder线程被唤醒,从队列中取出
-
④ 结果返回与唤醒
- Binder驱动将
BC_REPLY
转换为BR_REPLY
指令,发送给Client并唤醒其休眠线程。 - Client解析结果后继续执行后续逻辑。
- Binder驱动将