android的IPC机制 - Binder
来源:互联网 发布:电大网站美工期末 编辑:程序博客网 时间:2024/04/30 06:58
一 Binder提供的功能
1. 用驱动程序来推进进程间通信。
2. 通过共享内存的方式来提供性能
3. 为进程请求分配每个进程的线程池
4. 引用计数和跨进程的对象引用映射。
5. 进程间同步调用。
如上为Binder原理图:
Binder通信模型
Binder框架:
类比(互联网)理解:
Binder使用Client - Server通信方式:
1. 一个进程作为Server提供诸如视频/音频解码,视频捕获,地址本查询,网络连接等服务;
2. 多个进程作为 Client向Server发起服务请求,获得所需要的服务。
Client-Server通信据必须实现以下两点:
一是server必须有确定的 访问接入点或者说地址来接受Client的请求,并且Client可以通过某种途径获知Server的地址;
二是制定Command-Reply协议来传 输数据。
例子:
例如在网络通信中Server的访问接入点就是Server主机的IP地址+端口号,传输协议为TCP协议。
1. 对Binder而言,Binder可 以看成Server提供的实现某个特定服务的访问接入点, Client通过这个‘地址’向Server发送请求来使用该服务;
2. 对Client而言,Binder可以看成是通向Server的管道入口,要想和某个 Server通信首先必须建立这个管道并获得管道入口。
Binder驱动
驱动作用:
负责进程之间Binder通信的建立,Binder在进程之间的传递,Binder引用计数管理,数据 包在进程之间的传递和交互等一系列底层支持。
驱动和应用程序之间定义了一套接口协议:
主要功能由ioctl()接口实现,不提供 read(),write()接口,因为ioctl()灵活方便,且能够一次调用实现先写后读以满足同步交互,而不必分别调用write()和 read()。
Binder驱动的代码位于linux目录的kernel/drivers/staging/binder.c中。
ServiceManager与实名Binder
SMgr的作用是 (类似于DNS):
将字符形式的Binder名字转化成Client中对该Binder的引用,使得Client能够通过Binder名字获得 对Server中Binder实体的引用。
具体过程:
1. Server端:
Server创建了Binder的实体,为其取一个字符形式并可读易记的名字,将这个Binder连同名字以数据包的形式通过Binder驱动发送给ServerManager,通知SMgr注册一个名叫张三的Binder,它位于Server中。
2. 驱动端:
它为这个穿过进程边界的Binder,创建位于内核中的实体节点以及SMgr对实体的引用,并将名字及新建的引用打包传递给SMgr。
2. ServiceManager端:
Smgr收到数据包时,从中取出名字和引用填入一张查找表中。
这样,client就可以通过ServiceManager来获取Server中的binder实体的引用,从而可以进程间通信。
ServiceManager进程与Server进程? -> 也是进程间通信
这里面其实是两条线:
一. Server注册服务,创建binder并通知ServiceManager.
二. ServiceManager也作为Server端,注册了服务,创建了SMgr的binder实体,SMgr内核Binder实体,这样client端就可以利用SMgr内核Binder实体的引用来实现Binder的注册,查询和获取。
- SMgr提供的Binder比较特殊,它没有名字也不需要注册,当一个进程使用BINDER_SET_CONTEXT_MGR命令将自己 注册成SMgr时Binder驱动会自动为它创建Binder实体。
- 其次这个Binder的引用在所有Client中都固定为 0而无须通过其它手段获得。
也就是说,一个Server若要向SMgr注册自己Binder就必需通过0这个引用号和SMgr的Binder通信。
Client获得实名Binder的引用
Binder在应用程序中的表述 -- 具体需要参考AIDL使用去理解!
Binder在Server端的表述 - Binder实体
Binder内存映射和接收缓存区管理
fd = open("/dev/binder", O_RDWR);
mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
这样Binder的接收方就有了一片大小为MAP_SIZE的接收缓存区。mmap()的返回值是内存映射在用户空间的地址,不过这段空间是由驱动管理,用户不必也不能直接访问(映射类型为PROT_READ,只读映射)。
接收缓存区映射好后就可以做为缓存池接收和存放数据了。前面说过,接收数据包的结构为binder_transaction_data,但这只是消息头,真正的有效负荷位于data.buffer所指向的内存中。这片内存不需要接收方提供,恰恰是来自mmap()映射的这片缓存池。在数据从发送方向接收方拷贝时,驱动会根据发送数据包的大小,使用最佳匹配算法从缓存池中找到一块大小合适的空间,将数据从发送缓存区复制过来。要注意的是,存放 binder_transaction_data结构本身以及表4中所有消息的内存空间还是得由接收者提供,但这些数据大小固定,数量也不多,不会给接收方造成不便。映射的缓存池要足够大,因为接收方的线程池可能会同时处理多条并发的交互,每条交互都需要从缓存池中获取目的存储区,一旦缓存池耗竭将产生导致无法预期的后果。
有分配必然有释放。接收方在处理完数据包后,就要通知驱动释放data.buffer所指向的内存区。在介绍Binder协议时已经提到,这是由命令BC_FREE_BUFFER完成的。
通过上面介绍可以看到,驱动为接收方分担了最为繁琐的任务:分配/释放大小不等,难以预测的有效负荷缓存区,而接收方只需要提供缓存来存放大小固定,最大空间可以预测的消息头即可。在效率上,由于mmap()分配的内存是映射在接收方用户空间里的,所有总体效果就相当于对有效负荷数据做了一次从发送方用户空间到接收方用户空间的直接数据拷贝,省去了内核中暂存这个步骤,提升了一倍的性能。顺便再提一点,Linux内核实际上没有从一个用户空间到另一个用户空间直接拷贝的函数,需要先用copy_from_user()拷贝到内核空间,再用copy_to_user()拷贝到另一个用户空间。为了实现用户空间到用户空间的拷贝,mmap()分配的内存除了映射进了接收方进程里,还映射进了内核空间。所以调用copy_from_user()将数据拷贝进内核空间也相当于拷贝进了接收方的用户空间,这就是Binder只需一次拷贝的‘秘密’。
- Android的IPC机制-Binder
- android的IPC机制 - Binder
- Android的IPC机制Binder
- Android的IPC机制-Binder
- Android的IPC机制Binder
- Android Binder IPC机制
- 深入理解 Android 的 IPC 机制--------Binder
- Binder---- Android 的IPC 通信机制
- Binder---- Android 的IPC 通信机制
- Binder---- Android 的IPC 通信机制
- Binder---- Android 的IPC 通信机制
- 技术内幕:Android的IPC机制-Binder
- Binder---- Android 的IPC 通信机制
- 深入理解 Android 的 IPC 机制--------Binder
- Android的IPC机制——Binder
- Android IPC机制Binder解析
- Android IPC机制Binder解析
- Android IPC之Binder机制
- php isset empty 区别
- Android手机安全软件之设置电话拦截返回音浅析
- linux搭建FTP服务器的bash shell脚本
- Python开发环境Wing IDE使用手册之GTK和PyGObject
- 微信公共账号开发
- android的IPC机制 - Binder
- 数据结构-队列-顺序存储完整可执行代码
- linux 2.6&3.0 内核构造
- android 系统版本之strictmode使用
- 使用select函数改进客户端/服务器端程序
- sqlserver 连接远程主机及导入数据
- 流对象基本规律
- Apache "No services installed"问题的处理
- 【LeetCode】Longest Consecutive Sequence