A reworked contiguous memory allocator
http://lwn.net/Articles/447405/
June 14, 2011
分配大块物理上连续内存的问题一直在被讨论。虚拟内存,天生的在系统上分散使用内存页,内核运行一会儿就只剩下很少的连续空闲的页。多年以来,内核开发者处理这个问题的方法是尽量避免对大的连续物理页分配的依赖。只有相当少的内核代码会尝试分配多于两个物理连续页。
最近,对大的连续页分配的需求持续增长。一个是大页和THP,另一个是有新麻烦的旧事:不能执行分散/聚集DMA操作的硬件。任何只能对物理连续区域做DMA的设备(没有IOMMU)需要一个物理连续的缓存。这种需求一般出现在相对来说比较低端的硬件,有人可能希望这种硬件会随着时间流逝越来越少。但我们现在看到的却是在获得能力提升的同时仍有连续DMA缓存需求的设备。举个例子,能获取全高清数据的视频捕捉引擎能执行很多转换,但它仍需要一个连续的缓存来保存结果。高清视频的出现加重了这个问题--这些物理连续的缓存比以前更大也更难分配了。
大约一年以前,LWN发表过想要解决这个问题的CMA(contiguous memory allocator)补丁。这个补丁仍然遵循了传统的为满足大的分配请求的特殊目的而在启动的时候保留一部分内存的方法。几年以前,这种技术就已经被用在“bigphysarea”补丁中了,它简单的传给内核“mem=”启动参数来保留一部分物理内存不被使用。安卓的pmem驱动也是从一个保留的区域里分配内存。近20年的经验证明这种方法是可行的。不足是保留的内存就不能再被其他地方使用了;如果设备没有使用这部分内存,它就保持闲置。这种浪费越来越不被内核开发者,还有用户所欢迎。
因为这个和其他的原因,CMA补丁未被合并。但是问题尚未解决,而现在也没人继续研究这两种方法。CMA补丁的最新版看起来有点不同,尽管还有一些问题需要解决,这个补丁还是有更大的机会合入主线的。
CMA分配器仍然可以工作在一个保留的内存区域,但很明显这不是大家想要的操作模式。作为代替,新的CMA尝试维护内存区域,当有需求的时候连续的内存就会被创建。为实现这个目的,CMA依赖于内存管理代码中的“迁移类型”机制。
每一个区里,页块中的页被标记为(或非)可移动的或可重声明的。可移动页一般是指页缓存或匿名页,它们通过页表和页缓存基树来被访问。只要页表和基树做相应的改动,这些页的内容就可以被移到其他地方。可重声明页是指可能会按要求返回给内核的页,它们保存数据结构比如inode缓存。不可移动页一般是内核直接指向的页,比如,通过kmalloc()获得的内存就不能在不破坏数据的情况下被移动。
内存管理子系统会尽量把可移动页放在一起。(因为)如果想通过移动页来释放大块内存,只需要一个不可移动的页就可以摧毁所有的努力。通过把可移动页聚在一起,内核希望能按要求释放大块区域从而避免了这种问题。内存压缩代码依赖这些可移动页区域来工作。
CMA通过增加一个新的“CMA”的迁移类型来扩展这种机制,它就像“movable”类型,但有两点不同。“CMA”类型是粘贴的,被标记为CMA的页就不会再被内核改变了。内存分配器不再从CMA区域分配不可移动页,并且只有在其它方法不可用的情况下才会为其他使用来分配CMA页。所以,被标记为用作CMA的内存区域只包含可移动页,并且有相对较多的空闲页。
换句话说,被标记用作CMA的内存仍然可以被系统的其他部分使用,但有个限制是它只能包含可移动页。当一个驱动需要连续的内存时,CMA分配器会尝试从其中一个内存区域中分配足够的页来创建适当大小的连续缓存。如果那些内存区域的页是可移动的(现实中有时不会满足),驱动就会获得它需要的缓存。但这个缓存不需要时,内存可以被用作其他目的。
有人可能会疑惑为何需要这种机制,内存压缩已经可以为THP创建大块物理连续的内存了。答案是DMA缓存有一些跟大页不同的需求。它们可能更大,举个例子,大多数架构上THP是2MB,而DMA缓存能达到10MB或更多。也有可能存在只能映射DMA缓存到特定内存范围的奇葩硬件--CMA的开发者Marek Szyprowski貌似就这有中硬件。最后,一个2MB的大页必须2MB对齐,而DMA缓存的对齐要求则更宽松一些。CMA分配器可以获得正好是需要的数量的内存(不用像伙伴分配器那样扩展到下一个2的幂的大小)而不用担心过度严格的对齐要求。
CMA补丁提供了一些函数以方便创建内存区域和为特定范围的内存建立“内容/上下文”。然后有cm_alloc()和cm_free()来获取和释放缓存。但是,设备驱动最好不要直接调用CMA,而是把感知CMA集成到DMA函数里。当一个驱动调用比如dma_alloc_coherent()函数,CMA会被自动使用来满足要求。大多数情况下,这是就可以满足需求了。
剩余的关于CMA的疑问中的一个是关于如何在第一时间创建特殊区域。当前的方案是希望在系统的板文件(board file:系统相关的设置)中加入一些特殊的调用,这很像ARM的做事方法。社区的目的是不再使用板文件,所以得找其它方法。就像Arnd Bergmann指出的,把这些信息移到设备树也不是一个选项;这其实就是一个机制的问题。Arnd正在推动可以在大多数系统上设置一些合理的默认设置的方法,特殊挑战的奇葩系统的修复可以随后加上。
最终的结果是这个补丁进入主线之前起码还得再有一轮迭代。但是CMA满足了一个真实的需求。这些代码有潜力使物理连续内存分配更加可靠,同时最小化对系统其它部分的影响。看起来值得拥有。
(转载本站文章请注明作者和出处 http://www.cnblogs.com/baiyw/,请勿用于任何商业用途)