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

简介:
  回到前面BpMemoryHeap类中的assertMapped函数中,如果本BpMemoryHeap对象中的mHeapID等于-1,那么就说明这个BpMemoryHeap对象中的匿名共享内存还没准备就绪,因此,需要执行一次映射匿名共享内存的操作。
        在执行映射操作之作,先要看看在本进程中是否有其它映射到同一个MemoryHeapBase对象的BpMemoryHeap对象存在:
  1. sp<IBinder> binder(const_cast<BpMemoryHeap*>(this)->asBinder());  
  2. sp<BpMemoryHeap> heap(static_cast<BpMemoryHeap*>(find_heap(binder).get()));  
       这里的find_heap函数是BpMemoryHeap的成员函数,最终它调用了前面提到的全局变量gHeapCache来直正执行查找的操作:
  1. class BpMemoryHeap : public BpInterface<IMemoryHeap>  
  2. {     
  3. ......  
  4.   
  5. private:  
  6.     static inline sp<IMemoryHeap> find_heap(const sp<IBinder>& binder) {  
  7.         return gHeapCache->find_heap(binder);  
  8.     }  
  9.   
  10.     ......  
  11. }  
        注意,这里通过find_heap函数得到BpMemoryHeap对象可能是和正在执行assertMapped函数中的BpMemoryHeap对象一样,也可能不一样,但是这没有关系,这两种情况的处理方式都是一样的,都是通过调用这个通过find_heap函数得到BpMemoryHeap对象的assertReallyMapped函数来进一步确认它内部的匿名共享内存是否已经映射到进程空间了:
  1. void BpMemoryHeap::assertReallyMapped() const  
  2. {  
  3.     if (mHeapId == -1) {  
  4.   
  5.         // remote call without mLock held, worse case scenario, we end up  
  6.         // calling transact() from multiple threads, but that's not a problem,  
  7.         // only mmap below must be in the critical section.  
  8.   
  9.         Parcel data, reply;  
  10.         data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor());  
  11.         status_t err = remote()->transact(HEAP_ID, data, &reply);  
  12.         int parcel_fd = reply.readFileDescriptor();  
  13.         ssize_t size = reply.readInt32();  
  14.         uint32_t flags = reply.readInt32();  
  15.   
  16.         LOGE_IF(err, "binder=%p transaction failed fd=%d, size=%ld, err=%d (%s)",  
  17.             asBinder().get(), parcel_fd, size, err, strerror(-err));  
  18.   
  19.         int fd = dup( parcel_fd );  
  20.         LOGE_IF(fd==-1, "cannot dup fd=%d, size=%ld, err=%d (%s)",  
  21.             parcel_fd, size, err, strerror(errno));  
  22.   
  23.         int access = PROT_READ;  
  24.         if (!(flags & READ_ONLY)) {  
  25.             access |= PROT_WRITE;  
  26.         }  
  27.   
  28.         Mutex::Autolock _l(mLock);  
  29.         if (mHeapId == -1) {  
  30.             mRealHeap = true;  
  31.             mBase = mmap(0, size, access, MAP_SHARED, fd, 0);  
  32.             if (mBase == MAP_FAILED) {  
  33.                 LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)",  
  34.                     asBinder().get(), size, fd, strerror(errno));  
  35.                 close(fd);  
  36.             } else {  
  37.                 mSize = size;  
  38.                 mFlags = flags;  
  39.                 android_atomic_write(fd, &mHeapId);  
  40.             }  
  41.         }  
  42.     }  
  43. }  
        如果成员变量mHeapId的值为-1,就说明还没有把在Server端的MemoryHeapBase对象中的匿名共享内存映射到本进程空间来,于是,就通过一个Binder进程间调用把Server端的MemoryHeapBase对象中的匿名共享内存对象信息取回来:
  1. Parcel data, reply;  
  2. data.writeInterfaceToken(IMemoryHeap::getInterfaceDescriptor());  
  3. status_t err = remote()->transact(HEAP_ID, data, &reply);  
  4. int parcel_fd = reply.readFileDescriptor();  
  5. ssize_t size = reply.readInt32();  
  6. uint32_t flags = reply.readInt32();  
  7.   
  8. ......  
  9.   
  10. int fd = dup( parcel_fd );  
  11.           
  12. ......  
        取回来的信息包括MemoryHeapBase对象中的匿名共享内存在本进程中的文件描述符fd、大小size以及访问属性flags。如何把MemoryHeapBase对象中的匿名共享内存作为本进程的一个打开文件描述符,请参考前面一篇文章 Android系统匿名共享内存Ashmem(Anonymous Shared Memory)在进程间共享的原理分析 。有了这个文件描述符fd后,就可以对它进行内存映射操作了:
  1. Mutex::Autolock _l(mLock);  
  2. if (mHeapId == -1) {  
  3.     mRealHeap = true;  
  4.     mBase = mmap(0, size, access, MAP_SHARED, fd, 0);  
  5.     if (mBase == MAP_FAILED) {  
  6.         LOGE("cannot map BpMemoryHeap (binder=%p), size=%ld, fd=%d (%s)",  
  7.             asBinder().get(), size, fd, strerror(errno));  
  8.         close(fd);  
  9.     } else {  
  10.         mSize = size;  
  11.         mFlags = flags;  
  12.         android_atomic_write(fd, &mHeapId);  
  13.     }  
  14. }  
        前面已经判断过mHeapId是否为-1了,这里为什么又要重新判断一次呢?这里因为,在上面执行Binder进程间调用的过程中,很有可能也有其它的线程也对这个BpMemoryHeap对象执行匿名共享内存映射的操作,因此,这里还要重新判断一下mHeapId的值是否为-1,如果是的话,就要执行匿名共享内存映射的操作了,这是通过调用mmap函数来进行的,这个函数我们前面在分析MemoryHeapBase类的实现时已经见过了。
 
        从assertReallyMapped函数返回到assertMapped函数中:
  1. if (heap->mBase != MAP_FAILED) {  
  2.     Mutex::Autolock _l(mLock);  
  3.     if (mHeapId == -1) {  
  4.         mBase   = heap->mBase;  
  5.         mSize   = heap->mSize;  
  6.         android_atomic_write( dup( heap->mHeapId ), &mHeapId );  
  7.     }  
  8. else {  
  9.     // something went wrong  
  10.     free_heap(binder);  
  11. }  
        如果heap->mBase的值不为MAP_FAILED,就说明这个heap对象中的匿名共享内存已经映射好了。进入到里面的if语句,如果本BpMemoryHeap对象中的mHeap成员变量的值不等待-1,就说明前面通过find_heap函数得到的BpMemoryHeap对象和正在执行assertMapped函数的BpMemoryHeap对象是同一个对象了,因此,什么也不用做就可以返回了,否则的话,就要初始化一下本BpMemoryHeap对象的相关成员变量了:
  1. mBase   = heap->mBase;  
  2. mSize   = heap->mSize;  
  3. android_atomic_write( dup( heap->mHeapId ), &mHeapId );  
        注意,由于这块匿名共享内存已经在本进程中映射好了,因此,这里不需要再执行一次mmap操作,只需要把heap对象的相应成员变量的值拷贝过来就行了,不过对于文件描述符,需要通过dup函数来复制一个。
 
        这样,BpMemoryHeap对象中的匿名共享内存就准备就绪了,可以通过使用的它mBase成员变量来直接访问这块匿名共享内存。
        至此,MemoryHeapBase类的实现就分析完了,下面我们继续分析MemoryBase类的实现。




本文转自 Luoshengyang 51CTO博客,原文链接:http://blog.51cto.com/shyluo/966904,如需转载请自行联系原作者
目录
相关文章
|
2月前
|
缓存 Java Linux
如何解决 Linux 系统中内存使用量耗尽的问题?
如何解决 Linux 系统中内存使用量耗尽的问题?
146 48
|
25天前
|
机器学习/深度学习 人工智能 缓存
【AI系统】推理内存布局
本文介绍了CPU和GPU的基础内存知识,NCHWX内存排布格式,以及MNN推理引擎如何通过数据内存重新排布进行内核优化,特别是针对WinoGrad卷积计算的优化方法,通过NC4HW4数据格式重排,有效利用了SIMD指令集特性,减少了cache miss,提高了计算效率。
44 3
|
28天前
|
监控 Java Android开发
深入探索Android系统的内存管理机制
本文旨在全面解析Android系统的内存管理机制,包括其工作原理、常见问题及其解决方案。通过对Android内存模型的深入分析,本文将帮助开发者更好地理解内存分配、回收以及优化策略,从而提高应用性能和用户体验。
|
29天前
|
机器学习/深度学习 人工智能 算法
【AI系统】内存分配算法
本文探讨了AI编译器前端优化中的内存分配问题,涵盖模型与硬件内存的发展、内存划分及其优化算法。文章首先分析了神经网络模型对NPU内存需求的增长趋势,随后详细介绍了静态与动态内存的概念及其实现方式,最后重点讨论了几种节省内存的算法,如空间换内存、计算换内存、模型压缩和内存复用等,旨在提高内存使用效率,减少碎片化,提升模型训练和推理的性能。
51 1
|
2月前
|
监控 Java Android开发
深入探讨Android系统的内存管理机制
本文将深入分析Android系统的内存管理机制,包括其内存分配、回收策略以及常见的内存泄漏问题。通过对这些方面的详细讨论,读者可以更好地理解Android系统如何高效地管理内存资源,从而提高应用程序的性能和稳定性。
81 16
|
2月前
|
并行计算 算法 测试技术
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面
C语言因高效灵活被广泛应用于软件开发。本文探讨了优化C语言程序性能的策略,涵盖算法优化、代码结构优化、内存管理优化、编译器优化、数据结构优化、并行计算优化及性能测试与分析七个方面,旨在通过综合策略提升程序性能,满足实际需求。
65 1
|
2月前
|
JavaScript
如何使用内存快照分析工具来分析Node.js应用的内存问题?
需要注意的是,不同的内存快照分析工具可能具有不同的功能和操作方式,在使用时需要根据具体工具的说明和特点进行灵活运用。
50 3
|
2月前
|
Linux
如何在 Linux 系统中查看进程占用的内存?
如何在 Linux 系统中查看进程占用的内存?
|
2月前
|
开发框架 监控 .NET
【Azure App Service】部署在App Service上的.NET应用内存消耗不能超过2GB的情况分析
x64 dotnet runtime is not installed on the app service by default. Since we had the app service running in x64, it was proxying the request to a 32 bit dotnet process which was throwing an OutOfMemoryException with requests >100MB. It worked on the IaaS servers because we had the x64 runtime install
|
2月前
|
Android开发 开发者
Android性能优化——内存管理的艺术
Android性能优化——内存管理的艺术