Binder进程通信的基本原理
基础
- Binder是基于
linux
驱动设备的,所以我们可以把Binder驱动当做文件设备打开 -
mmap
系统调用用于把一个设备或者文件的内存映射到自己应用程序的内存空间中 -
A
进程对Binder执行mmap
调用,然后A
内存空间中就有Binder的地址,即A
中可以修改Binder中内存的值,当然Binder中的修改也会影响到A
,于是当Binder去拷贝另一个应用程序B
的一部分内存到自己的内存空间时(Bidner的内存空间),A
就可以直接访问到拷贝过来的B
的内存空间了,间而实现了A
和B
的内存通信
ProcessState
ProcessState
是进程单例的,会去打开/dev/binder
驱动,并且mmap
到当前进程的内存空间
一个进程开始的时候就会初始化一个ProcessState
,然后就会去开始binder
线程池循环等待指令到来
IPCThreadState
IPCThreadState
是线程单例,会去和binder驱动
直接交互
BpBinder
Binder
的代理对象,其中主要就是持有mHandle
(编号),在和Binder驱动
交互的时候使用mHandle
来寻找Binder
服务,对应native
层的Binder
Binder驱动
binder_proc
在Binder驱动中,有一个binder_proc
的链头的通过binder_proc队列
持有了所有的binder
,相当于每一次的binder_open
的时候就会创建一个binder_proc
表示当前的binder
进程,并且把它添加到Binder驱动
红黑树上。
相当于每一次我们的进程打开的binder驱动
就会获得驱动上面的所有binder服务
所组成的链表,而我们发起IPC
的时候,就会根据binder服务
的编号进行寻找,然后就会去发起数据传递(就是修改binder驱动
内存中的值)然后循环等待反馈。对应的binder服务端
则会在服务注册的时候就一直循环等待客户端的连接。binder_ioctl
binder_ioctl()
函数负责在两个进程间收发IPC数据和IPCreply
数据。binder thread pool
Binder线程池
在进程frok
出来就会运行起来,即等待客户端的连接,但这个时候可能binder service
并没有注册。
binder驱动
找到对应的service
需要的进程
,service名字
,方法标记
。
思想
在一块大家都可以访问的内存中进行数据和指令的交换,而不同进程中主要靠thread
的循环等待指令(事件驱动),但是这样交互很繁杂,所以又抽离出了一个manager(ServiceManager
)
每一个进程开始的时候都会进行ProcessState
的初始化,会去打开驱动,并提供接口去获取mHandle=0
的Binder
,同时也会让自己的Binder线程池循环起来。
binder
的调动的是阻塞的,阻塞的原理还是循环。所以客户端的binder
IPC请求最好放到子线程去执行。