当前位置:网站首页>Binder机制详解(三)
Binder机制详解(三)
2022-08-02 03:27:00 【浮空over】
系列目录
文章目录
前言
前两节学习了Binder机制需要储备的底层知识,接下来会分四层详细讲解Binder机制
一、Binder机制理解
binder 是 Android 中主要的跨进程通信方式,binder 驱动和 service manager 分别相当于网络协议中的路由器和 DNS,并基于 mmap 实现了 IPC 传输数据时只需一次拷贝。
binder 包括 BinderProxy、BpBinder 等各种 Binder 实体,以及对 binder 驱动操作的 ProcessState、IPCThreadState 封装,再加上 binder 驱动内部的结构体、命令处理,整体贯穿 Java、Native 层,涉及用户态、内核态,往上可以说到 Service、AIDL 等,往下可以说到 mmap、binder 驱动设备,是相当庞大、繁琐的一个机制。
二、应用层
1.Linux下的进程通信
管道通信:1v1,两次拷贝
socket:效率低,开销大
共享内存:性能高,安全性低
2.binder通信
binder通信:牺牲了开发灵活度,必须实现一个service,自己实现数据分发(通信的类,方法,数据,返回参数)—>aidl帮我们做
aidl.exe解析aidl配置类,生成一个java类
写完AIDL文件之后,系统会在Build时生成一个继承IInterface接口的java文件。这个文件名和对应的AIDL文件名相同。在这个文件中,有一个内部类Stub,这个类就是Binder,所以可以认为AIDL是为了帮助系统生成对应的Binder文件。
这个类继承了
IInterface
接口,同时这个类也是一个接口。这个接口申明了两个方法,也就是.aidl
中的方法。然后声明了一个内部类Stub。这个Stub就是一个Binder类。在Stub内部还有个代理类Proxy,在跨进程通讯中,它会是客户端的代理方法。
proxy调用者,stub接收者
3.stub
除去构造方法以外,Stub中的方法还有
asBinder()
、asInterface()
和onTransact
方法。在这三个方法之外,还有上文提到过的,两个静态ID,用来标识客户端调用的方法。其中
asBinder()
方法相当于一个get方法,用来返回当前的Binder对象接下来我们看一下
onTransact()
方法,这个方法运行在服务端,会通过code来分发具体要执行的方法(避免方法乱套)asInterface()
方法:判断当前服务端和客户端是否处于同一进程中。如果处于同一个进程中,会返回同一个Stub对象本身,如果处于不同的进程会返回封装后的客户端代理类Stub.proxy
。这个方法会在客户端调用,用来获取对象。
4.流程总结
客户端—>proxy中请求函数—>通过remote写入(code,data,返回值,类)—>mRemote—>transact(JNI层实现)写入到系统中—> 通知服务端进程—>onTransact通过code—>调用服务端request—>结果—>写入客户端进程
三、native层
进程间通信本质:内存拷贝
用户空间:存放程序的代码和数据
内核空间:存放内核代码数据
应用程序需接口申请才能调用代码在内核空间中运行,好处:应用程序崩溃不会导致内核崩溃
计算机蓝屏主要是硬件驱动(在内核空间)不兼容导致
物理内存
虚拟内存:用户空间和内核空间都属于虚拟内存
MMU内存管理单元:cpu想要访问一个地址,通过MMU(PTE表)去取
CPU在执行指令与数据时,获得的是虚拟内存的地址,但是CPU只能去物理内存寻址。此时,MMU就派上用场了。MMU负责,将虚拟地址,翻译成,真正运行时的物理地址。
1.Binder基于mmap如何实现一次拷贝
(binder驱动)内核空间和(接收方进程)用户空间映射到同一块物理内存上
发送方进程copy_from_user—>Binder驱动(内核空间)<—>mmap映射物理页alloc_page,接收方进程<—>mmap映射物理页alloc_page
- 内核刚开始只是分配了一个物理页,并且分别将这个物理页映射到进程的内核虚拟地址空间V1(修改内核空间的页表映射)和进程的用户虚拟地址空间V2(修改用户空间的页表映射)。在用户空间访问V1和在内核空间访问V2,其实都是访问的是同一个物理内存块,从而实现进程的内核和用户空间共享同一块物理内存的目的。这样binder驱动在内核空间,将一段数据拷贝到这个物理页,则该进程的用户空间则不需要copy_to_user()即可以同步看到内核空间的修改,并能够访问这段物理内存
2.Intent传参大小限制
4M,mmap映射时会判断大小
初始化binder—>binder_open(路径)—>mmap映射—> binder_loop不断解析分发物理内存中数据
四、驱动层
service manager(单独进程):运行binder,实现android进程间通信,父进程是init进程
init—>service manager
init—>zygote—>systemServer
copy_from_user:用户空间拷贝到内核空间(驱动)
Binder驱动核心是维护一个binder_proc类型的双向链表,里面记录了servicemanager在内的所有service信息,当client去请求某个service时,binder驱动去binder_proc中查找相应的service返回给client,同时增加service的引用个数
边栏推荐
猜你喜欢
随机推荐
Kotlin - 静态方法
CTF entry md5
在 UUP dump 被墙的情况下如何用 UUP 下载 ISO 镜像
广告电商「私域打工人」职业前景:你离月薪6万,还差多远?
链动2+1模式开发系统
uniapp | Compilation error after updating with npm update
最简单的FRP内网穿透教程
Debian 12 Bookworm 尝鲜记
库存现金、现金管理制度、现金的账务处理、银行存款、银行存款的账务处理、银行存款的核对
英语每日打卡
阿里技术官手码12W字面试小册
MVC,MVP和MVVM架构解析
file contains vulnerabilities
一个网络安全小白鼠的学习之路——nmap的基本使用
大厂底层必修:“应用程序与 AMS 的通讯实现”
管理会计(对内)指引、管理会计要素及其具体内容(可能考,考前记一下,推荐记一下四个大点即可)、
机器学习1
云安全笔记:云原生全链路加密
kotlin语法总结(一)
uniapp发布到微信小程序:分包、删减代码全过程