Binder机制可以说是Android系统中最难理解的一个部分了,这次结合Linux的内存管理来彻底理解它的通信原理。
在看介绍Binder的一些文章中,经常会提到用户空间地址和内核空间地址,这里需要先了解下它的概念。内存,是一块N字节大小的单元组成的数组,每个单元都有唯一的一个物理地址。在早些的系统中,由于当时的程序体积较小,内存一般够用,所以我们可以直接通过物理地址进行访问。但随着程序体积的增大,内存不够用了,所以在程序运行时,我们只需要将当下需要的数据加载进内存,其它数据可以放在磁盘上。因此,我们为每个进程分配虚拟地址,虚拟地址通过mmu映射成真实的物理地址。
未使用MMU时,CPU执行单元发出的是物理地址,使用MMU时,发出的是虚拟地址,通过映射转换成物理地址。
在32位的操作系统,每个进程一开始被分配到2^32,4G大小的虚拟地址。其中0-3G是用户空间,3-4g是内核空间。用户空间没有权限直接访问内核空间,但内核空间有权限直接访问用户空间。且内核空间是所有进程共享的。
Binder机制的核心就是利用内核空间和用户空间的共享数据的原理来实现进程间通信。Linux系统中的mmap,借助的是硬盘文件与内存地址之间形成一个映射关系,操作这块内存并可以直接操作该文件。但是android中,并不存在这么一个文件。Android借助是/dev/binder驱动,在内核空间中开辟了一块接收缓存区,并将之与用户空间地址进行了映射。所以通过这个映射关系,接收方在用户空间中就可以访问到接收缓存区中的数据,不需要再次进行拷贝。同时,接收缓存区与内核缓存区同样建立了映射关系,当内核空间copy data from 用户空间时,将数据拷贝到内核缓存区。至此 接收方便可以访问到这些数据了。整个过程,只用了一次拷贝。