基础知识
- binder_init()初始化binder设备
- binder_open()打开binder设备文件
2.1 初始化binder_proc结构体
2.2 将其加入到全局hash队列binder_procs中
2.3 创建/proc/binder/proc/ - binder_mmap()进行内存映射
3.1 分配内核缓冲区
3.2 分配物理页面
3.3 将分配的内核缓冲区加入到进程的空闲内核缓冲区红黑树中
> 当Binder驱动程序需要将一块数据传输给进程时,可以先将数据保存在为该进程分配的一块内核缓冲区中
> 然后在把这块内核缓冲区的用户空间地址告诉进程
> 最后进程便可以访问到里面的数据了 - binder内核缓冲区管理
4.1 分配内核缓冲区binder_alloc_buf()
4.2 释放内核缓冲区binder_free_buf()
类结构(User space)
Server组件/BnInterface/Binder本地对象/Binder实体对象
+-------+
|RefBase|
++----+-+
^ ^
+-----+-+ | +------------+
|IBinder| +--+ProcessState|
+-----+-+ +-----+------+
^ ^
+---------+ +-+-----+ |
|INTERFACE| |BBinder| |
+-+-------+ +-+--+--+ |
^ ^ | |
| +-----------+ | use +-----+--------+
+---+BnInterface+--+ +--> |IPCThreadState|
+-----------+ +--------------+
Client组件/BpInterface/Binder代理对象/Binder引用对象
+-------+ +------------+
|RefBase| <---+----------------+ProcessState|
+---+---- | ------+------+
^ | +-------+ ^
| +---+IBinder| |
+---------+ +-+-------+ +--+----+ |
|INTERFACE| |BpRefBase| ^ |
+----+----+ +---+---+-+ | |
^ ^ | | |
| +-----------+ | has +----+---+ |
+---+BpInterface+---+ +---> |BpBinder| |
+-----------+ +-----+--+ |
| |
use +--------+-----+
+---> |IPCThreadState|
+--------------+
每一个使用了Binder的进程都有一个Binder线程池。每一个Binder线程内部都有一个IPCThreadState对象,可以通过IPCThreadState的静态方法self获取,并调用它的transact和Binder驱动程序交互。transact内部是通过调用talkWithDriver函数与驱动进行交互。talkWithDriver函数既负责向Binder驱动程序发送通讯请求,也负责接受来自Binder驱动程序的通讯请求。
IPCThreadState有一个成员变量mProcess,指向一个ProcessState对象。ProcessState对象负责初始化Binder设备(打开设备文件/dev/binder、将/dev/binder映射到内存)。Binder线程池中的每一个线程都可以通过它来跟Binder驱动程序进行交互(ProcessState对象中保存着内核缓冲区的用户地址)。
即:
* IPCThreadState负责接受和发送进程间通讯请求
* ProcessState负责Binder线程和Binder驱动程序之间的交互
交互过程
+
Client Process | Server Process
|
|
+--------+ | +-------+
+-->BpBinder| | |BBinder+------+
| +------+-+ | +--^----+ |
User Space | (1) | | (3)| |
+-----------------------------+---------------------------+
Kernel Space| | | | |
| +-------v--+ (2) +---+-------+ |
| |binder_ref+---+--->binder_node| |
(5)| +----------+ | +-----------+ |(4)
| | |
| +--------v---------+ |
+-------+binder_transaction<---------+
+------------------+
一次的从Client到Server的通讯过程如下所示:
(1) BpClient向Binder驱动程序发起请求,Binder驱动程序根据BpClient传过来的handler找到对应的binder_ref。
(2) Binder驱动程序根据binder_ref找到对应的binder_node,并且创建一个binder_transaction来描述这次通讯。
(3) Binder驱动程序根据binder_node找到Server进程中的BBinder,将数据传给它。
(4) BBinder处理完成后,将结果返回给Binder驱动程序,驱动程序找到前面建立的binder_transaction。
(5) Binder驱动程序根据binder_transaction找到Client进程,进而找到BpBinder,将结果传给它处理。
若以transaction来描述一次client-server通讯,则如下图所示:
+------+ +-------------+ +------+
|Client| |Binder Driver| |Server|
+---+--+ +-------+-----+ +------+
| | |
| [BC_TRANSACTION] | |
+--------------------------> | |
| data(Parcel) +---------------------+ |
| | find server process | |
| | <-------------------+ |
| | |
| [BC_TRANSACTION_COMPLETE] | [BR_TRANSACTION] |
| <--------------------------+-----------------------------> |
| | data(Parcel) |
| | |
+-----------------+ | +----------------+
|wait for response| | | process data |
| <---------------+ | +--------------> |
| | |
| | [BC_REPLY] |
| | <-----------------------------+
| +-------------------+ result(Parcel) |
| |find client process| |
| +-----------------> | |
| | |
| [BR_REPLY] | [BR_TRANSACTION_COMPLETE] |
| <--------------------------+-----------------------------> |
| result(Parcel) | |
| | +----------------+
| | | wait for next |
| | +--------------> |
| | |
+ + +
ServiceManager启动过程
ServiceManager是Binder机制的核心组件之一,扮演着Binder通讯中Context Manager的角色,通过负责管理Binder系统中的Service组件,并向Client组件提供获取Service Proxy对象的服务。
ServiceManager运行在独立进程中,与其通讯需采用Binder机制,所以ServiceManager算是一个特殊的Service组件。
ServiceManager由init进程负责启动,在系统启动的时候启动:
service servicemanager /system/bin/servicemanager
user system
critical
onrestart restart zygote
onrestart restart media
- servicemanager以服务方式启动
- critical表明当服务退出时,系统会立刻重启servicemanager。
- onrestart参数表明,当servicemanager重启时,zygote和media也需要重启。
进程启动后,有以下三个初始化的步骤:
- 调用函数binder_open打开设备文件/dev/binder,以及将其映射到本进程的内存空间。
- 调用binder_become_context_manager将自己注册为Binder系统的context manager。
- 调用binder_loop来循环等待和处理Client进程的通讯请求。
获取Binder Proxy的过程
简略过程如下图所示:
+------+ +-------------+ +-------------+
|Client| |Binder Driver| |ServerManager|
+---+--+ +-------+-----+ +----------+--+
| | |
| [BC_TRANSACTION] | |
+--------------------------> | |
| target service name(Parcel)+-----------------------------+ |
| | find servermanager process | |
| | <---------------------------+ |
| | |
| [BC_TRANSACTION_COMPLETE] | [BR_TRANSACTION] |
| <--------------------------------------------------------> |
| | |
| | |
+-----------------+ | +-----------------------------+
|wait for handler | | |[CHECK_SERVICE_TRANSACTION] |
| <---------------+ | +---------------------------> |
| | |
| | [BC_REPLY] |
| | <-----------------------------+
| +---------------------+ target service info |
| | create Binder Ref | |
| +-------------------> | |
| | |
| [BR_REPLY] | [BR_TRANSACTION_COMPLETE] |
| <--------------------------------------------------------> |
| Binder Ref Handler | |
| | +----------------+
| | | wait for next |
| | +--------------> |
+--------------------+ | |
| create Binder Proxy| | |
| <------------------+ | |
| + +
|
| communicate with target Service
+------------------------------------------------------------>
+
- Client获取ServerManager的Proxy对象。
- Client向ServerManager的Proxy对象请求获取目标service的handler。
- ServerManager根据Client传入的service名称寻找目标service的信息,生成binder_ref,返回给client。
- Client根据binder_ref生成proxy对象。
- Client和目标Service进行进行进程间通讯。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。