既然要搞清楚为什么要使用binder,那就要理解binder的作用。
binder在java层的作用就是一个通信的媒介。那我们就需要理解,binder到底解决的问题是什么,原来的IPC通信机制有什么不足之处。
1.现有的Linux的IPC机制种类
1.共享内存
2.管道
3.消息队列
4.socket
1.1性能方面
我们来看看一次通信,这些方式分别需要拷贝的内存次数。
内存拷贝次数越多,通信效率越低。Binder的内存拷贝次数是1,低于共享内存,高于其他方式。
1.2安全性方面
传统的IPC方式,毫无安全性可言,这也无可厚非,因为android平台会面对海量的应用,需要区分恶意的应用,阻止他们访问。传统的IPC方式无法取得对应进程的UID(UID是android系统对每个APP赋予的唯一标识,可以用它做权限验证),无法做到权限的验证。2.Binder的优势在哪?是如何解决其他种类的问题
Binder通信可以获得UID,保证了安全性。虽然效率不是最高,但是可以被接受。
3.Binder的原理
为什么Binder能做到拷贝一次内存就可以完成通信?首先需要了解一下Linux上的概念。
3.1进程隔离
Linux中使用了进程隔离技术,也就是说,各个进程之间的内存是互相不共享的。自己玩自己的内存,保证数据的安全性。因此如果进程之间需要通信,则需要相应的IPC机制进行处理。
进程隔离技术使用到了虚拟内存的概念。虚拟内存是一种提高物理内存利用率的技术,它是物理内存的映射,可以使得程序看到的都是一片连续的内存,可以使用代理模式来理解一下,它是物理内存的代理,实际上映射的物理内存可能都是零散的内存碎片,以及磁盘。它可以交换一些不常用的内存到磁盘,提高内存的效率。
3.2进程空间:用户空间和内核空间
内核空间中存放的是内核代码和数据,而进程的用户空间中存放的是用户程序的代码和数据。再具体一点来说,假设操作系统是32位的,寻址能力就是2的32次方,就是4G,将高位的1GB字节供内核使用,称之为内核空间。剩下的3GB字节供用户进程使用,称之为用户空间。他们都运行在虚拟地址上,但是是相互隔离的。
如果用户空间想要访问内核空间的资源(因为内核空间占有系统资源,例如读写文件,访问网络),那就需要两者之间进行通信。这时候系统内核可以提供接口,给用户进行调用,这样保证了系统的安全和稳定。也就是说,传统的IPC进程间通信就是通过系统内核来完成的。
3.3用户态和系统态
当进程在执行用户的代码的时候,此时进程处于用户态。当在进程在执行内核代码的时候,此时进程处于内核态。
3.4内核模块和驱动
传统的IPC方式是通过系统内核来完成的,Binder也是一样,内核中存在一个binder的驱动。4.传统IPC机制的通信原理
此处偷盗一波rushjs大神的图
通常是下面两个步骤(非共享内存机制):1.发送方进程通过系统调用(copy_from_user)将要发送的数据存拷贝到内核缓存区中。
2.接收方开辟一段内存空间,内核通过系统调用(copy_to_user)将内核缓存区中的数据拷贝到接收方的内存缓存区。
这种传统IPC机制存在2个问题:
1.需要进行2次数据拷贝,第1次是从发送方用户空间拷贝到内核缓存区,第2次是从内核缓存区拷贝到接收方用户空间。
2.接收方进程不知道事先要分配多大的空间来接收数据,可能存在空间上的浪费。
5.Binder的底层原理
传统IPC机制需要拷贝2次内存,Binder是如何只用1次内存拷贝就实现进程间通信的呢?前面我们已经了解到,Linux是使用的是虚拟内存寻址方式,用户空间的虚拟内存地址是映射到物理内存中的,对虚拟内存的读写实际上是对物理内存的读写,这个过程就是内存映射,这个内存映射过程是通过系统调用mmap()来实现的。
Binder借助了内存映射的方法,在内核空间和接收方用户空间的数据缓存区之间做了一层内存映射。这样一来,从发送方用户空间拷贝到内核空间缓存区的数据,就相当于直接拷贝到了接收方用户空间的数据缓存区,从而减少了一次数据拷贝。
binder调用是C/S架构,client与server处于不同的进程。那我们第一个念头就是,底层驱动一定是调用了系统资源帮助我们做了这个对象引用传递的事情。
整个过程参与者有,ServerManager,Binder底层驱动,Server,Client。这几个角色的作用是与一次网络请求传递很像。
ServerManager作为DNS解析服务器,Binder底层驱动相当于路由器,Client请求发起者,Server请求接受者。
简单来说。
1.Client发起请求,输入了域名。(例如在浏览器中输入www.juejin.im)
2.ServerManager,给我返回相应的Binder对象。(DNS解析出掘进的真实IP)
3.Binder驱动帮助传递这个Binder对象的引用。(通过层层路由传输)
4.Server接收到Binder。(请求到达)
这里其实可以跟七层网络协议栈进行类比一下,就非常清楚了。回过头想一下,既然是ServerManager中能够找到对应的Binder对象,那么一定会有一个提前注册的过程。而且ServerManager与Client和Server肯定都处于不同的进程,他们之间的通信也是由binder来通信的。那也就是说,会有一个ServerManager会提供一个类似全局的binder的一个概念,Client可以直接取得到,这样才能进行与ServerManager的通信。
7.Binder代理机制
上层binder的使用,其实是感知不到代理的,这也是代理的作用,让上层无感知。实际上,Client获取到Server的Binder对象的引用,实际上是Binder驱动的一层代理。假设,Client端RPC调用了一个server的方法,实际上是在操作Binder驱动的代理,然后由驱动传输这个操作到Server端,再调用了Server端的方法。
具体的看一下AIDL文件生成的类的源码即可清楚。里面定义了一个proxy,proxy里面包含所有AIDL文件的方法。
我在想这里是不是要画个图啊?~~
Binder整个过程就是这样了,我个人感觉深入去了解一个东西,可以把你很多零散的知识联系起来。
网络安全成长路线图
这个方向初期比较容易入门一些,掌握一些基本技术,拿起各种现成的工具就可以开黑了。不过,要想从脚本小子变成hei客大神,这个方向越往后,需要学习和掌握的东西就会越来越多,以下是学习网络安全需要走的方向:
# 网络安全学习方法
上面介绍了技术分类和学习路线,这里来谈一下学习方法:
## 视频学习
mg-blog.csdnimg.cn/e98fa11b565342d59b5f63c5e626f914.png)
# 网络安全学习方法
上面介绍了技术分类和学习路线,这里来谈一下学习方法:
## 视频学习
无论你是去B站或者是油管上面都有很多网络安全的相关视频可以学习,当然如果你还不知道选择那套学习,我这里也整理了一套和上述成长路线图挂钩的视频教程,完整版的视频已经上传至CSDN官方,朋友们如果需要可以点击这个链接免费领取。网络安全重磅福利:入门&进阶全套282G学习资源包免费分享!