系统相关
首页 > 系统相关> > Android跨进程通信、Binder与Aidl

Android跨进程通信、Binder与Aidl

作者:互联网

Android为什么使用binder通信

Android系统中,涉及到多进程间的通信底层都是依赖于Binder IPC机制。例如当进程A中的Activity要向进程B中的Service通信,这便需要依赖于Binder IPC。不仅于此,整个Android系统架构中,大量采用了Binder机制作为IPC(进程间通信)方案。

当然也存在部分其他的IPC方式,如管道、SystemV、Socket等。那么Android为什么不使用这些原有的技术,而是要使开发一种新的叫Binder的进程间通信机制呢?

为什么要使用Binder?

性能方面

在移动设备上(性能受限制的设备,比如要省电),广泛地使用跨进程通信对通信机制的性能有严格的要求,Binder相对出传统的Socket方式,更加高效。Binder数据拷贝只需要一次,而管道、消息队列、Socket都需要2次,共享内存方式一次内存拷贝都不需要,但实现方式又比较复杂。【文章最下面有binder一次拷贝的解释】

安全方面

传统的进程通信方式对于通信双方的身份并没有做出严格的验证,比如Socket通信ip地址是客户端手动填入,很容易进行伪造,而Binder机制从协议本身就支持对通信双方做身份校检,因而大大提升了安全性。

Binder使用原理

首先我们看看我们的程序跨进程调用系统服务的简单示例,实现浮动窗口部分代码:

//获取WindowManager服务引用
WindowManager wm = (WindowManager)getSystemService(getApplication().WINDOW_SERVICE);  
//布局参数layoutParams相关设置略...
View view=LayoutInflater.from(getApplication()).inflate(R.layout.float_layout, null);  
//添加view
wm.addView(view, layoutParams);

注册服务(addService):在Android开机启动过程中,Android会初始化系统的各种Service,并将这些Service向ServiceManager注册(即让ServiceManager管理)。这一步是系统自动完成的。

获取服务(getService):客户端想要得到具体的Service直接向ServiceManager要即可。客户端首先向ServiceManager查询得到具体的Service引用,通常是Service引用的代理对象,对数据进行一些处理操作。即第1行代码中,得到的wm是WindowManager对象的引用。

使用服务:通过这个引用向具体的服务端发送请求,服务端执行完成后就返回。即第3行调用WindowManager的addView函数,将触发远程调用,调用的是运行在systemServer进程中的WindowManager的addView函数。

使用服务的具体执行过程 

Client就是房客,Server就是房东,ServiceManager就是房屋中介,每个Server如果要提供服务就必须要去ServiceManager那里去注册,ServiceManager在一张查找表中记录一个Server的名字,对应着Server的引用。Client想要获得Server,必须通过名字到ServiceManager取找Server的引用,获得这个Server的binder引用,通过这个binder引用去和Server通信。


1.client通过获得一个server的代理接口,对server进行调用。
2.代理接口中定义的方法与server中定义的方法时一一对应的。
3.client调用某个代理接口中的方法时,代理接口的方法会将client传递的参数打包成Parcel对象。
4.代理接口将Parcel发送给内核中的binder driver。
5.server会读取binder driver中的请求数据,如果是发送给自己的,解包Parcel对象,处理并将结果返回。
6.整个的调用过程是一个同步过程,在server处理的时候,client会block住。因此client调用过程不应在主线程。
7.client和ServiceManager也不是同一个进程,为什么不需要通过binder驱动来通信呢?因为对一般的Service组件来说,Client进程首先要通过Binder驱动程序来获取它的一个句柄值,然后通过这个句柄创建一个Binder代理对象,最后将这个Binder代理对象封装成一个实现特定接口的代理对象。ServiceManager也相当于一个service,是一个守护进程,但由于ServiceManager的句柄值为0,因此获取它的代理对象不需要跟Binder驱动程序进程交互。

Aidl的意义

1.aidl主要就帮助了我们完成了包装数据和解包的过程,并调用了transact过程,而用来传递的数据包我们就称为parcel,最终获取跨进程binder并调用其中相关内容

2.用aidl定义需要被调用方法接口,实现这些方法,调用这些方法

3.底层是binder。代码上就是接口,使用interface声明,但其中只能使用简单数据类型,复杂数据类型如某类则需要创新其对应aidl文件并实现相关函数才能使用

Aild的使用理解

以IPackageManager、PackageManager、PackageManagerService解释AIDL

比喻解释:

假设你是一个公司的商务负责人,正在和客户商谈事务,在涉及公司的具体业务的同事,你要请示你的老板,你需要给你老板打电话,交流商务谈判的具体细节,这里面,你就是应用进程里面的ApplicationPackageManager,IPackageManager就是你们的通信工具——电话,你老板就是SystemServer进程里面的PackageManagerService,你的电话就是IPackageManager.Stub.Proxy,老板的电话是IPackageManager.Stub。IPackageManager其实就是一个具体业务场景下的数据交换的工具而已。

 

Binder与Aidl

 

 

 

【为什么binder只使用了一次内存拷贝】

回忆下我们在Android中如果需要做文件读写操作,是不是必须要申请权限呢?为什么要申请呢? 因为用户空间的权限低于内核空间,但是用户空间又需要访问内核空间的资源 一般情况下,操作系统会提供一些系统调用接口,通过系统调用接口,用户程序可以在内核的控制下实现对内核资源的有限访问,这样既能保证满足应用程序的资源请求,又能保障系统安全和稳定。

传统IPC机制通信流程【共享内存机制除外】

标签:调用,Aidl,binder,进程,Binder,IPackageManager,ServiceManager,Android
来源: https://www.cnblogs.com/1118zjg/p/16009924.html