首先是我为什么要写这篇文章,有几点原因:其一,市面上能讲清楚Binder的文章很少,而且很多文章会让人看的云里雾里,不知所云;其二,很多同学对这一块也不是很理解,尽管很多人已经工作了很多年。
我特地去查了一下Binder的英文翻译:
Binder机制其实是用于进程间通信的,可以理解为进程之间的粘合剂。
Binder到底是什么?
从机制,模型角度来说:Binder是一种Android中实现跨进程通信(IPC)的方式,用于实现Android中跨进程通信。【Binder机制】
从模型,结构组成来说:Binder是一种虚拟的物理设备驱动,链接Service进程,Client进程和Service Manager进程。【Binder驱动】
从Android代码实现角度来说:Binder是一个类,实现了IBinder接口,是Binder机制的在Android代码中的实现。【Binder类】
本文也将从Binder机制到Binder驱动,再到Binder类来层层深入。
在讲解Binder前,先普及一下linux的一些基础知识:
进程空间划分为用户空间和内核空间,进程之间用户空间的数据不可共享,内核空间数据可以共享。
来看一张图:
进程内用户空间 & 内核空间进行交互需通过 系统调用,主要通过函数:
copy_from_user和copy_to_user。
![](https://i-blog.csdnimg.cn/blog_migrate/3a4dd11c92b3f008b9fc700d786fb611.png)
IPC其中一种方式就是通过共享内存的方式,但是这种方式需要拷贝两次数据,很明显效率低下。而且接受进程也不知道所需要接受的数据大小,不知道需要多大的缓存,一般是开辟尽量大的空间,很明显会浪费空间。
内存映射在linux操作系统中非常重要,涉及到高效率的跨进程通信和文件操作。
/**
* 函数原型
*/
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
/**
* 具体使用(用户进程调用mmap())
* 下述代码即常见了一片大小 = MAP_SIZE的接收缓存区 & 关联到共享对象中(即建立映射)
*/
mmap(NULL, MAP_SIZE, PROT_READ, MAP_PRIVATE, fd, 0);
/**
* 内部原理
* 步骤1:创建虚拟内存区域
* 步骤2:实现地址映射关系,即:进程的虚拟地址空间 ->> 共享对象
* 注:
* a. 此时,该虚拟地址并没有任何数据关联到文件中,仅仅只是建立映射关系
* b. 当其中1个进程对虚拟内存写入数据时,则真正实现了数据的可见
*/
在Linux
系统下,根据内存映射的本质原理 & 特点,其应用场景在于:
- 实现内存共享:如 跨进程通信
- 提高数据读 / 写效率 :如 文件读 / 写操作
文件读/写操作:
传统linux操作系统文件操作流程:
使用内存映射文件读/写操作:
使用了内存映射的跨进程通信:
Binder跨进程通信的核心原理:
模型原理步骤说明: