| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> Android-binder通信详解 -> 正文阅读 |
|
[移动开发]Android-binder通信详解 |
1. binder是什么?binder是安卓系统的进程间通信方式。 2. 为什么安卓要用binder?Android内核是基于Linux系统,linux本身就有很多种进程间通信方式: 内存共享,消息队列、信号量等,为什么安卓还要用binder呢? 传统ipc(进程间通信): 共享内存,不需要内存拷贝,但是控制繁琐。 管道通信,需要两次内存拷贝。 ? binder通信: Binder只需要一次拷贝是因为安卓的内存映射方法,也就是mmap。a进程发数据给b进程,a进程把数据拷贝给mmap开辟的内核空间,b进程通过mmap就可以取出来这个数据而不用重新拷贝。 ? ? 3. binder的实现:binder的实现是基于内存映射的,也就是上面说的mmap。 这里我们首先要理解用户空间和内核空间。内核空间可以访问所有的进程页表。也就是内核空间可以访问所有的用户空间。也是基于这个前提,进程间通信才可以实现。 要理解mmap必须先理解物理地址、虚拟地址和页表的概念。 物理地址: 物理地址空间是实在的存在于计算机中的一个实体,在每一台计算机中保持唯一独立性。我们可以称它为物理内存;如在32位的机器上,物理空间的大小理论上可以达到2^32字节(4GB)。 虚拟地址: 虚拟地址并不真实存在于计算机中。每个进程都有4G的虚拟地址空间,其中3G用户空间,1G内核空间(linux),每个进程共享内核空间,独立的用户空间。每个进程都有自己独立的虚拟地址空间。这样每个进程都能访问自己的地址空间,这样做到了有效的隔离。 ?虚拟地址里面存放的什么内容? ?mmap的作用是映射文件描述符和指定文件的(off_t off)区域至调用进程的(addr,addr *len)的内存区域,如下图所示: ?binder的整个流程: ? 4. binder的通信流程? ? 整个安卓的进程间通信都是基于c/s架构的,就是client / server 架构。 系统启动时servicemanager作为0号进程先启动,然后会读取rc文件,把系统中其他的进程依次启动。 server启动的时候就把自己注册到servicemanager里面,servicemanager里面会维护一个services的list。 client端想要和service通信就会先获取servicemanager服务,然后从servicemanager里面通过service name获取对应的service的binder,拿到了这个binder client端就可以通过这个binder和service通信了。 具体过程如下: ?4.1 server注册进程:此处以mediaplayer为例:
所有的::instantiate()函数都是static型函数,且分别是创建各个子模块的对象实例。由此可看出mediaserver共分2个子模块: MediaPlayerService & ResourceManagerService。
?server注册到servermanager的时候会调用frameworks/native/cmds/servicemanager/service_manager.c中的do_add_service。这个函数中首先检查是否有权限注册service,没权限就会报错返回;然后检查是否已经注册过,注册过的service将不能再次注册。然后构造一个svcinfo对象,并加入一个全局链表中svclist中。最后通知binder设备:有一个service注册进来。 Tips: server一定是一个死循环,一直在等待client的调用,我们自己写的server一般是while死循环之类的。安卓server的死循环在binder driver里面,我们在server代码里面看不到,但是只要server调用了startThreadPool就会有一个死循环在底层跑着。 4.2 service启动流程首先,每个service都要有对应的rc文件,里面说明了这个service启动需要加载的文件流程: 以mediaserver.rc为例:
有了这个rc文件,系统在启动的时候就会调用system/bin/mediaserver这个可执行文件。这个文件里面的实现就是上面的main函数,然后就会把MediaPlayerService和ResourceManagerService注册进去。 4.3 client调用流程下面以MediaCodecList为例:
client端调用的就是IMediaPlayerService中的函数,这个IMediaPlayerService就是接口类,bn和bp都会继承这个类。client端调用的是bp的代码,然后bp通过binder调用到bn。
4.4 一个问题: MediaPlayerService和ResourceManagerService属于一个进程吗?这里首先理解一个概念: 代码中的service究竟是什么?
service是一个继承了interface的具体实现,用于和client通信。server端和client端同时继承interface类,一个是bp一个是bn。 所以呢?service和binder有啥关系? service和进程有啥关系? service调用了instantiate函数就是把自己注册到了servicemanager里面,这个时候service就是一个binder接口。 注意:直到这里都没有进程的概念。service 不等于 进程。 那么进程是怎么来的? 看看service的启动流程, 在servicemanager加载rc文件的时候,这个rc文件里面调用的是/system/bin/mediaserver,一个可执行文件,可执行文件在系统中是什么?是一个单独的进程。到这里就破案了。 MediaPlayerService和ResourceManagerService都在/system/bin/mediaserver中。所以他们肯定属于同一个进程,但是他们分别注册到了service manager中,所以他们是两个binder。 5. 安卓的treble机制在Android 8.0开始,Android引入了Treble的机制,为了方便Android系统的快速移植、升级,提升系统稳定性,Binder机制被拓展成了"/dev/binder", "/dev/hwbinder","/dev/vndbinder"。 三种binder的具体使用如下: ? 此处需要注意VNDK的两种概念: 在代码中,当一个so既需要在system分区使用又需要在vendr分区使用则声明该so为VNDK,然后so生成的时候就会产生两个, 一个在system目录,一个在vendor目录。 此处的vndk是两个vendor分区的进程通信用的。 ? 6. 总结? ?本文讲述了安卓binder通信。首先从linux已有进程通信存在的问题讲起,讲述了binder存在的必要,然后讲述了binder的实现流程,以及通过media player service为例讲述了在c/s架构中binder的具体使用过程。最后讲述了安卓中的treble机制,就是安卓对已有binder的几种扩展。下篇文章将通过audio finger和audio hal的通信再次讲述hwbinder的实现过程。敬请期待~ |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 9:50:25- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |