Android Binder 原理二

上一篇文章总结了AIDL的常见使用,并借此分析了Binder的上层原理。这里再跟大家讲一讲Binder偏底层一点的东西。

首先,我们来讲一讲为什么要用Binder来实现IPC。我们都知道Android 是基于Linux内核开发的,而Linux关于IPC有共享内存、管道、消息队列和Socket等方式。那为什么还需要再开发一套Binder机制呢。

Binder机制是基于性能、稳定性和安全性几个方面考虑的。

性能

Socket 主要是用于通信较频繁的场景下使用,通常开销比较大。

管道和消息队列 采用存储转发的方式。数据从发送方缓存区拷贝到内核缓存区,再从内核缓存区拷贝到接收方的缓存区。经历了两次数据拷贝。

共享内存 虽然没有数据的拷贝,但是很难做控制,难以使用。

Binder 只需要一次数据拷贝。首先Binder驱动在内核空间开辟了一个数据接收缓存区,并用内存映射mmap建立内核缓存区跟数据接收缓存区将的映射,以及数据接收缓存区跟用户空间地址的映射。发送方通过系统调用copyFromuser将数据从用户端拷贝到内核缓存区,由于内核缓存区跟用户空间地址存在映射,等于是把数据拷贝到了用户端。

稳定性

Binder基于C/S架构,职责明确,分工清晰,只需要一次数据拷贝,性能较好,而共享内存虽然不需要数据拷贝,但是控制复杂,难以使用。从稳定性来说,Binder是优于共享内存的。

安全性

 传统的IPC无法获取用户的UID和PID,只能在数据包里面加入UID和PID,但是这样容易被篡改。而Binder既支持实名Binder,又支持匿名Binder,安全性高。

Binder的通信模型

前面我们介绍过Binder是基于C/S架构,由一系列组件构成,包括Client、Server、ServiceManager和Binder驱动。其中Binder驱动运行在内核空间,Client、Server、ServiceManager都是运行在用户空间,当然运行在不同的进程。Client、Server由应用程序提供,而ServiceManager跟Binder驱动都是由系统提供。Client、Server、ServiceManager都是通过系统调用open、mmap、ioctl访问设备的/dev/binder,  从而实现与Binder驱动的交互来实现跨进程间通信。他们之间的关系就类似于我们通过浏览器访问网站一样

Client是浏览器,浏览器访问网址,首先要通过路由器(Binder驱动),来访问DNS服务器(ServiceManager)来查询网址对映的IP地址(Server)。

最后再总结一下 Android 几种IPC的区别。

Bundle  能实现android 四大组件之间的传递数据,数据类型仅支持基本数据类型,以及继承了Parcelable和Serializable的类,

AIDL 功能强大,可以支持一对多的并发通信,需要处理线程同步。

文件 无法实现实时的交互,不适合高并发的场景

网络

Socket 功能强大,支持一对一实时通信,操作比较复杂,不支持直接RPC

Messenger数据用Message进行传递,支持Bundle类型的数据,不能RPC, 适合低并发下一对多的即时通信。

你可能感兴趣的:(Android Binder 原理二)