传统IPC传输数据
Android系统内核是Linux,每个进程有自己的虚拟地址空间,在32位系统下最大是4GB,其中3GB为用户空间,1GB为内核空间;每个进程用户空间相对独立,而内核空间是一样的,可以共享。但是用户空间和内核空间是隔离开的,无法互相访问,传统的IPC传输数据需要借助copy_from_user和copy_to_user两个系统调用,把用户/内核空间内存中的数据拷贝到内核/用户空间的内存中,这样的话,如果两个进程需要进行一次单向通信则需要进行两次拷贝

Binder传输数据
Binder单次通信只需要进行一次拷贝,因为它使用了内存映射(memory map),将一块物理内存(若干个物理页)分别映射到接收端用户空间和内核空间,达到用户空间和内核空间共享数据的目的
- 数据发送(client)进程通过copy_from_user()将数据从用户空间拷贝到了内核空间
- 数据接收(server)进程通过mmap将内核空间的内存地址映射到了用户空间
- 只要client将数据拷贝到内核空间,那么server进程就可以直接读取到内核空间的数据,无需再次拷贝

Binder驱动是什么
传统的 Linux 通信机制,比如 Socket,管道等都是内核支持的。但是 Binder 并不是 Linux 内核的一部分,它是怎么做到访问内核空间的呢?Linux 的动态可加载内核模块(Loadable Kernel Module,LKM)机制解决了这个问题:模块是具有独立功能的程序,它可以被单独编译,但不能独立运行。它在运行时被链接到内核作为内核的一部分在内核空间运行。这样,Android系统可以通过添加一个内核模块运行在内核空间,用户进程之间通过这个模块作为桥梁,就可以完成通信了。这个运行在内核空间的,负责各个用户进程通过 Binder 通信的内核模块叫做 Binder 驱动
Binder与传统IPC对比
传统的Linux IPC机制:
- 管道:在创建时分配一个page大小的内存,缓存区大小比较有限
- 消息队列:信息复制两次,额外的CPU消耗;不合适频繁或信息量大的通信
- 共享内存:无须复制,共享缓冲区直接付附加到进程虚拟地址空间,速度快;但进程间的同步问题操作系统无法实现,必须各进程利用同步工具解决
- 套接字:作为更通用的接口,传输效率低,主要用于不通机器或跨网络的通信
- 信号量:常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段
- 信号: 不适用于信息交换,更适用于进程中断控制,比如非法内存访问,杀死某个进程等

浙公网安备 33010602011771号