1、进程隔离
需要明白,不同进程的应用,彼此之间,数据是相对隔离的,即应用 A 不能 直接 访问另外一个进程的应用 B ,换句话说,不同进程的应用甚至都可能不知道另外的进程中的应用的存在。
在android系统中,这种进程间的隔离是通过「虚拟地址空间」来实现的。一个进程想要访问另外一个进程,需要使用特定的机制才可以。
2、Linux 中的两种空间
两种空间分别为
-
用户空间
-
内核空间
用户空间
:即上层应用层次的空间,由于进程隔离,不同进程间的应用空间是彼此独立的、互不感知的,这样做的好处是保证了彼此的数据安全。
内核空间
:是 linux kernel-linux 内核层工作的所处空间,为了保证系统的独立与安全,内核空间和用户空间保存相对的独立,用户空间只有在经过特定的系统机制调用才能访问到内核空间,但是相反,内核层访问用户层那当然轻而易举,但是系统内核一般不会主动访问用户空间数据。内核空间是独一份的,而用户空间可以是多份的。内核层的独立设计,既保证了系统能够稳定的运行,也支持了用户空间之间的相互访问,同时也节省了系统的内存空间,存取更加高效。
附:Kernel Space 定义链接
3、系统调用
根据内核空间的定义,如果用户空间想要访问内核空间,必须要经过system call
系统调用 ,如果要我们设计系统的话,为了保证我们自己系统的安全运行,用户软件肯定不能轻易的访问我们设定的系统,但是为了让软件更加的易用好用,我们又不得不开放一些系统的访问权限,所以我们也会设定特定的方法来让应用去访问,思路是相通的。
4、内核模块/驱动
由第三点,我们知道了,用户空间想要访问内核空间必须经过「系统调用」,然而,用户的需求并不简单,我们有时还需要去访问另外一个应用的应用空间,那这该怎么办呢?
Linux 系统其实提供了一些方式,比如 socket ,管道。
socket 和管道都是 Linux 内核支持的,用户空间可以通过这些方式进行"进程间的通信"。
而 Android 系统,虽然他属于 Linux 系统,但是 Android 并没有用 socket 和管道,而是选择了 Binder ,而 Binder 他并不是 Linux 内核支持的,那么 Binder 是以一种什么形式存在的呢?
Linux 的「动态可加载内核模块」(Loadable Kernel Module) 机制,解决了这个问题
注意:这里的模块是一个具有独立功能的程序,他可以被独立编译,但是不能够独立运行,它需要被链接到内核,作为内核的一部分在内核空间运行
依托于这种 「动态可加载内核模块机制」,Android 只需提供一个「内核模块」运行于「内核空间」,用户依托这个「内核模块」完成进程间的通信。
在 Android 中,运行于内核空间,通过 「Binder」 完成进程间通信的内核模块就是「Binder驱动」。
5、为什么使用 Binder 驱动呢?
为什么 Android 不沿用 Linux 的已经存在的方式:socket、System V、管道,而是采用 Binder 驱动呢?
其实可以从两方面考虑:
-
性能方面
Android 作为运行在移动终端的系统,性能是必须要考虑的,Binder 驱动的方式可以有效的节省 数据拷贝的时间(只需要从「发送方的数据缓存区』拷贝到「内核缓存区」即可,「接收方的数据缓存区」和「内核缓存区」是映射到同一块物理地址上的,从而有效节省了数据拷贝的时间) -
安全方面
传统的 Linux 进程间通信方式无法获得对方进程可靠的 PID、UID,也就无法鉴别对方的身份,对方可以修改上层协议搞破坏
Binder 驱动 对每个进程分配了 PID 和 UID,且在 Binder 通信时对 PID 和 UID 进行了有效性验证,大大提升了安全性。
6、Binder 驱动的工作原理
附图解:为了做这个图,把 AE 也学了,也是醉了

7、IBinder/Binder/IInterface/BinderProxy/Stub/Proxy
- IBinder 是一个接口,实现了此接口的类 均会具备 跨进程传输的特性,换句话说,只有实现了 IBinder 接口,才能进行跨进程传输,aidl 中的Stub 类 继承自 Binder 类,而 Binder 类实现了 IBinder 接口,所以具备跨进程通信的能力
- IInterface 也是一个接口,他声明了 被远程的服务端具备什么样的能力,比如,我们在创建出来的 AIDLInterface.aidl 中 加入了一个getImage() 的方法,那么其实就是声明了,服务端具备 getImage() 这样的能力
- Binder 是 IBinder 的实现类,他是被远程的服务端特有的类,由于Binder 实现了 IBinder 接口,所以是可以进行进程间传递的;
- 而 BinderProxy 同样继承了 IBinder 接口,所以同样支持进程间传输,同时,他还是 Binder 类的内部类,是 Binder 在客户端的本地代理,与Binder 具备相像的能力,客户端在远程调用服务端时,实际上是调用了BinderProxy 这个类,Binder 驱动在内核层完成了 Binder 和 BinderProxy 之间的相互转化
- Stub 是使用aidl时,编译后生成的一个IInterface 接口的内部类,首先Stub 继承了Binder类,即实现了IBinder接口,说明他可一进行进程间传输;其次Stub还实现了IInterface接口,说明他还声明了服务端具备的能力,Stub内部有一个Proxy 类,这个类就是Stub类的代理类,用于客户端进程的调用,Stub类还是一个抽象类,目的是让我们自定义服务端承诺给客户端的能力。
未完,待续。。。
网友评论