德惠网站/自动收录网
Binder简单理解
简单来说,Binder 就是用来Client 端和 Server 端通信的。并且 Client 端和 Server 端 可以在一个进程也可以不在同一个进程,Client 可以向 Server 端发起远程调用,也可以向Server传输数据(当作函数参数来传),并且不用关心对方在哪个进程。
Binder的基本原理
Binder借助了内存映射(mmap)的方法,在内核空间和接收方用户空间的数据缓存区之间做了一层内存映射。从发送方用户空间拷贝到内核空间缓存区的数据,就相当于直接拷贝到了接收方用户空间的数据缓存区,从而减少了一次数据拷贝。
IPC通信原理
理解了上面的几个概念,我们再来看看传统的 IPC 方式中,进程之间是如何实现通信的。
通常的做法是消息发送方将要发送的数据存放在内存缓存区中,通过系统调用进入内核态。然后内核程序在内核空间分配内存,开辟一块内核缓存区,调用 copyfromuser() 函数将数据从用户空间的内存缓存区拷贝到内核空间的内核缓存区中。同样的,接收方进程在接收数据时在自己的用户空间开辟一块内存缓存区,然后内核程序调用 copytouser() 函数将数据从内核缓存区拷贝到接收进程的内存缓存区。这样数据发送方进程和数据接收方进程就完成了一次数据传输,我们称完成了一次进程间通信
我们来看下原理图:
这种传统的 IPC 通信方式有两个问题:
1、性能低下,一次数据传递需要经历:内存缓存区 --> 内核缓存区 --> 内存缓存区,需要 2 次数据拷贝;
2、接收数据的缓存区由数据接收进程提供,但是接收进程并不知道需要多大的空间来存放将要传递过来的数据,因此只能开辟尽可能大的内存空间或者先调用 API 接收消息头来获取消息体的大小,这两种做法不是浪费空间就是浪费时间。
Binder跨进程通信原理
理解了 Linux IPC 相关概念和通信原理,接下来我们正式介绍下 Binder IPC 的原理。
动态内核可加载模块
正如前面所说,跨进程通信是需要内核空间做支持的。传统的 IPC 机制如管道、Socket 都是内核的一部分,因此通过内核支持来实现进程间通信自然是没问题的。但是 Binder 并不是 Linux 系统内核的一部分,那怎么办呢?这就得益于 Linux 的 动态内核可加载模块(Loadable Kernel Module,LKM)的机制;模块是具有独立功能的程序,它可以被单独编译,但是不能独立运行。它在运行时被链接到内核作为内核的一部分运行。这样,Android 系统就可以通过动态添加一个内核模块运行在内核空间,用户进程之间通过这个内核模块作为桥梁来实现通信。
在 Android 系统中,这个运行在内核空间,负责各个用户进程通过 Binder 实现通信的内核模块就叫 Binder 驱动(Binder Dirver)。
那么在 Android 系统中用户进程之间是如何通过这个内核模块(Binder 驱动)来实现通信的呢?难道是和前面说的传统 IPC 机制一样,先将数据从发送方进程拷贝到内核缓存区,然后再将数据从内核缓存区拷贝到接收方进程,通过两次拷贝来实现吗?显然不是,否则也不会有开篇所说的 Binder 在性能方面的优势了。这就涉及到 内存映射 的概念了。
内存映射
Binder IPC 机制中涉及到的内存映射通过 mmap() 来实现,mmap() 是操作系统中一种内存映射的方法。内存映射简单的讲就是将用户空间的一块内存区域映射到内核空间。映射关系建立后,用户对这块内存区域的修改可以直接反应到内核空间;反之内核空间对这段区域的修改也能直接反应到用户空间。
内存映射能减少数据拷贝次数,实现用户空间和内核空间的高效互动。两个空间各自的修改能直接反映在映射的内存区域,从而被对方空间及时感知。也正因为如此,内存映射能够提供对进程间通信的支持。
Binder IPC 实现原理
Binder IPC 正是基于内存映射(mmap)来实现的,但是 mmap() 通常是用在有物理介质的文件系统上的。
比如进程中的用户区域是不能直接和物理设备打交道的,如果想要把磁盘上的数据读取到进程的用户区域,需要两次拷贝(磁盘–>内核空间–>用户空间);通常在这种场景下 mmap() 就能发挥作用,通过在物理介质和用户空间之间建立映射,减少数据的拷贝次数,用内存读写取代I/O读写,提高文件读取效率。
而 Binder 并不存在物理介质,因此 Binder 驱动使用 mmap() 并不是为了在物理介质和用户空间之间建立映射,而是用来在内核空间创建数据接收的缓存空间。
一次完整的 Binder IPC 通信过程通常是这样:
1、首先 Binder 驱动在内核空间创建一个 数据接收缓存区 ;
2、接着在内核空间开辟一块内核缓存区,建立 内核缓存区 和 内核中数据接收缓存区 之间的映射关系,以及 内核中数据接收缓存区 和 接收进程用户空间地址 的映射关系;
3、发送方进程通过系统调用 copyfromuser() 将数据 copy 到内核中的内核缓存区,由于内核缓存区和接收进程的用户空间存在内存映射,因此也就相当于把数据发送到了接收进程的用户空间,这样便完成了一次进程间的通信。
我们来看下原理图:
Binder通信流程
我们上面以及聊过,Binder的通信流程是先由Client发出,经过Binder Framework到达Kernel,再经过Kernel转发,最终通过Binder Framework到达Server。整体的通信流程有点像网络通信。
我们以常见的启动四大组件为例来描述Binder的通信流程,如下所示:
1、当我们在Activity里启动一个Service,这个调用会经过层层传递到ActivityManagerProxy,然后ActivityManagerProxy会通过Binder发起跨进程调用。
2、接着Client就会向Binder Driver发起binder ioctl请求,在IPCTreadState::waitForResponse里执行While循环,在While循环中调用IPCThreadState::talkWithDriver()与驱动交互,然后Client线程等待驱动回复
binder驱动收到BC_TRANSACTION事件后的应答消息:
BR_TRANSACTION_COMPLETE:对于oneway transaction(非阻塞通信、单向),当收到该消息,则完成了本次Binder通信
BR_DEAD_REPLY:回复失败,往往是线程或节点为空,则结束本次通信Binder
BR_FAlLED_REPLY:回复失败,往往是transaction出错导致,则结束本次通信Binder
BR_REPLY:对于非oneway transaction时,当收到该消息,则完整地完成本次Binder通信
3、上述命令除了BR_TRANSACTION_COMPLETE:其他回复Client端的进程都会接着调用IPCThreadState::executeCommand()处理驱动返回的命令。
4、对于Server端而言,会调用IPCThreadState::joinThreadPool循环执行IPCThreadState::getAndExecuteCommand,最终调用ActivityManagerService.startService方法。如果需要回复Client会调用talkWithDriver与驱动通信
Client在与Service的通信过程按照是否需要Server返回数据可以分为两种方式:
单向模式:不需要Server返回数据
双向模式:需要Server返回数据
对以上的代码做简单分析:
binder_ioctl -> binder_ioctl_write_read -> binder_thread_write
```java
static long binder_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
{...switch (cmd) {case BINDER_WRITE_READ:ret = binder_ioctl_write_read(filp, cmd, arg, thread)...
}——————————————————static int binder_ioctl_write_read(struct file *filp,unsigned int cmd, unsigned long arg,struct binder_thread *thread)
{...if (copy_from_user(&bwr, ubuf, sizeof(bwr))) { //把用户空间数据ubuf拷贝到bwrret = -EFAULT;goto out;...if (bwr.write_size > 0) { //写缓冲区有数据时,binder_thread_writeret = binder_thread_write(proc, thread,bwr.write_buffer,bwr.write_size,&bwr.write_consumed);trace_binder_write_done(ret);...}if (bwr.read_size > 0) { //读缓冲区有数据时,binder_thread_readret = binder_thread_read(proc, thread, bwr.read_buffer,bwr.read_size,&bwr.read_consumed,filp->f_flags & O_NONBLOCK);trace_binder_read_done(ret);binder_inner_proc_lock(proc);...}...//将内核数据bwr拷贝到用户空间ubufif (copy_to_user(ubuf, &bwr, sizeof(bwr))) { ret = -EFAULT;goto out;}
}
Client端
status_t IPCThreadState::transact(int32_t handle,uint32_t code, const Parcel& data,Parcel* reply, uint32_t flags)
{if (reply) {//等待响应err = waitForResponse(reply);} else {Parcel fakeReply;err = waitForResponse(&fakeReply);}...
} else {//oneway,则不需要等待 reply 的场景err = waitForResponse(nullptr, nullptr);
}
status_t IPCThreadState::waitForResponse(Parcel *reply, status_t *acquireResult)
{int32_t cmd;int32_t err;//在while循环中做下面的事情:while (1) { //循环中通过talkWithDriver与驱动通信if ((err=talkWithDriver()) < NO_ERROR) break; ...if (mIn.dataAvail() == 0) continue;cmd = mIn.readInt32();switch (cmd) {... //循环中等待Binder驱动回复,执行executeCommanderr = executeCommand(cmd); ...}}...return err;
}—————————————————status_t IPCThreadState::executeCommand(int32_t cmd)
{
...
switch ((uint32_t)cmd) { //switch判断case BR_ERROR:result = mIn.readInt32();break;case BR_OK:break;case BR_ACQUIRE:refs = (RefBase::weakref_type*)mIn.readPointer();obj = (BBinder*)mIn.readPointer();ALOG_ASSERT(refs->refBase() == obj,"BR_ACQUIRE: object %p does not match cookie %p (expected %p)",refs, obj, refs->refBase());obj->incStrong(mProcess.get());IF_LOG_REMOTEREFS() {LOG_REMOTEREFS("BR_ACQUIRE from driver on %p", obj);obj->printRefs();}mOut.writeInt32(BC_ACQUIRE_DONE);mOut.writePointer((uintptr_t)refs);mOut.writePointer((uintptr_t)obj);break;case BR_RELEASE:refs = (RefBase::weakref_type*)mIn.readPointer();obj = (BBinder*)mIn.readPointer();...
Server端
void IPCThreadState::joinThreadPool(bool isMain)
{
...do { //循环里面不断的读取命令数据,然后解析命令数据,并给出相应的响应。processPendingDerefs();// now get the next command to be processed, waiting if necessaryresult = getAndExecuteCommand();...}—————————————————————status_t IPCThreadState::getAndExecuteCommand()
{status_t result;int32_t cmd;result = talkWithDriver();if (result >= NO_ERROR) {size_t IN = mIn.dataAvail();if (IN < sizeof(int32_t)) return result;cmd = mIn.readInt32();IF_LOG_COMMANDS() {alog << "Processing top-level Command: "<< getReturnString(cmd) << endl;}pthread_mutex_lock(&mProcess->mThreadCountLock);mProcess->mExecutingThreadsCount++;if (mProcess->mExecutingThreadsCount >= mProcess->mMaxThreads &&mProcess->mStarvationStartTimeMs == 0) {mProcess->mStarvationStartTimeMs = uptimeMillis();}pthread_mutex_unlock(&mProcess->mThreadCountLock);//解析来自驱动的命令result = executeCommand(cmd);pthread_mutex_lock(&mProcess->mThreadCountLock);mProcess->mExecutingThreadsCount--;if (mProcess->mExecutingThreadsCount < mProcess->mMaxThreads &&mProcess->mStarvationStartTimeMs != 0) {int64_t starvationTimeMs = uptimeMillis() - mProcess->mStarvationStartTimeMs;if (starvationTimeMs > 100) {ALOGE("binder thread pool (%zu threads) starved for %" PRId64 " ms",mProcess->mMaxThreads, starvationTimeMs);}mProcess->mStarvationStartTimeMs = 0;}pthread_cond_broadcast(&mProcess->mThreadCountDecrement);pthread_mutex_unlock(&mProcess->mThreadCountLock);}return result;
}
本文主要对在Android开发中的binder通信机制原理的理解,更多有关通讯以及Android开发的技术进阶可以前往《Android高级开发进阶手册》点击可以查看详细内容板块。
Binder 的完整定义
1.从进程间通信的角度看,Binder 是一种进程间通信的机制;
2.从 Server 进程的角度看,Binder 指的是 Server 中的 Binder 实体对象;
3.从 Client 进程的角度看,Binder 指的是对 Binder 代理对象,是 Binder 实体对象的一个远程代理
4.从传输过程的角度看,Binder 是一个可以跨进程传输的对象;Binder 驱动会对这个跨越进程边界的对象对一点点特殊处理,自动完成代理对象和本地对象之间的转换。
相关文章:

Android开发,车载通讯应用——binder通讯原理解析
Binder简单理解 简单来说,Binder 就是用来Client 端和 Server 端通信的。并且 Client 端和 Server 端 可以在一个进程也可以不在同一个进程,Client 可以向 Server 端发起远程调用,也可以向Server传输数据(当作函数参数来传&#…...

[算法]求n!在m进制下末尾有多少个0
参考链接:求n!在m进制下末尾0的个数_.!零n,,m-CSDN博客 我们这里和参考链接不同 使用结构体去存储每个因数的信息 然后使用变量index作为索引,其最终值为因数的个数 具体原理: 例子1:求9!在10进制下的…...

mysql之用户管理、权限管理、密码管理
用户管理 创建用户create user 杨20.0.0.13 identified by 123; 用户重命名rename user 杨20.0.0.13 to yang20.0.0.13; 删除用户drop user 杨20.0.0.13; 权限管理 查看用户权限show grants for 杨20.0.0.13; 赋予用户权限grant all privileges on *.* to 杨localhost id…...

图情档核心期刊 | 北大核心、CSSCI、CSCD
中文核心期刊要目总览(A Guide to the Core Journal of China, 简称北大核心): 主办单位:北京大学图书馆更新频率:北大核心在2008年之前每4年更新研究和编制出版一次,2008年之后,改为…...

Mac上具好用的屏幕录像工具(Omi录屏专家)Screen Recorder By Omi Mac 下载安装详细教程
Omi 录屏专家 是 Mac 上的一款出色的录音工具,它让您能够在Mac电脑上轻松录制和保存高质量音频。这款应用拥有简单直观的操作界面,无论我们水平如何,都可以轻松捕捉录制卓越的音质和录像视频。 该版本的 Omi 安装后可以直接支持最高 4K 60帧…...

牛客网刷题-(8)
🌈write in front🌈 🧸大家好,我是Aileen🧸.希望你看完之后,能对你有所帮助,不足请指正!共同学习交流. 🆔本文由Aileen_0v0🧸 原创 CSDN首发🐒 如…...

oracle 重启步骤及踩坑经验
oracle 重启步骤及踩坑经验 标准重启步骤 切换到oracle用户 su - oracle关闭监听 lsnrctl stop杀掉oracle有关进程 ps -ef|grep $ORACLE_SID|grep -v ora_|grep LOCALNO|awk {print $2}|xargs kill -9#查询pid ps -ef|grep $ORACLE_SID|grep -v ora_|grep LOCALNO|awk {p…...

处理mysql数据量大查询缓慢问题(最少百万才有差别)
我建了两个表,一个售后单表,一个售后商品明细表,都是五十个字段。 select * FROM (select id, as_id, as_date, outer_as_id, so_id, type, created, modified, status, status_name, shop_status, shop_status_name, remark, question_type,…...

element-plus走马灯不显示
问题描述 依赖正确,代码用法正确,但是element-plu走马灯就是不显示!! <div class"content"><el-carousel height"150px" width"200px"><el-carousel-item v-for"item in 4&qu…...

【精】UML及软件管理工具汇总
目录 1 老七工具(规划质量) 1.1 因果图(鱼骨图、石川图) 1.2 控制图 1.3 流程图:也称过程图 1.4 核查表:又称计数表 1.5 直方图 1.6 帕累托图 1.7 散点图…...

【uniapp+vue3】scroll-view实现纵向自动滚动及swiper实现纵向自动滚动
scroll-view本身不支持自动滚动,通过scroll-top属性控制滚动,但是不可以循环滚动 <scroll-view class"notice-bar" scroll-y"true" ref"scrollViewRef" :scroll-top"data.scrollViewTop"scroll-with-animati…...

this.refs[‘tagInput‘].refs.input.focus()和this.$refs[‘tagInput‘].focus()区别
this.$refs[tagInput].$refs.input.focus()和this.$refs[tagInput].focus()两者之间的选择取决于你的组件结构和如何访问DOM元素。 1.this.$refs[tagInput].$refs.input.focus(): 2.这种语法假设你的this.$refs[tagInput]是一个组件实例,并且这个组件实例有一个名为…...

电脑硬件坏了,如何维修?
在电子设备日益普及的今天,电脑已成为很多人生活和工作中不可或缺的工具,然而在使用过程中很容易遇见电脑故障之类的问题,这些问题十有八九来自硬件,那么针对电脑硬件问题,该如何维修? 一般来说,…...

elementplus日期时间选择器组件显示很窄
问题描述 似乎是elementplus原生组件的宽度是和父组件相关的 只要父组件很窄就会让弹窗也很窄,但其实两者的宽度不必有这种限制 解决思路 打开控制条查看元素位置以及css样式的class名 发现类名为el-picker-panel__body 尝试重构 css内写样式 .el-picker-pane…...

第三方软件测评选择远程测试好还是现场测试好?
如今许多软件企业在软件开发过程完成之后,会将软件测试工作交由第三方软件测评机构来进行,那么做第三方软件测试时,远程测试和现场测试哪个更好呢?我想这是许多软件企业都十分关注的问题,今天卓码软件测评小编将对以上问题作出简…...

HTTPS协议:保障网络安全的加密通信协议
在当今数字化时代,网络安全问题备受关注。为了保护用户的隐私和数据安全,HTTPS协议应运而生。本文将介绍HTTPS协议的定义、工作原理以及其在网络通信中的重要性。 一、HTTPS协议的定义 HTTPS(Hypertext Transfer Protocol Secure)…...

C++设计模式_21_Iterator 迭代器(理解;面向对象的迭代器已过时;C++中使用泛型编程的方式实现)
Iterator 迭代器也是属于“数据结构”模式。GoF中面向对象的迭代器已经过时,C中目前使用泛型编程的方式实现,其他语言还在使用面向对象的迭代器。 文章目录 1. 动机(Motivation)2. 模式定义3. Iterator 迭代器代码分析4. 面向对象的迭代器与泛型编程实现…...

有一个 3*4 的矩阵,找出其中值最大的元素,及其行列号
1解题思路: 首先学会输入二维数组;然后知道如何比较求最大值;最后就是格式问题; 2代码: #include<stdio.h> int main() {int a[3][4];int i,j,max,row,line;for(i0;i<3;i){printf("请输入二维数组\n&…...

磁盘的命令
目录 1- 磁盘空间命令1.1 df1.2 du只想查看目录的权限 加 -d 参数 1- 磁盘空间命令 1.1 df 全称 disk free 快速获取磁盘被占用了多少空间, 目前还剩下所少空间 常用命令df -hdf 是从总体上统计系统各磁盘的占用情况,不能统计具体的文件夹或文件的大小 1.2 du 全称 disk u…...

一张图讲清楚业务稳定性要如何做:SRE体系化稳定性方案
概述:作为一个SRE、运维工程师,当我们在治理系统稳定性时,方法有很多,但往往无从下手。本文以一张逻辑图的形式,为读者提供治理稳定性的体系化思路。 先上图: 1、治理目标 我们做稳定性的目标,…...

安卓端GB28181设备接入模块如何实现实时位置订阅(MobilePosition)
技术背景 实时位置(MobilePosition)订阅和上报,对GB28281设备接入终端尤其重要,如移动单兵设备、执法记录仪、智能安全帽、车载终端等,Android国标接入设备通过获取到实时经纬度信息,按照一定的间隔上报到…...

11.与JavaScript深入交流-[js一篇通]
文章目录 1.变量的使用1.1基本用法1.2理解 动态类型 2.基本数据类型2.1number 数字类型2.1.1数字进制表示2.1.2特殊的数字值 2.2string 字符串类型2.2.1基本规则2.2.2转义字符2.2.3求长度2.2.4字符串拼接 2.3boolean 布尔类型2.4undefined 未定义数据类型2.5null 空值类型 3.运…...

Ubuntu 搭建 DHCP ivp6 server 步骤
Ubuntu 搭建 DHCP ivp6 server 步骤 安装 DHCP server安装 radvd(实现局域网路由功能)测试运行 安装 DHCP server apt 安装 isc-dhcp-server sudo apt-get install isc-dhcp-server修改配置文件 /etc/dhcp/dhcpd6.conf 内容如下: lease-time 7200; lo…...

分享大数据分析师前景怎么样? 从事行业有哪些?
数据分析师发展前景和待遇怎么样?有前途吗?好找工作吗?根据某招聘网数据显示,当前市场表现为: 2023年较2022年同期对比增长160%,2022年较2021年下降了46%。 工资待遇:2023年较2022年下降了2…...

通过wordpress能搭建有影响力的帮助中心
wordpress建站服务是一种提供简单易用的工具和功能,帮助用户轻松创建和管理网站的服务。它适用于各类网站管理员、个人博主和小型企业主,无论是想要搭建个人博客、展示作品集还是开设在线商店,都可以通过wordpress建站服务来实现。 | 一、搭建…...

word页脚设置,页脚显示第几页共有几页设置步骤
word页脚设置,页脚显示第几页共有几页设置步骤: 具体步骤: 步骤1: 步骤1.1选择页脚---空白页脚 步骤1.2,在"[在此处键入]",直接输入你需要的格式,如 “第页/共页” 步骤1.3选择第“…...

C语言实现斐波那契数列的多种方法
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。对于解决此类问题方法有四,前两…...

一文解决:Swagger API 未授权访问漏洞问题
Swagger 是一个用于设计、构建、文档化和使用 RESTful 风格的 Web 服务的开源软件框架。它通过提供一个交互式文档页面,让开发者可以更方便地查看和测试 API 接口。然而,在一些情况下,未经授权的访问可能会导致安全漏洞。本文将介绍如何解决 …...

Elasticsearch下载安装,IK分词器、Kibana下载安装使用,elasticsearch使用演示
首先给出自己使用版本的网盘链接:自己的版本7.17.14 链接:https://pan.baidu.com/s/1FSlI9jNf1KRP-OmZlCkEZw 提取码:1234 一般情况下 Elastic Search(ES) 并不单独使用,例如主流的技术组合 ELK(…...

springboot自定义404页面
添加配置类 import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.servlet.Servlet; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.valves.ErrorReportValve; import org.apache.coyote.UpgradeProtoc…...