Client,Server,Service Manager之间交互都是虚线表示,是由于它们彼此之间不是直接交互的,而是都通过与Binder驱动进行交互的
binder请求码,以”BC_“开头,简称BC码,用于从IPC层传递到Binder Driver层;
binder响应码,以”BR_“开头,简称BR码,用于从Binder Driver层传递到IPC层;
对于请求码为BC_TRANSACTION或BC_REPLY时,会执行binder_transaction()方法
[-> service_manager.c] svcmgr_handler()
1.do_add_service//注册指定服务 2.do_find_service//根据名称查找相应服务
驱动设备的四大操作:初始化(binder_init),打开 (binder_open),映射(binder_mmap),数据操作(binder_ioctl)
虚拟进程地址空间(vm_area_struct)和虚拟内核地址空间(vm_struct)都映射到同一块物理内存空间。当Client端与Server端发送数据时,Client(作为数据发送端)先从自己的进程空间把IPC通信数据copy_from_user拷贝到内核空间,而Server端(作为数据接收端)与内核共享数据,不再需要拷贝数据,而是通过内存地址空间的偏移量,即可获悉内存地址,整个过程只发生一次内存拷贝
为何不直接让发送端和接收端直接映射到同一个物理空间,那样就连一次复制的操作都不需要了,0次复制操作那就与Linux标准内核的共享内存的IPC机制没有区别了,对于共享内存虽然效率高,但是对于多进程的同步问题比较复杂,而管道/消息队列等IPC需要复制2两次,效率较低
Binder在进程间数据通信的流程图,从图中更能明了Binder的内存转移关系。
由defaultServiceManager()返回的是BpServiceManager(单例)
defaultServiceManager 等价于 new BpServiceManager(new BpBinder(0));
ProcessState对象(单例)
defaultServiceManager()
-> addService(String16("media.player"), new MediaPlayerService());
-> status_t err = remote()->transact(ADD_SERVICE_TRANSACTION, data, &reply);
-> status_t status = IPCThreadState::self()->transact(mHandle, code, data, reply, flags);
Binder代理类调用transact()方法,真正工作还是交给IPCThreadState来进行transact工作,
BC_TRANSACTION和BR_TRANSACTION过程是一个完整的事务过程;BC_REPLY和BR_REPLY是一个完整的事务过程
getService()->循环5次checkService()
其中remote()为BpBinder
->BpBinder::transact()->
status_t status = IPCThreadState::self()->transact(
mHandle, code, data, reply, flags);