进程间通讯

Linux进程间通讯方式:管道、消息队列、共享内存、Socket

Binder产生的背景:为了方便程序开发,系统提供了大量服务,但只有Socket支持Client-Server模式,当然也可以在这些底层机制上架设一套协议来实现Client-Server通信,但这样增加了系统的复杂性,另外,Socket作为一款通用接口,其开销大传输效率低,主要用在跨网络的进程间通信;消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,至少有两次拷贝过程;共享内存虽然无需拷贝,但控制复杂,难以使用;还有一点是出于安全性考虑,使用传统IPC只能由用户在数据包里填入UID/PID,这样很容易被恶意程序利用,Android为每个安装好的应用程序分配了自己的UID,进程UID是由IPC机制本身在内核中添加,其次传统IPC访问接入点是开放的,无法建立私有通道,而Binder既有实名Binder也有匿名Binder

Binder内存映射:传统方式需要两次拷贝,用户空间->内核空间->用户空间,Linux使用copy_from_user()和copy_to_user()实现这两个跨空间拷贝,Binder采用一种全新策略:由Binder驱动管理接收缓存,其中,Binder驱动实现了mmap()系统调用,这样Binder的接收方就有了一片大小为MAP_SIZE的接收缓存区。mmap()的返回值是内存映射在用户空间的地址,不过这段空间是由驱动管理,用户不必也不能直接访问(映射类型为PROT_READ,只读映射),在效率上,由于mmap()分配的内存是映射在接收方用户空间里的,所有总体效果就相当于对有效负荷数据做了一次从发送方用户空间到接收方用户空间的直接数据拷贝,省去了内核转存这个步骤

fd = open("/dev/binder", O_RDWR);
mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);

Binder通讯模型:Server、Client、ServerManager、Binder驱动,首先ServiceManager提供Binder注册和查询服务,Server通过0号引用和ServiceManager通讯,将创建好的实体引用(Binder驱动自动完成实体到引用的转换过程)和对应的名字注册到ServiceManager中,然后,Client通过对应名字来查找ServiceManager中保存的实体引用

AIDL原理:AIDL(Android接口定义语言),支持的类型有:基本类型、String、CharSequence、ArrayList、HashMap、其他AIDL定义的AIDL接口(需要import、引用传递)、实现Parcelable的类(需要import、值传递)。自定义类型的三个步骤:实现Parcelable接口、新建aidl文件夹,在相同包名下,创建类同名的AIDL文件、在使用该类时,需要在头文件中import(parcelable Person)。我们要保证,在客户端和服务端中都有我们需要用到的.aidl文件和其中涉及到的.java文件,因此不管在哪一端写的逻辑,写完之后我们都要把这些文件复制到另一端去。在服务器端,我们是实现Stub内部类的接口实现(Stub是抽象类,继承了Binder类,实现了外层接口),并在onBind中返回给客户端。在客户端,我们是调用Stub类的asInterface方法(asInterface方法判断本地是否有IInterface的实例,如果有直接返回,否则把IBinder实例传给Proxy类,返回Proxy类的实例

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

little-sparrow

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值