Binder机制原理

Binder机制原理Binder是什么?可以理解为Android的血管。是一种进程间通信的机制。比如Activity,Service需要和AMS通信的时候,就需要Binder除了进程间通信,也可以把Binder理解为一种虚拟物理设备驱动。虚拟表示没有实体,和键盘鼠标不一样。Binder是虚拟的。在应用层,也可以把Binder理解为一个是一个能发起进程间通信的Java类为什么是Binder?Linux也有一些很优秀的进程间通信机制,例如管道,消息队列,共享内存,socket等,但是为什么Android使用Binder而

前言

本篇文章记录本人对Binder的学习,因为本人能力有限,若有错误,还请批评指正。
binder的使用文章推荐

1.Binder是什么?

  • 可以理解是为Android的血管。是一种进程间通信的机制。比如Activity,Service需要和AMS通信的时候,就需要Binder。
  • 除了进程间通信,也可以把Binder理解为一种虚拟物理设备驱动。虚拟表示没有实体,和键盘鼠标不一样。Binder是虚拟的。因为mmap映射时将虚拟内存映射到/dev/binder文件,在linux中这个代表一个驱动,所以说它是一种虚拟物理设备驱动。
  • 除此之外,在应用层,也可以把Binder理解为一个是一个能发起进程间通信的Java类,实现了IBinder接口。除此之外,AIDL中的Stub,Proxy也实现了IBinder,还有AMS等也实现了IBinder。另外在ServiceManager中查找服务时,所用到的Map集合的value也是IBinder类型的。

综上所述,Binder可以说是:
①进程间通信的机制
②虚拟物理设备驱动
③一个能发起进程间通信的Java类

2.为什么是Binder?

Linux也有一些很优秀的进程间通信机制,例如管道,消息队列,共享内存,socket等,但是为什么Android使用Binder而不是这些呢?
看Binder与共享内存,socket的对比

参考指标 Binder 共享内存 socket
性能上 需要拷贝1次 需要拷贝0次 需要拷贝2次
架构上 C/S架构,很稳定,且易用 难以控制,易用性差 C/S架构(但是是一款通用的接口,传输效率低,开销大)
安全性上(最重要) ①为每个APP分配UID②支持实名和匿名访问 不分配UID,访问接入点是开放的,不安全 不分配UID,访问接入点是开放的,不安全

解释下这幅图:

2.1 拷贝次数

(1)传统的IPC通信(两次拷贝)
基础知识:内存被操作系统划分成了两块:用户空间和内核空间,用户空间是用户程序代码运行的地方,内核空间是内核代码运行的地方,为了安全,它们是隔离的。即使用户的程序崩溃了,内核也不受影响。同时,内核空间映射到物理内存中是一块的,而用户空间,不同进程映射到的物理内存不一样。(所以内核空间的数据是共享的,从下面的图也可以看出来)
我们软件工程师所说的内存一般都是虚拟内存。
在这里插入图片描述
下面是我自己画的图,描述了传统IPC的过程
在这里插入图片描述
当需要进程间通信时,数据会先从进程1的用户空间,通过系统调用copy_from_user进入内核空间,然后再通过系统调用copy_to_user进入进程2的用户空间,从而完成通信。

可以看到,传统的IPC需要两次拷贝,每次拷贝都需要系统调用,上下文切换。
(2)Binder通信(一次拷贝)
在这里插入图片描述
可以看到,数据也会先从进程1的用户空间到系统的内核空间,完成一次拷贝,但是进入系统内核空间后,进程2的用户空间的数据接收区和内核空间的那部分区域,能够映射到同一块物理空间。这样就不用发生copy_to_user的系统调用了,从而不用第二次拷贝。
用到了mmap,即内存映射。即内存上的空间可以映射到磁盘上的对应区域(操作系统学过)
(3)共享内存(0次拷贝)
在这里插入图片描述
可以发现,它把copy_from_user省略掉了,直接就是进程1和进程2能够共享同一块物理内存,不需要拷贝。这样看似效率很高,但是实则易用性很差。因为程序员的水平是参差不齐的。这个技术本身没有问题,有问题的是使用这个技术的人。所以我觉得Binder的一次拷贝是故意的,目的是提高易用性。后面的mmap是谷歌工程师完成的,我们只需要让服务类继承Binder,那么它就具有了进程间通信的能力了。至于具体的细节,谷歌工程师已经帮我们封装好了。但是因为客户端太灵活了,情况很多,难以统一,所以谷歌工程师不能帮我们实现客户端这边的封装。

2.2 架构

这个其实就是C/S架构的好处,客户端有什么需求就丢给服务器,解耦,很稳定。而且很易用(Binder需要拷贝一次,而不是零次,为的就是易用性更高),程序员只需要关心业务本身代码,无需过度关注进程通信细节。
而共享内存的话,需要面临一系列复杂的问题,比如访问的安全性,同步等问题。

2.3 安全性

这个要分两方面来说
①首先Binder为每个app分配了一串UID,这串UID是app的唯一身份标识。而共享内存,socket等都是app自己生成类似的这种编码,直接交给上层,上层只管接收,没有能力去甄别对错。假如有恶意软件伪装,那么是无法跟踪这个软件的。
②其次是支持实名访问和匿名访问。实名访问的话,和共享内存,socket是一样的,这样安全性较低。匿名访问安全性高,我们自己写的AIDL一般就是匿名访问。匿名访问类似于滴滴打车,打过来的手机号是虚拟的,并不是实际的,也就是一个代理对象。

区分实名访问和匿名访问的标准是,有无在ServiceManager注册过。注册过的就是实名,反之就是匿名。
比较常见的实名如AMS,WMS等

3.mmap介绍

3.1 mmap是什么?

mmap 是一种内存映射文件的方法,即将一个文件或者其它对象映射到进程的地址空间,实现文件磁盘地址和进程虚拟地址空间中一段虚拟地址的一一对映关系。实现这样的映射关系后,进程就可以采用指针的方式读写操作这一段内存,而系统会自动回写脏页面到对应的文件磁盘上,即完成了对文件的操作而不必再调用 read、write 等系统调用函数。相反,内核空间对这段区域的修改也直接反映用户空间,从而可以实现不同进程间的文件共享。

3.2 mmap实现的c++

在这里插入图片描述
同时,使用mmap一般都要创建文件,因为linux一切皆文件。

4.AIDL是什么?

关于AIDL的参考文章

(1)定义

AIDL全程是Android Interface Difination Language,即接口定义语言,是用于定义服务器和客户端通信接口的一种描述语言,可以拿来生成用于IPC的代码。目的就是实现进程间通信。
其实它就是一个模板,真正起作用的不是AIDL文件,而是编译后,根据AIDL文件生成的那个Interface类。

(2)AIDL文件编译后的组成

以这样的AIDL文件为例
在这里插入图片描述

此AIDL文件在编译后,会生成这样一个interface
在这里插入图片描述
TestAidl接口里面有两部分
一个是静态抽象内部类Stub,一个是接口待实现的方法add
其中,Stub又实现了TestAidl接口。但是又因为Stub是抽象类,所以不必实现add方法,add方法的具体实现在具体的服务类里面。也就是Stub的子类

下面来看一下Stub的组成
在这里插入图片描述
看起来有点乱,但其实可以分成以下几部分

抽象类Stub 继承Binder  实现TestAidl{ 
   
	①静态的asInterface方法{ 
   
       返回代理类(分两种情况:同进程,直接返回继承该StubBinder;不同进程,返回静态代理类)
    }
	②重写的onTransact方法
	③静态代理类Proxy  实现TestAidl{ 
   
    	实现add方法,主动调用transact方法
    }
 }

①一个是asInterface方法,如果是同一进程的,则直接返回继承该Stub的服务端对象,如果不是同一进程,则构造一个代理类,由这个代理类,来间接操作这个服务端对象。
②一个是onTransact方法,此方法在客户端调用transact方法时调用。下图是onTransact方法的代码
在这里插入图片描述
code是方法的代码,是一个int类型,因为客户端和服务端都实现同一个接口,那么他们都会实现同一批方法(在这里就是add方法),那么就可以为这一批方法进行统一编序号,方便方法的匹配调用。
③还有一个是静态代理类,它是对服务端的代理。里面的代码如下
在这里插入图片描述
会发现它和Stub的代码很像。没错,其实它代理的就是Stub的实现类,所以这是正常现象。我们再看add方法,里面有两个Parcel类型的变量,分别负责接收发送的参数,接收返回的数据。这里面就有transact方法的调用,这里调用就会调用到onTransact方法。transactonTransact方法的四个参数分别表示的含义为:
①用于区分执行哪个方法
②客户端传递的参数
③服务器返回回去的值
④标明是否有返回值,0表示有,1表示没有

(3)AIDL进行进程间通信的流程

①客户端调用bindService,在onServiceConnected的回调方法中,调用StubasInterface方法,得到mRemote值。(如果是同一进程,直接返回服务端对象。如果是不同进程,返回代理对象)。这里假设是不同进程
②客户端调用mRemoteadd方法,因为是不同进程,所以调用代理对象的add方法。
add方法里面会调用transact方法,然后客户端阻塞直到方法执行完成,拿到返回值。
④客户端调用transact方法,会调用服务端StubonTransact方法,里面会执行Stub子类即具体服务类的add方法。

今天的文章Binder机制原理分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/8416.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注