前言概述
Binder网上有很多文章要么讲的深入全是LInux内核指令C语言分析,要么空洞无脑。这里个人理解整理如下。
- 什么是Binder:
1.Binder是一个类实现了IBinder接口,目的就是为了IPC服务而存在的。进程间通信的必须依赖的东西。
2.Binder是ServiceManager连接各种Manager(ActivityManager、WindowManager…….)和相应的系统底层ManagerService的桥梁。
3.Binder本意就是一个驱动程序,提供设备文件在Framework/dev/binder。
- 什么是IPC(Inter-Process Communication)
1.IPC是跨进程(由于Andoird每个APP都至少是拥有一个进程)也可理解跨应用间通信,可以对比(Handler是线程间通信的桥梁).
2.Android每个应用都单独拥有一个Pid(进程ID),相互调用数据就需要IPC,但是Adroid OS 不允许我们直接像对象一样调用方法获取数据,所以我们需要Binder驱动IPC通信。
3.Binder的IPC与一般IPC的区别
我们都知道且最常用的Socket也是IPC通讯,通用的网络通讯方式,但是建立Socket连接销毁都有一定的开销;消息队列和管道采用存储-转发方式,即数据先从发送方缓存区拷贝到内核开辟的缓存区中,然后再从内核缓存区拷贝到接收方缓存区,数据传递至少有两次拷贝过程,所以对于移动应用效率不行,考虑IPC之间的安全问题,以及Binder支持1对多,Android OS就使用自己的驱动Binder来服务IPC;
理解IPC需要关注的几个点
ServiceManager
系统服务和我们自定义服务可以存放的地点,内部HashMap(String, IBinder)存放Binder,通过这个类我们可以获取到系统提供的服务流程大概如此为什么通过Binder就能够跨进程了呢?
首先我们的Android OS 进程数据共享图
IOCTL就是用户空间与内核交互数据的驱动函数。
通过这一点我们就肯定知道Binder是肯定能够在内核空间与用户空间之间传递数据才能够实现我们需要IPC,下图也就是我们Binder干的事情;
这也使得我们实现Aidl来进行跨进程语言自定义类型的时候为什么要序列化对象,才能够实现IPC通信,因为底层并不认识JAVA对象,需要parcelable序列化后,实现writeToParcel与readFromParcel,来实现IPC通信。Parcel就是我们进程间数据保存的一个容器。,把数据写入到Parcel,Binder对其解析送到远程服务端,由远程服务端再次解析执行对应的函数,又通过Binder来返回到用户进程.
怎么使用系统服务呢?
//获取WindowManager服务引用
WindowManager wm = (WindowManager)getSystemService(getApplication().WINDOW_SERVICE); //AudioService 》AudioManager
// NotificationManagerService》 NotificationManager
//
其实JAVA中这部分的服务大部分都有一个供用户空间使用的manager类,这就是一个最正常的RPC调用,用户通过调用xxxManager的方法,实际上被Binder给迁移到系统服务进程中对应的SystemManagerService中对应的方法,并将结果再通过binder带回。
总结
本文只是对Binder机制的一些个人理解总结,并没有深入研究,
可参考老罗blog,有时间自己还是要从源码去深入理解下。
如何在最新版AS2.2版本下使用Aidl创建自定义类型的远程服务,见下篇Blog!