Android系统匿名共享内存(Anonymous Shared Memory)C++调用接口分析(5)

简介:
下面我们再来看MemoryBase类在Client端的实现,同样,先看它们的类图关系:
     这个图中我们可以看出,MemoryBase类在Client端的实现与MemoryHeapBase类在Client端的实现是类似的,这里只要把IMemory类换成IMemoryHeap类以及把BpMemory类换成BpMemoryHeap类就变成是MemoryHeapBase类在Client端的实现了,因此,我们这里只简单分析BpMemory类的实现,前面已经分析过IMemory类的实现了。
        BpMemory类实现在frameworks/base/libs/binder/IMemory.cpp文件中,我们先看它的声明:
  1. class BpMemory : public BpInterface<IMemory>  
  2. {  
  3. public:  
  4.     BpMemory(const sp<IBinder>& impl);  
  5.     virtual ~BpMemory();  
  6.     virtual sp<IMemoryHeap> getMemory(ssize_t* offset=0, size_t* size=0) const;  
  7.   
  8. private:  
  9.     mutable sp<IMemoryHeap> mHeap;  
  10.     mutable ssize_t mOffset;  
  11.     mutable size_t mSize;  
  12. };  
       和MemoryBase类一样,它实现了IMemory类的getMemory成员函数,在它的成员变量中,mHeap的类型为IMemoryHeap,它指向的是一个BpMemoryHeap对象,mOffset表示这个BpMemory对象所要维护的这部分匿名共享内存在整个匿名共享内存块中的起始位置,mSize表示这个BpMemory对象所要维护的这部分匿名共享内存的大小。
 
       下面我们就看一下BpMemory类的成员函数getMemory的实现:
  1. sp<IMemoryHeap> BpMemory::getMemory(ssize_t* offset, size_t* size) const  
  2. {  
  3.     if (mHeap == 0) {  
  4.         Parcel data, reply;  
  5.         data.writeInterfaceToken(IMemory::getInterfaceDescriptor());  
  6.         if (remote()->transact(GET_MEMORY, data, &reply) == NO_ERROR) {  
  7.             sp<IBinder> heap = reply.readStrongBinder();  
  8.             ssize_t o = reply.readInt32();  
  9.             size_t s = reply.readInt32();  
  10.             if (heap != 0) {  
  11.                 mHeap = interface_cast<IMemoryHeap>(heap);  
  12.                 if (mHeap != 0) {  
  13.                     mOffset = o;  
  14.                     mSize = s;  
  15.                 }  
  16.             }  
  17.         }  
  18.     }  
  19.     if (offset) *offset = mOffset;  
  20.     if (size) *size = mSize;  
  21.     return mHeap;  
  22. }  
        如果成员变量mHeap的值为NULL,就表示这个BpMemory对象尚未建立好匿名共享内存,于是,就会通过一个Binder进程间调用去Server端请求匿名共享内存信息,在这些信息中,最重要的就是这个Server端的MemoryHeapBase对象的引用heap了,通过这个引用可以在Client端进程中创建一个BpMemoryHeap远程接口,最后将这个BpMemoryHeap远程接口保存在成员变量mHeap中,同时,从Server端获得的信息还包括这块匿名共享内存在整个匿名共享内存中的偏移位置以及大小。这样,这个BpMemory对象中的匿名共享内存就准备就绪了。
 
        至此,MemoryBase类的实现就分析完了,下面我们将通过一个实例来说明如何使用MemoryBase类在进程间进行内存共享,因为MemoryBase内部使用了MemoryHeapBase类,所以,这个例子同时也可以说明MemoryHeapBase类的使用方法。
        3. MemoryHeapBas类e和MemoryBase类的使用示例
        在这个例子中,我们将在Android源代码工程的external目录中创建一个ashmem源代码工程,它里面包括两个应用程序,一个是Server端应用程序SharedBufferServer,它提供一段共享内存来给Client端程序使用,一个是Client端应用程序SharedBufferClient,它简单地对Server端提供的共享内存进行读和写的操作。Server端应用程序SharedBufferServer和Client端应用程序SharedBufferClient通过Binder进程间通信机制来交互,因此,我们需要定义自己的Binder对象接口ISharedBuffer。Server端应用程序SharedBufferServer在内部实现了一个服务SharedBufferService,这个服务托管给Service Manager来管理,因此,Client端应用程序SharedBufferClient可以向Service Manager请求这个SharedBufferService服务的一个远接接口,然后就可以通过这个服务来操作Server端提供的这段共享内存了。
        这个工程由三个模块组成,第一个模块定义服务接口,它的相关源代码位于external/ashmem/common目录下,第二个模块实现Server端应用程序SharedBufferServer,它的相关源代码位于external/ashmem/server目录下,第三个模块实现Client端应用程序SharedBufferClient,它的相关源代码码位于external/ashmem/client目录下。
        首先来看common模块中的服务接口的定义。在external/ashmem/common目录下,有两个源文件ISharedBuffer.h和ISharedBuffer.cpp。源文件ISharedBuffer.h定义了服务的接口:
  1. #ifndef ISHAREDBUFFER_H_  
  2. #define ISHAREDBUFFER_H_  
  3.   
  4. #include <utils/RefBase.h>  
  5. #include <binder/IInterface.h>  
  6. #include <binder/Parcel.h>  
  7.   
  8. #define SHARED_BUFFER_SERVICE "shy.luo.SharedBuffer"  
  9. #define SHARED_BUFFER_SIZE 4  
  10.   
  11. using namespace android;  
  12.   
  13. class ISharedBuffer: public IInterface  
  14. {  
  15. public:  
  16.         DECLARE_META_INTERFACE(SharedBuffer);  
  17.         virtual sp<IMemory> getBuffer() = 0;  
  18. };  
  19.   
  20. class BnSharedBuffer: public BnInterface<ISharedBuffer>  
  21. {  
  22. public:  
  23.         virtual status_t onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags = 0);  
  24. };  
  25.   
  26. #endif  
        这个文件定义了一个ISharedBuffer接口,里面只有一个成员函数getBuffer,通过这个成员函数,Client端可以从Server端获得一个匿名共享内存,这块匿名共享内存通过我们上面分析的MemoryBase类来维护。这个文件同时也定义了一个必须要在Server端实现的BnSharedBuffer接口,它里面只有一个成员函数onTransact,这个成员函数是用来处理Client端发送过来的请求的。除了定义这两个接口之外,这个文件还定义了两个公共信息,一个是定义常量SHARED_BUFFER_SERVICE,它是Server端提供的内存共享服务的名称,即这个内存共享服务在Service Manager中是以SHARED_BUFFER_SERVICE来作关键字索引的,另外一个是定义常量SHARED_BUFFER_SIZE,它定义了Server端共享的内存块的大小,它的大小设置为4个字节,在这个例子,将把这个共享内存当作一个整型变量来访问。
 
        源代文件ISharedBuffer.cpp文件定义了一个在Client端使用的BpSharedBuffer接口,它是指向运行在Server端的实现了ISharedBuffer接口的内存共享服务的远程接口,同时,在这个文件里面,也实现了BnSharedBuffer类的onTransact成员函数:
  1. #define LOG_TAG "ISharedBuffer"  
  2.   
  3. #include <utils/Log.h>  
  4. #include <binder/MemoryBase.h>  
  5.   
  6. #include "ISharedBuffer.h"  
  7.   
  8. using namespace android;  
  9.   
  10. enum  
  11. {  
  12.     GET_BUFFER = IBinder::FIRST_CALL_TRANSACTION  
  13. };  
  14.   
  15. class BpSharedBuffer: public BpInterface<ISharedBuffer>  
  16. {  
  17. public:  
  18.     BpSharedBuffer(const sp<IBinder>& impl)  
  19.         : BpInterface<ISharedBuffer>(impl)  
  20.     {  
  21.   
  22.     }  
  23.   
  24. public:  
  25.     sp<IMemory> getBuffer()  
  26.     {  
  27.         Parcel data;  
  28.         data.writeInterfaceToken(ISharedBuffer::getInterfaceDescriptor());  
  29.   
  30.         Parcel reply;  
  31.         remote()->transact(GET_BUFFER, data, &reply);  
  32.   
  33.         sp<IMemory> buffer = interface_cast<IMemory>(reply.readStrongBinder());  
  34.   
  35.         return buffer;  
  36.     }  
  37. };  
  38.   
  39. IMPLEMENT_META_INTERFACE(SharedBuffer, "shy.luo.ISharedBuffer");  
  40.   
  41. status_t BnSharedBuffer::onTransact(uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags)  
  42. {  
  43.     switch(code)  
  44.     {  
  45.     case GET_BUFFER:  
  46.         {  
  47.             CHECK_INTERFACE(ISharedBuffer, data, reply);  
  48.   
  49.             sp<IMemory> buffer = getBuffer();  
  50.             if(buffer != NULL)  
  51.             {  
  52.                 reply->writeStrongBinder(buffer->asBinder());  
  53.             }  
  54.   
  55.             return NO_ERROR;  
  56.         }  
  57.     default:  
  58.         {  
  59.             return BBinder::onTransact(code, data, reply, flags);  
  60.         }  
  61.     }  
  62. }  
        在BpSharedBuffer类的成员函数transact中,向Server端发出了一个请求代码为GET_BUFFER的Binder进程间调用请求,请求Server端返回一个匿名共享内存对象的远程接口IMemory,它实际指向的是一个BpMemory对象,获得了这个对象之后,就将它返回给调用者;在BnSharedBuffer类的成员函数onTransact中,当它接收到从Client端发送过来的代码为GET_BUFFER的Binder进程间调用请求后,便调用其子类的getBuffer成员函数来获一个匿名共享内存对象接口IMemory,它实际指向的是一个MemoryBase对象,获得了这个对象之后,就把它返回给Client端。
 




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966920,如需转载请自行联系原作者
目录
相关文章
|
4月前
|
开发框架 前端开发 Android开发
Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势
本文深入探讨了 Flutter 与原生模块(Android 和 iOS)之间的通信机制,包括方法调用、事件传递等,分析了通信的必要性、主要方式、数据传递、性能优化及错误处理,并通过实际案例展示了其应用效果,展望了未来的发展趋势。这对于实现高效的跨平台移动应用开发具有重要指导意义。
412 4
|
4月前
|
安全 Android开发 数据安全/隐私保护
深入探讨iOS与Android系统安全性对比分析
在移动操作系统领域,iOS和Android无疑是两大巨头。本文从技术角度出发,对这两个系统的架构、安全机制以及用户隐私保护等方面进行了详细的比较分析。通过深入探讨,我们旨在揭示两个系统在安全性方面的差异,并为用户提供一些实用的安全建议。
|
18天前
|
存储 监控 算法
员工屏幕监控系统之 C++ 图像差分算法
在现代企业管理中,员工屏幕监控系统至关重要。本文探讨了其中常用的图像差分算法,该算法通过比较相邻两帧图像的像素差异,检测屏幕内容变化,如应用程序切换等。文中提供了C++实现代码,并介绍了其在实时监控、异常行为检测和数据压缩等方面的应用,展示了其实现简单、效率高的特点。
40 15
|
2月前
|
存储 算法 安全
基于哈希表的文件共享平台 C++ 算法实现与分析
在数字化时代,文件共享平台不可或缺。本文探讨哈希表在文件共享中的应用,包括原理、优势及C++实现。哈希表通过键值对快速访问文件元数据(如文件名、大小、位置等),查找时间复杂度为O(1),显著提升查找速度和用户体验。代码示例展示了文件上传和搜索功能,实际应用中需解决哈希冲突、动态扩容和线程安全等问题,以优化性能。
|
2月前
|
存储 程序员 编译器
什么是内存泄漏?C++中如何检测和解决?
大家好,我是V哥。内存泄露是编程中的常见问题,可能导致程序崩溃。特别是在金三银四跳槽季,面试官常问此问题。本文将探讨内存泄露的定义、危害、检测方法及解决策略,帮助你掌握这一关键知识点。通过学习如何正确管理内存、使用智能指针和RAII原则,避免内存泄露,提升代码健壮性。同时,了解常见的内存泄露场景,如忘记释放内存、异常处理不当等,确保在面试中不被秒杀。最后,预祝大家新的一年工作顺利,涨薪多多!关注威哥爱编程,一起成为更好的程序员。
|
4月前
|
安全 Android开发 数据安全/隐私保护
深入探索Android与iOS系统安全性的对比分析
在当今数字化时代,移动操作系统的安全已成为用户和开发者共同关注的重点。本文旨在通过比较Android与iOS两大主流操作系统在安全性方面的差异,揭示两者在设计理念、权限管理、应用审核机制等方面的不同之处。我们将探讨这些差异如何影响用户的安全体验以及可能带来的风险。
127 21
|
3月前
|
Java 开发工具 Android开发
安卓与iOS开发环境对比分析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自占据半壁江山。本文深入探讨了这两个平台的开发环境,从编程语言、开发工具到用户界面设计等多个角度进行比较。通过实际案例分析和代码示例,我们旨在为开发者提供一个清晰的指南,帮助他们根据项目需求和个人偏好做出明智的选择。无论你是初涉移动开发领域的新手,还是寻求跨平台解决方案的资深开发者,这篇文章都将为你提供宝贵的信息和启示。
53 8
|
5月前
|
缓存 Java Shell
Android 系统缓存扫描与清理方法分析
Android 系统缓存从原理探索到实现。
149 15
Android 系统缓存扫描与清理方法分析
|
4月前
|
Ubuntu Linux Shell
C++ 之 perf+火焰图分析与调试
【11月更文挑战第6天】在遇到一些内存异常的时候,经常这部分的代码是很难去进行分析的,最近了解到Perf这个神器,这里也展开介绍一下如何使用Perf以及如何去画火焰图。
171 5
|
4月前
|
存储 编译器 Linux
【c++】类和对象(上)(类的定义格式、访问限定符、类域、类的实例化、对象的内存大小、this指针)
本文介绍了C++中的类和对象,包括类的概念、定义格式、访问限定符、类域、对象的创建及内存大小、以及this指针。通过示例代码详细解释了类的定义、成员函数和成员变量的作用,以及如何使用访问限定符控制成员的访问权限。此外,还讨论了对象的内存分配规则和this指针的使用场景,帮助读者深入理解面向对象编程的核心概念。
286 4