ImageVerifierCode 换一换
格式:DOCX , 页数:36 ,大小:256.52KB ,
资源ID:6686201      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/6686201.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(ION内存管理.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

ION内存管理.docx

1、ION内存管理1.android之ION内存管理器(1)- 简介为什么需要ION回顾2011年末2,LWN审查了android kernel patch3,以期望将这些patch合并到kernel主线中。但是PMEM(android实现的 一个内存分配器)使这个愿望破灭了。为什么PMEM不被linux 社区接受的原因在3中有讲到。从那开始,PMEM很明确会被完全抛弃,取而代之的是ION内存管理器。ION是google在Android4.0 ICS为了解决内存碎片管理而引入的通用内存管理器,它会更加融合kernel。目前QCOM MSM, NVDIA Tegra, TI OMAP, MRVL P

2、XA都用ION替换PMEM。如何获取source codeION codes reside in drivers/gpu/ionSpecific usage examples on omap4:ION 框架1ION 定义了四种不同的heap,实现不同的内存分配策略。 ION_HEAP_TYPE_SYSTEM : 通过vmalloc分配内存 ION_HEAP_TYPE_SYSTEM_CONTIG: 通过kmalloc分配内存 ION_HEAP_TYPE_CARVEOUT: 在保留内存块中(reserve memory)分配内存 ION_HEAP_TYPE_CUSTOM: 由客户自己定义下图是两个

3、client共享内存的示意图。图中有2个heap(每种heap都有自己的内存分配策略),每个heap中分配了若干个buffer。client的handle管理到对应的buffer。两个client是通过文件描述符fd来实现内存共享的。ION APIs用户空间 API定义了6种 ioctl 接口,可以与用户应用程序交互。 ION_IOC_ALLOC: 分配内存 ION_IOC_FREE: 释放内存 ION_IOC_MAP: 获取文件描述符进行mmap (? 在code中未使用这个定义) ION_IOC_SHARE: 创建文件描述符来实现共享内存 ION_IOC_IMPORT: 获取文件描述符 I

4、ON_IOC_CUSTOM: 调用用户自定义的ioctlION_IOC_SHARE 及ION_IOC_IMPORT是基于DMABUF实现的,所以当共享进程获取文件描述符后,可以直接调用mmap来操作共享内存。mmap实现由DMABUF子系统调用ION子系统中mmap回调函数完成。内核空间 API内核驱动也可以注册为一个ION的客户端(client),可以选择使用哪种类型的heap来申请内存。 ion_client_create: 分配一个客户端。 ion_client_destroy: 释放一个客户端及绑定在它上面的所有ion handle.ion handle: 这里每个ion handle

5、映射到一个buffer中,每个buffer关联一个heap。也就是说一个客户端可以操作多块buffer。Buffer 申请及释放函数: ion_alloc: 申请ion内存,返回ion handle ion_free: 释放ion handleION 通过handle来管理buffer,驱动需要可以访问到buffer的地址。ION通过下面的函数来达到这个目的 ion_phys: 返回buffer的物理地址(address)及大小(size) ion_map_kernel: 给指定的buffer创建内核内存映射 ion_unmap_kernel: 销毁指定buffer的内核内存映射 ion_ma

6、p_dma: 为指定buffer创建dma 映射,返回sglist(scatter/gather list) ion_unmap_dma: 销毁指定buffer的dma映射ION是通过handle而非buffer地址来实现驱动间共享内存,用户空间共享内存也是利用同样原理。 ion_share: given a handle, obtain a buffer to pass to other clients ion_import: given an buffer in another client, import it ion_import_fd: given an fd obtained vi

7、a ION_IOC_SHARE ioctl, import itHeap APIHeap 接口定义 drivers/gpu/ion/ion_priv.h这些接口不是暴露给驱动或者用户应用程序的。/* * struct ion_heap_ops - ops to operate on a given heap * allocate: allocate memory * free: free memory * phys get physical address of a buffer (only define on physically contiguous heaps) * map_dma ma

8、p the memory for dma to a scatterlist * unmap_dma unmap the memory for dma * map_kernel map memory to the kernel * unmap_kernel unmap memory to the kernel * map_user map memory to userspace */struct ion_heap_ops int (*allocate) (struct ion_heap *heap, struct ion_buffer *buffer, unsigned long len,uns

9、igned long align, unsigned long flags); void (*free) (struct ion_buffer *buffer); int (*phys) (struct ion_heap *heap, struct ion_buffer *buffer, ion_phys_addr_t *addr, size_t *len); struct scatterlist *(*map_dma) (struct ion_heap *heap, struct ion_buffer *buffer); void (*unmap_dma) (struct ion_heap

10、*heap, struct ion_buffer *buffer); void * (*map_kernel) (struct ion_heap *heap, struct ion_buffer *buffer); void (*unmap_kernel) (struct ion_heap *heap, struct ion_buffer *buffer); int (*map_user) (struct ion_heap *mapper, struct ion_buffer *buffer, struct vm_area_struct *vma);ION debugION 在/sys/ker

11、nel/debug/ion/ 提供一个debugfs 接口。每个heap都有自己的debugfs目录,client内存使用状况显示在/sys/kernel/debug/ion/$cat /sys/kernel/debug/ion/ion-heap-1 client pid size test_ion 2890 16384每个由pid标识的client也有一个debugfs目录/sys/kernel/debug/ion/$cat /sys/kernel/debug/ion/2890 heap_name: size_in_bytes ion-heap-1: 40960 11参考文献1.https:

12、/wiki.linaro.org/BenjaminGaignard/ion2.3.2. android之ION内存管理器(2)- cacheION如何实现buffer共享的思路倒是很清晰的,但是深入代码研究,发现ION是依赖于DMA Mapping的,而DMA mapping模块对我而言还是挺复杂的,看这个模块遇到的第一个问题就是cache。既然是DMA mapping,直接将申请的buffer设置为non-cacheable不就行了?这样就可以保证CPU通过DMA读写缓冲区的一致性了。为什么还有Consistent DMA mappings 和 Streaming DMA mappings一

13、说呢?下面先介绍一下Cache的概念。CacheCache写机制:Write-through与Write-back5Cache写机制分为write through和write back两种。 Write-through- Write is done synchronously both to the cache and to the backing store. Write-back(orWrite-behind) Writing is done only to the cache. A modified cache block is written back to the store, ju

14、st before it is replaced.Write-through(直写模式)在数据更新时,同时写入缓存Cache和后端存储。此模式的优点是操作简单;缺点是因为数据修改需要同时写入存储,数据写入速度较慢。Write-back(回写模式)在数据更新时只写入缓存Cache。只在数据被替换出缓存时,被修改的缓存数据才会被写到后端存储。此模式的优点是数据写入速度快,因为不需要写存储;缺点是一旦更新后的数据未被写入存储时出现系统掉电的情况,数据将无法找回。Write-misses写缺失的处理方式对于写操作,存在写入缓存缺失数据的情况,这时有两种处理方式: Write allocate(akaF

15、etch on write) Datum at the missed-write location is loaded to cache, followed by a write-hit operation. In this approach, write misses are similar to read-misses. No-write allocate(akaWrite-no-allocate,Write around) Datum at the missed-write location is not loaded to cache, and is written directly

16、to the backing store. In this approach, actually only system reads are being cached.Write allocate方式将写入位置读入缓存,然后采用write-hit(缓存命中写入)操作。写缺失操作与读缺失操作类似。No-write allocate方式并不将写入位置读入缓存,而是直接将数据写入存储。这种方式下,只有读操作会被缓存。无论是Write-through还是Write-back都可以使用写缺失的两种方式之一。只是通常Write-back采用Write allocate方式,而Write-through采用

17、No-write allocate方式;因为多次写入同一缓存时,Write allocate配合Write-back可以提升性能;而对于Write-through则没有帮助。Cache的两个函数 -Flush 把Cache内容写回Memory,当Cache为Write through,不需要Flush -Invalidate 把Cache内容直接丢掉不要。Cache的使用场合 当有DMA在使用memory的时候,一般要用到cache的处理。因为DMA在访问memory时是不经过cache的。比较典型的比如在Ethernet,wireless,USB等driver里,DMA会操作descript

18、ors和packet buffers,Driver要做这些处理 -如果driver使用descripter和packet buffer的地址都是cache的地址,那么 a).Driver在读descripter里一些状态,有没有收到包时,要对descripter当前结构里的内容做cache invalidate,收到packet后,也要对packet buffer做cache invalidate b).Driver在写descripter里一些状态,要发送包时,要对descripter当前结构里的内容做cache flush,发送packet时,也要对packet buffer做cache

19、flush -有些driver会对descripter使用uncache 地址,那么上面两种情况里invalidate/flush就不用做了。一般很少会对packet buffer也用uncache地址的,因为对packet内容的处理将会很频繁,使用uncache会很慢。而descripter一般由于结构比较小,如果也使用cache地址的话,做invalidate/flush的时间消耗可能会比uncache的还要多。下面文字采自于6C B 位的具体含义0 0 无cache,无写缓冲(strongly-ordered);任何对memory的读写都反映到总线上。对 memory 的操作过程中CPU

20、需要等待。0 1 无cache,有写缓冲(shareable device);读操作直接反映到总线上;写操作,CPU将数据写入到写缓冲后继续运行,由写缓冲进行写回操作。1 0 有cache,写通模式(write-through);读操作首先考虑cache hit;写操作时直接将数据写入写缓冲,如果同时出现cache hit,那么也更新cache。1 1 有cache,写回模式(write-back);读操作首先考虑cache hit;写操作也首先考虑cache hit。处理流程图Write-through模式处理流程:A Write-Through cache with No-Write Al

21、locationWrite-back模式处理流程:参考文献1.https:/wiki.linaro.org/BenjaminGaignard/ion2.3.4. linux设备驱动程序第三版 JONATHAN CORBET5.6. ARM Architecture Reference Manual, ARMv7-A and ARMv7-R edition DDI0406C3.linux之DMA API - 通用设备的动态DMA映射文描述DMA API。更详细的介绍请参看Documentation/DMA-API-HOWTO.txt。API分为两部分,第一部分描述API,第二部分描述可以支持非一

22、致性内存机器的扩展API。你应该使用第一部分所描述的API,除非你知道你的驱动必须要支持非一致性平台。第一部分 DMA API为了可以引用DMA API,你必须 #include 1-1 使用大块DMA一致性缓冲区(dma-coherent buffers)void *dma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)一致性内存:设备对一块内存进行写操作,处理器可以立即进行读操作,而无需担心处理器高速缓存(cache)的影响。同样的,处理器对一块内存进行些操作,设备可以立

23、即进行读操作。(在告诉设备读内存时,你可能需要确定刷新处理器的写缓存。)此函数申请一段大小为size字节的一致性内存,返回两个参数。一个是dma_handle,它可以用作这段内存的物理地址。 另一个是指向被分配内存的指针(处理器的虚拟地址)。注意:由于在某些平台上,使用一致性内存代价很高,比如最小的分配长度为一个页。因此你应该尽可能合并申请一致性内存的请求。最简单的办法是使用dma_pool函数调用(详见下文)。参数flag(仅存在于dma_alloc_coherent中)运行调用者定义申请内存时的GFP_flags(详见kmalloc)。void *dma_zalloc_coherent(s

24、truct device *dev, size_t size, dma_addr_t *dma_handle, gfp_t flag)对dma_alloc_coherent()的封装,如果内存分配成功,则返回清零的内存。voiddma_free_coherent(struct device *dev, size_t size, void *cpu_addr, dma_addr_t dma_handle)释放之前申请的一致性内存。dev, size及dma_handle必须和申请一致性内存的函数参数相同。cpu_addr必须为申请一致性内存函数的返回虚拟地址。注意:和其他内存分配函数不同,这些函

25、数必须要在中断使能的情况下使用。1-2 使用小块DMA一致性缓冲区如果要使用这部分DMA API,必须#include 。许多驱动程序需要为DMA描述符或者I/O内存申请大量小块DMA一致性内存。你可以使用DMA 内存池,而不是申请以页为单位的内存块或者调用dma_alloc_coherent()。这种机制有点像struct kmem_cache,只是它利用了DMA一致性内存分配器,而不是调用 _get_free_pages()。同样地,DMA 内存池知道通用硬件的对齐限制,比如队列头需要N字节对齐。struct dma_pool *dma_pool_create(const char *na

26、me, struct device *dev, size_t size, size_t align, size_t alloc);create( )函数为设备初始化DMA一致性内存的内存池。它必须要在可睡眠上下文调用。name为内存池的名字(就像struct kmem_cache name一样)。dev及size就如dma_alloc_coherent()参数一样。align为设备硬件需要的对齐大小(单位为字节,必须为2的幂次方)。如果设备没有边界限制,可以设置该参数为0。如果设置为4096,则表示从内存池分配的内存不能超过4K字节的边界。void *dma_pool_alloc(struct

27、 dma_pool *pool, gfp_t gfp_flags, dma_addr_t *dma_handle);从内存池中分配内存。返回的内存同时满足申请的大小及对齐要求。设置GFP_ATOMIC可以确保内存分配被block,设置GFP_KERNEL(不能再中断上下文,不会保持SMP锁)允许内存分配被block。和dma_alloc_coherent()一样,这个函数会返回两个值:一个值是cpu可以使用的虚拟地址,另一个值是内存池设备可以使用的dma物理地址。voiddma_pool_free(struct dma_pool *pool, void *vaddr, dma_addr_t a

28、ddr);返回内存给内存池。参数pool为传递给dma_pool_alloc()的pool,参数vaddr及addr为dma_pool_alloc()的返回值。voiddma_pool_destroy(struct dma_pool *pool);内存池析构函数用于释放内存池的资源。这个函数在可睡眠上下文调用。请确认在调用此函数时,所有从该内存池申请的内存必须都要归还给内存池。1-3 DMA寻址限制intdma_supported(struct device *dev, u64 mask)用来检测该设备是否支持掩码所表示的DMA寻址能力。比如mask为0x0FFFFFF,则检测该设备是否支持2

29、4位寻址。返回1表示支持,0表示不支持。注意:该函数很少用于检测是否掩码为可用的,它不会改变当前掩码设置。它是一个内部API而非供驱动者使用的外部API。intdma_set_mask(struct device *dev, u64 mask)检测该掩码是否合法,如果合法,则更新设备参数。即更新设备的寻址能力。返回0表示成功,返回负值表示失败。intdma_set_coherent_mask(struct device *dev, u64 mask)检测该掩码是否合法,如果合法,则更新设备参数。即更新设备的寻址能力。返回0表示成功,返回负值表示失败。u64dma_get_required_ma

30、sk(struct device *dev)该函数返回平台可以高效工作的掩码。通常这意味着返回掩码是可以寻址到所有内存的最小值。检查该值可以让DMA描述符的大小尽量的小。请求平台需要的掩码并不会改变当前掩码。如果你想利用这点,可以利用改返回值通过dma_set_mask()设置当前掩码。1-4 流式DMA映射dma_addr_tdma_map_single(struct device *dev, void *cpu_addr, size_t size, enum dma_data_direction direction)映射一块处理器的虚拟地址,这样可以让外设访问。该函数返回内存的物理地址。在dma_API中强烈建议使用表示D

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1