介绍
通常在Android中,我们的每个App都是一个进程,App之间的通信是进程间通信(IPC),在Android中采用Binder机制进行IPC。
通信的含义
自然语言中,“通信“意为:交互信息。
计算机语言中,”通信“意为:交换数据,数据存在内存中。因此两个进程间要进行通信,就必须要能分别访问到对方的内存中的数据。
而在Android中,进程之间不能直接通信,通过Binder建立两个进程之间的连接。
需要储备的Linux IPC知识
(1)虚拟地址空间
Android是建立在Linux内核上的,因此进程间要进行数据交换,就必须要了解如何进行内存中的数据访问。
在编写程序过程中,并不能直接访问内存的物理地址,因此系统为我们提供了虚拟地址(逻辑地址)来给每个进程分配地址空间。
在32位的系统中,物理地址寻址大小为4G。虚拟地址空间(4G)又被分为:内核地址空间(1G)+用户地址空间(3G)。
普通的应用程序只能访问3G的用户空间,内核、驱动等运行在内核地址空间,每个进程内核地址空间是共享的。应用程序想要操作网络、磁盘等硬件资源需要通过内核来访问。
通常来说是通过:copy_from_user 和 copy_to_user 函数用来交换内核地址空间与用户地址空间的数据。
(2)虚拟地址如何映射到物理内存
图片每个进程分配的虚拟地址空间都是独立的,通过页表映射到物理内存,进而读写数据。进程的虚拟地址空间既然是独立的,那么各个进程之间自然无法直接访问。
(3)Linux IPC常用方式
a、共享物理内存。b、通过内核中转。
图片a、共享内存(共享物理内存):多个进程共享同一段物理内存,当某个进程改变内存内容时,其它进程都能够知道。此种方式无需拷贝内容,但是需要信号量进行进程间同步。
图片b、通过内核中转:先将A发送的内容拷贝到内核,这过程可以理解为存储,再从内核拷贝到B的用户空间,这过程可以理解为转发,因此一次"存储-转发"过程需要两次内容拷贝。
Binder通信方式
Linux提供了上述(还有其它的如信号量等)的IPC方式,但是由于每种方式都有其缺点,因此Android另起炉灶弄了另一种方式:Binder。
要搞懂Binder通信方式,首先要了解“内存映射”。
内存映射
图片"存储-转发"过程需要在用户空间和内核空间之间拷贝数据,还有一种不需要拷贝的方式:内存映射(mmap)。
如上图,进程空间与内核空间共享磁盘上的一个映射文件,当进程空间往映射文件写入数据后(此处不是真正的I/O,而是内存读写),相当于写入了内核空间,反之亦然。
图片进程A给进程B发送一段信息,流程如下:
1、进程A通过系统调用拷贝内容到内核空间。
2、由于内核空间与进程B做了内存映射,因此进程B能够知道内核空间的信息。
由此可知,通过Binder,进程A发送数据给进程B只进行了一次数据拷贝。
对比其他的IPC通信方式:
图片Binder优势:传统的IPC方式只能由使用者填入UID/PID,容易被外界仿造、篡改。而Binder内置为发送者添加UID/PID,更安全。
Android中的Binder使用
举个例子:APP进程调起手机系统的震动服务。
Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(1000);
- 解释:
* Binder进程间通信
* 原理:Binder使用C/S模式,也就是S(Server)端提供服务入口,C(Client)调用服务提供的接口,进而两者可以进行通信。
*
* 本例中:通过APP调起手机系统的震动服务
* APP进程 -->> Client
* system_service -->> Server
*
* Android系统启动后会开启名为:system_server的进程,顾名思义:系统服务,提供给所有App使用的公共服务进程。
* 当我们调用Context中的getSystemService(xx)方法的时候,相当于App进程与system_service(服务提供进程)进行了一次IPC过程
* 简单来说,通过ServiceManager获取Binder,该Binder连接system_server,ServiceManager跑在另外的进程里)。
* 参考文章:
* https://mp.weixin.qq.com/s/y2Qx9vwSpJIVItWLgxU1qg</pre>
网友评论