【Android】进程间通信——Binder

文章目录

  • 引言
  • Binder驱动
  • ServiceManager
    • 启动ServiceManager
      • 内存机制:bind_mmap
    • 获取ServiceManager
    • 服务注册
    • 服务获取

使用: 系统工程师、 应用工程师

引言

【Android】进程间通信——Binder_第1张图片Client,Server,Service Manager之间交互都是虚线表示,是由于它们彼此之间不是直接交互的,而是都通过与Binder驱动进行交互的

【Android】进程间通信——Binder_第2张图片

【Android】进程间通信——Binder_第3张图片
【Android】进程间通信——Binder_第4张图片

Binder驱动

【Android】进程间通信——Binder_第5张图片binder请求码,以”BC_“开头,简称BC码,用于从IPC层传递到Binder Driver层;
binder响应码,以”BR_“开头,简称BR码,用于从Binder Driver层传递到IPC层;

对于请求码为BC_TRANSACTION或BC_REPLY时,会执行binder_transaction()方法

ServiceManager

启动ServiceManager

【Android】进程间通信——Binder_第6张图片[-> service_manager.c] svcmgr_handler()
1.do_add_service//注册指定服务 2.do_find_service//根据名称查找相应服务
【Android】进程间通信——Binder_第7张图片
驱动设备的四大操作:初始化(binder_init),打开 (binder_open),映射(binder_mmap),数据操作(binder_ioctl)
【Android】进程间通信——Binder_第8张图片

内存机制:bind_mmap

虚拟进程地址空间(vm_area_struct)和虚拟内核地址空间(vm_struct)都映射到同一块物理内存空间。当Client端与Server端发送数据时,Client(作为数据发送端)先从自己的进程空间把IPC通信数据copy_from_user拷贝到内核空间,而Server端(作为数据接收端)与内核共享数据,不再需要拷贝数据,而是通过内存地址空间的偏移量,即可获悉内存地址,整个过程只发生一次内存拷贝
【Android】进程间通信——Binder_第9张图片

为何不直接让发送端和接收端直接映射到同一个物理空间,那样就连一次复制的操作都不需要了,0次复制操作那就与Linux标准内核的共享内存的IPC机制没有区别了,对于共享内存虽然效率高,但是对于多进程的同步问题比较复杂,而管道/消息队列等IPC需要复制2两次,效率较低

Binder在进程间数据通信的流程图,从图中更能明了Binder的内存转移关系。
【Android】进程间通信——Binder_第10张图片

获取ServiceManager

【Android】进程间通信——Binder_第11张图片由defaultServiceManager()返回的是BpServiceManager(单例)

  • 通过继承接口IServiceManager实现了接口中的业务逻辑函数;
  • 通过成员变量mRemote= new BpBinder(0)进行Binder通信工作
  • BpBinder通过handler来指向所对应BBinder, 在整个Binder系统中handle=0代表ServiceManager所对应的BBinder
    在这里插入图片描述
    getContextObject等价于new BpBinder(0);

defaultServiceManager 等价于 new BpServiceManager(new BpBinder(0));

ProcessState对象(单例)

  • 成员变量mDriverFD记录binder驱动的fd,用于访问binder设备
  • mmap的binder分配的默认内存大小为1M-8k,BINDER_VM_SIZE = (110241024) - (4096 *2),

服务注册

【Android】进程间通信——Binder_第12张图片

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工作,

【Android】进程间通信——Binder_第13张图片

  • 1.MediaPlayerService进程调用ioctl()向Binder驱动发送IPC数据

【Android】进程间通信——Binder_第14张图片

  • 2.Binder驱动收到该Binder请求,生成BR_TRANSACTION命令,选择目标处理该请求的线程,即ServiceManager的binder线程
  • 3.Service Manager的线程调用服务注册函数将服务”media.player”注册到服务目录中。当服务注册完成后,生成IPC应答数据(BC_REPLY)
  • 3.Binder驱动收到该Binder应答请求,生成BR_REPLY命令。在MediaPlayerService收到该命令后,知道服务注册完成便可以正常使用

BC_TRANSACTION和BR_TRANSACTION过程是一个完整的事务过程;BC_REPLY和BR_REPLY是一个完整的事务过程

服务获取

getService()->循环5次checkService()
【Android】进程间通信——Binder_第15张图片其中remote()为BpBinder

->BpBinder::transact()->

status_t status = IPCThreadState::self()->transact(
            mHandle, code, data, reply, flags);

你可能感兴趣的:(Android,binder,进程间通信,Android)