Android进阶(六)Binder机制
一、进程通信
1、进程隔离:
进程隔离是为保护操作系统中进程互不干扰而设计的一组不同硬件和软件的技术。进程数据不共享,进程A的虚拟地址和进程B的虚拟地址不同,这样就防止进程A将数据信息写入进程B,保证了数据的安全性。
- 进程空间分为内核空间和用户空间,内核空间(Kernel)是系统内核运行的空间。用户空间(User Space)是用户程序运行的空间,他们之间是隔离的。
- 内核有访问的所有权限,用户空间也可以通过系统接口去访问内核空间。用户空间可以通过内核空间(类似于中介者)进行相互访问。
2、Linux进程间IPC方式:
- 管道
- 消息队列
- 共享内存
- 套接字
- 信号量
- 信号
Linux 下的传统 IPC 通信原理:
传输过程:
内存缓存区 --> 内核缓存区 --> 内存缓存区,需要 2 次数据拷贝;
3、Binder机制的特点
(1)传输性能
- Binder数据拷贝只需要一次,而消息队列、管道、Socket等需要两次,共享内存一次拷贝都不需要。Binder性能仅次于共享内存。
(2)稳定性
- Binder基于C/S架构,Server端和Client端相对独立,稳定性好。
- 共享内存没有Server端和Client端的区分,可能存在同步死锁等问题。Binder稳定性优于共享内存。
(3)安全性
- 传统的Linux通信方式无法获取对方进程的UID,所以访问接入点是开放的,不安全。
- Android为每个应用程序分配了自己的UID,作为自身的标识。Binder的方式可以通过UID建立私有通道,Binder的安全性更高。
二、Binder机制实现原理
1、内存映射
Binder IPC正是基于内存映射(mmap)来实现的
Binder通信过程:
- 首先 Binder 驱动在内核空间创建一个数据接收缓存区;
- 接着在内核空间开辟一块内核缓存区,建立内核缓存区和内核中数据接收缓存区之间的映射关系,以及内核中数据接收缓存区和接收进程用户空间地址的映射关系;
- 发送方进程通过系统调用 copy_from_user() 将数据 copy 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。
2、Binder通信模型
- 包括 Client、Server、ServiceManager、Binder 驱动。
- 其中 Client、Server、Service Manager 运行在用户空间,Binder 驱动运行在内核空间。
- 对于Client,Binder是Server本地对象的一个引用,这个引用实际上是一个代理对象,Client通过这个代理对象来间接访问Server的本地对象。
- 对于Server,Binder是提供具体实现的本地对象,需向ServiceManager注册。
- Binder驱动是连接Client来Server的桥梁,负责将代理对象转化为本地对象,并将Server的执行结果返回给Client。
- ServiceManager它保存了Server Binder字符名称和Binder引用的映射,Client通过它来找到Server的Binder引用。
3、Binder通信过程:
- 一个进程使用 BINDERSETCONTEXT_MGR 命令通过 Binder 驱动将自己注册成为 ServiceManager;
- Server 通过驱动向 ServiceManager 中注册 Binder,表明可以对外提供服务。驱动为这个 Binder 创建位于内核中的实体节点以及 ServiceManager 对实体的引用,将名字以及新建的引用打包传给 ServiceManager,ServiceManger 将其填入查找表。
- Client 通过名字,在 Binder 驱动的帮助下从 ServiceManager 中获取到对 Binder 实体的引用,通过这个引用就能实现和 Server 进程的通信。
三、AIDL
1、AIDL使用的基本步骤
(1)生成AIDL接口(new->AIDL->AIDL File)
interface MyWindowManager {void sysout();
}
复制代码
生成AIDL文件之后,比起以前多了一个叫做 aidl 的包,而且他的层级是和 java 包相同的。
(2)编译MyWindowManager.aidl生成Java文件
public interface MyWindowManager extends android.os.IInterface {/** Local-side IPC implementation stub class. *///Stub 继承 Binder, 说明它是一个 Binder 本地对象;实现 IInterface 接口,表明Server可以提供的方法public static abstract class Stub extends android.os.Binderimplements com.example.myview.binder.MyWindowManager {private static final java.lang.String DESCRIPTOR = "com.example.myview.binder.MyWindowManager";/** Construct the stub at attach it to the interface. */public Stub() {this.attachInterface(this, DESCRIPTOR);}public static com.example.myview.binder.MyWindowManager asInterface(android.os.IBinder obj) {if ((obj == null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin != null) && (iin instanceof com.example.myview.binder.MyWindowManager))) {return ((com.example.myview.binder.MyWindowManager) iin);}return new com.example.myview.binder.MyWindowManager.Stub.Proxy(obj);}@Overridepublic android.os.IBinder asBinder() {return this;}@Overridepublic boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)throws android.os.RemoteException {......return super.onTransact(code, data, reply, flags);}//Binder本地代理对象private static class Proxy implements com.example.myview.binder.MyWindowManager {private android.os.IBinder mRemote;Proxy(android.os.IBinder remote) {mRemote = remote;}@Overridepublic android.os.IBinder asBinder() {return mRemote;}public java.lang.String getInterfaceDescriptor() {return DESCRIPTOR;}@Overridepublic void sysout() throws android.os.RemoteException {android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_sysout, _data, _reply, 0);_reply.readException();} finally {_reply.recycle();_data.recycle();}}}static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_sysout = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);}public void sysout() throws android.os.RemoteException;
}
复制代码
- MyWindowManager继承了IInterface,是Client和Server通信的接口
- Stub为静态抽象内部类,继承了Binder。其子类需要实现MyWindowManager接口,是Server的Binder的本地对象
- Stub.Proxy为静态内部类,内部包含了IBinder对象,是Server在Client中的本地代理对象,将参数序列化后交给mRemote处理,实现了跟远程Stub的通信
- asInterface方法通常是Client在bindService成功后,由Client来调用的,作用是将绑定成功后返回的IBinder对象转换为具体的IInterface接口。Client拿到这个IInterface接口后跟Server进行通信
(3)Server端提供方法的具体实现
public class MyWindowManagerService extends Service {@Nullable@Overridepublic IBinder onBind(Intent intent) {return mWindowManager;}private final MyWindowManager.Stub mWindowManager = new MyWindowManager.Stub() {@Overridepublic void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble,String aString) throws RemoteException {}@Overridepublic void sysout() throws RemoteException {Log.e("hj", "sysout: " );}};}
复制代码
(4)其他进程的Activity实现跟Service的通信
public class MainActivity extends AppCompatActivity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);Intent intent = new Intent(this, MyWindowManagerService.class);bindService(intent, mConnection, Context.BIND_AUTO_CREATE);}ServiceConnection mConnection = new ServiceConnection() {@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {MyWindowManager windowManager = MyWindowManager.Stub.asInterface(service);try {windowManager.sysout();} catch (RemoteException e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {}};
}
复制代码
2、IBinder/IInterface/Binder/BinderProxy/Stub
- IBinder : IBinder 是一个接口,代表了一种跨进程通信的能力。只要实现了这个借口,这个对象就能跨进程传输。
- IInterface : IInterface 代表的就是 Server 进程对象提供了哪些方法
- Binder : Java 层的 Binder 类,代表的其实就是 Binder 本地对象。Proxy 类是 Binder 类的一个内部类,它代表远程进程的 Binder 对象的本地代理;这两个类都继承自 IBinder, 因而都具有跨进程传输的能力;实际上,在跨越进程的时候,Binder 驱动会自动完成这两个对象的转换。
- Stub : AIDL 的时候,编译工具会给我们生成一个名为 Stub 的静态内部类;这个类继承了 Binder, 说明它是一个 Binder 本地对象,它实现了 IInterface 接口,表明它具有 Server 承诺给 Client 的能力;Stub 是一个抽象类,具体的 IInterface 的相关实现需要自己实现。
参考文章:
Android Binder设计与实现 - 设计篇
为什么 Android 要采用 Binder 作为 IPC 机制?
写给 Android 应用工程师的 Binder 原理剖析
Android进阶(六)Binder机制相关推荐
- Android深入浅出之Binder机制
Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的.所以搞明白B ...
- [Innost]Android深入浅出之Binder机制
ZZ FROM:http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html ============================== ...
- Android深入浅出之Binder机制(转)
Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Binder机制来和客户端通讯交互的.所以搞明白B ...
- android深入浅出binder机制,Android深入浅出之Binder机制.pdf
Android深入浅出之Binder机制 Android深入浅出之Binder机制 一 说明 Android系统最常见也是初学者最难搞明白的就是Binder了,很多很多的Service就是通过Bind ...
- (zz)Android深入浅出之Binder机制
Android深入浅出之Binder机制 原文地址:http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html 一 说明 Android ...
- Android之通过Binder机制实现IPC和linux的传统IPC的对比分析
一. Android的Binder机制实现IPC 这里bind机制实现实现IPC模型这里不具体分析,简单理解就是clint-server模型 涉及到4个模块client.server.serverMa ...
- Android中的Binder机制
来自:http://www.cnblogs.com/innost/archive/2011/01/09/1931456.html 一说明 Android系统最常见也是初学者最难搞明白的就是Binder ...
- 从源码角度分析Android中的Binder机制的前因后果
为什么在Android中使用binder通信机制? 众所周知linux中的进程通信有很多种方式,比如说管道.消息队列.socket机制等.socket我们再熟悉不过了,然而其作为一款通用的接口,通信开 ...
- Android为什么采用Binder机制
Android采用Binder作为IPC机制有什么优点? 首先我们为您先来概括性地说说Linux现有的所有进程间IPC方式: 管道:管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系 ...
- Android进阶(六)文件读操作
Android中文件的读写操作与Java中文件的读写操作是有区别的.在Java中,读文件操作如以下代码所示: public class FileRead { private static final ...
最新文章
- 群晖服务器性能测试,原创首发!群晖J3455 G4560 I7 4770HQ功耗性能测试!
- JavaScript复制内容到剪贴板
- [算法总结] 13 道题搞定 BAT 面试——字符串
- 从零开始学前端:定时器、Math对象 --- 今天你学习了吗?(JS:Day12)
- 微擎 php开发手册,目录结构
- EBS相关日志和参数
- javaweb学习笔记(XML基础)
- 华为路由设置虚拟服务器命令,华为路由器配置ip命令
- 数仓建模—数据资产管理
- __builtin_choose_expr
- 被称为偏执的企业家,他成功跻身中国民企500强
- 【键盘】jQuery+CSS3模拟键盘事件(精)
- 深度学习-深度学习集群管理方案
- 龙ol服务器维护补偿boss,龙OL副本BOOS位置攻击属性及掉落物品介绍
- 制作DeepLabV3Plus训练集
- solidity投票合约在bcos上的部署及解析(三)
- 我看车展感(tu)想(cao)
- 如何迁移操作系统到ssd固态硬盘?
- 物联网卡智能净水器打造智慧洁净生活
- 转让测绘资质,转让天津测绘资质