Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析

 在前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)驱动程序源代码分析中,我们系统地介绍了Android系统匿名共享内存的实现原理,其中着重介绍了它是如何辅助内存管理系统来有效地管理内存的,在再前面一篇文章Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划中,我们还提到,Android系统匿名共享内存的另外一特点是通过Binder进程间通信机制来实现进程间共享的,本文中,将详细介绍Android系统匿名共享内存是如何使用Binder进程间通信机制来实现进程间共享的。

        由于Android系统匿名共享内存在进程间共享的原理涉及到Binder进程间通信机制的相关知识,所以希望读者在继续阅读本文之前,最好对Android系统的Binder进程间通信机制有一定的了解,具体可以参考Android进程间通信(IPC)机制Binder简要介绍和学习计划这篇文章。

        在Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划这篇文章中,我们举了一个例子来简要地介绍了Android系统的匿名共享内存机制及其使用方法,在这篇文章中,我们继续以这个实例来说明Android系统的匿名共享内存是如何使用Binder进程间通信机制来实现进程间共享的。为了方便描述,结合前面的Binder进程间通信机制知识,我们通过下面这个序列图来总结这个实例中的匿名共享内存文件的文件描述符在进程间传输的过程:

        这里, 我们需要关注的便是虚线框部分了,它在Binder驱动程序中实现了在两个进程中共享同一个打开文件的方法。我们知道,在Linux系统中,文件描述符其实就是一个整数。每一个进程在内核空间都有一个打开文件的数组,这个文件描述符的整数值就是用来索引这个数组的,而且,这个文件描述符只是在本进程内有效,也就是说,在不同的进程中,相同的文件描述符的值,代表的可能是不同的打开文件。因此,在进程间传输文件描述符时,不能简要地把一个文件描述符从一个进程传给另外一个进程,中间必须做一过转换,使得这个文件描述在目标进程中是有效的,并且它和源进程的文件描述符所对应的打开文件是一致的,这样才能保证共享。

        在浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路一文中,我们介绍了用来传输的Binder对象的数据结构struct flat_binder_object,它定义在kernel/common/drivers/staging/android/binder.h 文件中:

 
  1. /*  
  2.  * This is the flattened representation of a Binder object for transfer  
  3.  * between processes.  The 'offsets' supplied as part of a binder transaction 
  4.  * contains offsets into the data where these structures occur.  The Binder  
  5.  * driver takes care of re-writing the structure type and data as it moves  
  6.  * between processes.  
  7.  */  
  8. struct flat_binder_object {  
  9.     /* 8 bytes for large_flat_header. */  
  10.     unsigned long       type;  
  11.     unsigned long       flags;  
  12.  
  13.     /* 8 bytes of data. */  
  14.     union {  
  15.         void        *binder;    /* local object */  
  16.         signed long handle;     /* remote object */  
  17.     };  
  18.  
  19.     /* extra data associated with local object */  
  20.     void            *cookie;  
  21. }; 

       域type是一个枚举类型,它的取值范围是:

 
  1. enum {  
  2.     BINDER_TYPE_BINDER  = B_PACK_CHARS('s''b''*', B_TYPE_LARGE),  
  3.     BINDER_TYPE_WEAK_BINDER = B_PACK_CHARS('w''b''*', B_TYPE_LARGE),  
  4.     BINDER_TYPE_HANDLE  = B_PACK_CHARS('s''h''*', B_TYPE_LARGE),  
  5.     BINDER_TYPE_WEAK_HANDLE = B_PACK_CHARS('w''h''*', B_TYPE_LARGE),  
  6.     BINDER_TYPE_FD      = B_PACK_CHARS('f''d''*', B_TYPE_LARGE),  
  7. }; 

        这里我们要介绍的Binder对象的type便是BINDER_TYPE_FD了,要传输的文件描述符的值保存在handle域中。

 

        在Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析一文中,我们详细介绍了Binder对象在进程间通信传输的完整过程,这里就不再详述了,有兴趣的读都可以回过头去参考一下。这里,我们只关注文件描述符类型的Binder对象在Binder驱动程序中的相关处理逻辑。

        文件描述符类型的Binder对象在Binder驱动程序中的相关处理逻辑实现在binder_transact函数,这个函数定义在kernel/common/drivers/staging/android/binder.c文件中:

 
  1. static void  
  2. binder_transaction(struct binder_proc *proc, struct binder_thread *thread,  
  3. struct binder_transaction_data *tr, int reply)  
  4. {  
  5.     struct binder_transaction *t;  
  6.     struct binder_work *tcomplete;  
  7.     size_t *offp, *off_end;  
  8.     struct binder_proc *target_proc;  
  9.     struct binder_thread *target_thread = NULL;  
  10.     struct binder_node *target_node = NULL;  
  11.     struct list_head *target_list;  
  12.     wait_queue_head_t *target_wait;  
  13.     struct binder_transaction *in_reply_to = NULL;  
  14.     struct binder_transaction_log_entry *e;  
  15.     uint32_t return_error;  
  16.  
  17.     ......  
  18.       
  19.  
  20.     offp = (size_t *)(t->buffer->data + ALIGN(tr->data_size, sizeof(void *)));  
  21.  
  22.     ......  
  23.  
  24.     off_end = (void *)offp + tr->offsets_size;  
  25.     for (; offp < off_end; offp++) {  
  26.         struct flat_binder_object *fp;  
  27.         ......  
  28.         fp = (struct flat_binder_object *)(t->buffer->data + *offp);  
  29.         switch (fp->type) {  
  30.         ......  
  31.         case BINDER_TYPE_FD: {  
  32.             int target_fd;  
  33.             struct file *file;  
  34.  
  35.             if (reply) {  
  36.                 if (!(in_reply_to->flags & TF_ACCEPT_FDS)) {  
  37.                     binder_user_error("binder: %d:%d got reply with fd, %ld, but target does not allow fds\n",  
  38.                                     proc->pid, thread->pid, fp->handle);  
  39.                     return_error = BR_FAILED_REPLY;  
  40.                     goto err_fd_not_allowed;  
  41.                 }  
  42.             } else if (!target_node->accept_fds) {  
  43.                 binder_user_error("binder: %d:%d got transaction with fd, %ld, but target does not allow fds\n",  
  44.                                 proc->pid, thread->pid, fp->handle);  
  45.                 return_error = BR_FAILED_REPLY;  
  46.                 goto err_fd_not_allowed;  
  47.             }  
  48.  
  49.             file = fget(fp->handle);  
  50.             if (file == NULL) {  
  51.                 binder_user_error("binder: %d:%d got transaction with invalid fd, %ld\n",  
  52.                                     proc->pid, thread->pid, fp->handle);  
  53.                 return_error = BR_FAILED_REPLY;  
  54.                 goto err_fget_failed;  
  55.             }  
  56.             target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC);  
  57.             if (target_fd < 0) {  
  58.                 fput(file);  
  59.                 return_error = BR_FAILED_REPLY;  
  60.                 goto err_get_unused_fd_failed;  
  61.             }  
  62.             task_fd_install(target_proc, target_fd, file);  
  63.             if (binder_debug_mask & BINDER_DEBUG_TRANSACTION)  
  64.                     printk(KERN_INFO "        fd %ld -> %d\n", fp->handle, target_fd);  
  65.             /* TODO: fput? */  
  66.             fp->handle = target_fd;  
  67.         } break;  
  68.  
  69.         ......  
  70.         }  
  71.     }  
  72.       
  73.     ......  
  74.  

        这里,我们先明确一下在Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划这篇文章中所举的例子获取匿名共享内存文件的文件描述符的场景。匿名共享内存文件是在Server进程创建的,Client通过IMemoryService.getFileDescriptor去获取Server进程所创建的匿名共享内存文件的文件描述符,Server进程在返回这个文件描述符的过程中进入到Binder驱动程序,即这里的binder_transact函数。因此,这里的当前执行binder_transact函数的进程是Server进程,即源进程是Server进程,而目标进程是Client进程,就是这里的target_proc所表示的进程了。

 

        函数binder_transaction处理文件描述符类型的Binder对象就在中间的for循环里面。

       首先是获得Binder对象,并保存在本地变量fp中:

 
  1. fp = (struct flat_binder_object *)(t->buffer->data + *offp); 

       文件描述符的值就保存在fp->handle中,通过fget函数取回这个文件描述符所对应的打开文件结构:

 
  1. file = fget(fp->handle); 

      这里的file是一个struct file指针,它表示一个打开文件结构。注间,在Linux系统中,打开文件结构struct file是可以在进程间共享的,它与文件描述符不一样。

 

       接着在目标进程中获得一个空闲的文件描述符:

 
  1. target_fd = task_get_unused_fd_flags(target_proc, O_CLOEXEC); 

       现在,在目标进程中,打开文件结构有了,文件描述符也有了,接下来就可以把这个文件描述符和这个打开文件结构关联起来就可以了:

 
  1. task_fd_install(target_proc, target_fd, file); 

       由于这个Binder对象最终是要返回给目标进程的,所以还要修改fp->handle的值,它原来表示的是在源进程中的文件描述符,现在要改成目标进程的文件描述符:

 
  1. fp->handle = target_fd; 
      

       这样,对文件描述符类型的Binder对象的处理就完成了。目标进程拿到这个文件描述符后,就可以和源进程一起共享打开文件了。

 

       至此,Android系统匿名共享内存利用Binder进程间通信机制来实现进程间共享的学习就结束了,整个Android系统匿名共享内存机制的学习也完成了,希望对读者有所帮助,重新学习Android系统匿名共享内存机制请回到Android系统匿名共享内存Ashmem(Anonymous Shared Memory)简要介绍和学习计划一文。





本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/965501,如需转载请自行联系原作者

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/286308.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

转帖-Linux学习(Find命令使用实例)

为什么80%的码农都做不了架构师&#xff1f;>>> find / -name httpd.conf find / -name access_log 2>/dev/null find /etc -name *srm* find / -amin -10 # 查找在系统中最后10分钟访问的文件 find / -atime -2 # 查找在系统中最后48小时访问的文件 find / -mm…

Landsat中国西北地区行列号Shapefile图层对照(附行列号Shapefile下载)

GISer们,在下载Landsat卫星影像数据时,你还在为研究区的影响行列号犯愁吗?你还在苦苦对照图片吗?你Out了!重磅来了,本文提供了中国西北地区的Shapefile格式的矢量图层,和你的研究区叠在一起,是不是可以很快找出你想要的行列号呢? 《中国区域Modis行列号,Landsat条带…

|洛谷|动态规划|P1164 小A点菜

http://www.luogu.org/record/lists?pidP1164 01背包方案数#include<cstdio> #include<algorithm> #include<cstring> #define ms(i,j) memset(i,j, sizeof i); using namespace std; int n,m; int a[105]; int f[10005]; int main() {scanf("%d%d&quo…

MAUI 入门教程系列(1.框架简介)

前言在2020年5月, 微软宣布了MAUI跨平台框架, MAUI 是Xamarin.Forms演变而来, 这也就意味着, 如果你原来具备Xamarin.Forms开发经验, 你可以流畅的过渡到MAUI开发当中。原本于2021年底发布的MAUI正式版被推迟到了2022年5月底发布。现在, 你目前可以通过安装VS2022 预览版进行安…

ivx动效按钮 基础按钮制作 02

本节示例&#xff1a; 一、特效块的制作 在上一节中制作了一个可以增加动效的自定义按钮后&#xff0c;这一节通过这个行按钮对其进行特效制作。 在行按钮中的绝对定位中&#xff0c;我们创建一个行&#xff0c;命名为移入&#xff0c;接下来我们做一个移入动效&#xff1a…

C语言试题二十之利用以下的简单迭代方法求方程cos(x)-x=0的一个实根。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 编写函数fu…

最新Modis影像数据下载完整流程---以MOD13Q1 NDVI数据下载为例(2020年12月2日更新)

本文详细讲解Modis数据的下载流程,以MOD13Q1影像为例,该数据为16天合成的空间分辨率为250m的NDVI产品,原始数据的投影为正弦曲线投影。 Modis数据MRT和ArcGIS处理方法集锦: 1.《ArcGIS10.8完美实现MODIS NDVI数据格式转换和投影变换》 2.《重磅!ArcGIS10.8 Python代码批量…

解决夜神模拟器无法联机调试 adb server version (**) doesn't match this client (**); killing...

前言 最新下了个最新版的夜神模拟器&#xff0c;然后adb devices发现连不上模拟器了&#xff0c;报adb server version (**) doesnt match this client (##); killing... 从报错信息看是adb版本不匹配导致的&#xff0c;接下来讲如何解决这个问题 环境&#xff1a; 夜神模拟器…

WCF分布式开发常见错误(25):The certificate 'CN=WCFHTTPS' must have a private key

在准备WCF安全开发实践编程系列文章的时候&#xff0c;制作证书出现这个问题。The certificate CNWCFHTTPS must have a private key that is capable of key exchange. The process must have access rights for the private key.证书必须有一个可以交换密钥的私钥&#xff0c…

lintcode二叉树的锯齿形层次遍历 (双端队列)

题目链接&#xff1a; http://www.lintcode.com/zh-cn/problem/binary-tree-zigzag-level-order-traversal/ 二叉树的锯齿形层次遍历 给出一棵二叉树&#xff0c;返回其节点值的锯齿形层次遍历&#xff08;先从左往右&#xff0c;下一层再从右往左&#xff0c;层与层之间交替进…

C语言试题二十一之定义n×n的二维数组编写函数 function(int a[][n])功能是:使数组左下半三角元素中的值全部置成0。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 定义了nn的…

【前端就业课 第二阶段】CSS 零基础到实战(02)列表

整个前端学习路线 以下路线为 CSDN C认提供&#xff1a; 如果想 快点搞完 并且 就业 可以选择C认证&#xff0c;C认证还可以 内推、招聘会 &#xff0c;所以如果在校生想要稳一点&#xff0c;就可以选择C认证或者超级实习生计划&#xff0c;贼稳&#xff01; 链接在这PC端&…

【专升本计算机】甘肃省2020年专升本计算机测试题

文章目录 第一部分 公共基础部分第二部分 数据库部分(文史财经类)第三部分 C语言部分(理工农医类)第四部分 综合部分第一部分 公共基础部分 一、单项选择(90题,每题1分,共90分) 世界上第一台电子计算机诞生于( )年。 A. 1956 B. 1946 C. 1944 D. 1940目前,第二代计…

Docker Eats Disk?

背景介绍下午 5:30&#xff0c;差不多到点打卡下班&#xff0c;准备好零食饮料&#xff0c;放松一下准备下班&#xff0c;然后...CI 构建失败&#xff0c;经典的一幕&#xff01;&#xff01;&#xff01;无法从镜像仓库拉取镜像&#xff0c;docker 正常运行&#xff0c;为什么…

C#网络编程(订立协议和发送文件) - Part.4

转载自&#xff1a;http://www.tracefact.net/CSharp-Programming/Network-Programming-Part4.aspx 文件传输 前面两篇文章所使用的范例都是传输字符串&#xff0c;有的时候我们可能会想在服务端和客户端之间传递文件。比如&#xff0c;考虑这样一种情况&#xff0c;假如客户端…

Android Studio怎么设置悬浮提示文字框显示函数

[摘要]AndroidStudio函数悬浮提示文字框设置方法一&#xff1a;AndroidStudio在默认情况下是不会和Eclipse那样&#xff0c;鼠标移动到一个类或... Android Studio函数悬浮提示文字框设置方法一&#xff1a; Android Studio在默认情况下是不会和Eclipse那样&#xff0c;鼠标移…

消息队列入门(三)JMS标准及实现

消息中间件 消息中间件即Message-oriented middleware(MOM)&#xff0c;消息中间件利用高效可靠的消息传递机制进行平台无关的数据交流&#xff0c;并基于数据通信来进行分布式系统的集成。 通过提供消息传递和消息排队模型&#xff0c;消息中间件可以在分布式环境下扩展进程间…

C语言试题二十二之定义了3×3的二维数组,并在主函数中赋值。函数的功能使求出数组周边元素的平均值并作为函数值返回给主函数中的s。

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 定义了33的…

【专升本计算机】专升本计算机期末考试复习题(A卷附答案)

文章目录 一、单选题(每空2分,共20分)。二、填空题(每空2分,共30分)。三、程序题(每小题10分,共50分)一、单选题(每空2分,共20分)。 世界上第一台电子计算机诞生于( B )年。 A.1956   B.1946   C.1944   D.1940以下不属于数字计算机特点的是 C__ 。 A.运算…

spring定时任务的配置使用

spring的定时任务配置分为三个步骤&#xff1a; 1、定义任务 2、任务执行策略配置 3、启动任务 1、定义任务 <!--要定时执行的方法--> <bean id"testTaskJob" class"org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean&qu…