本文将从如下几个方面介绍Contiguous Memory Allocator(CMA)的相关内容:

  1. CMA是什么?
  2. CMA是如何工作的?
  3. CMA vs IOMMU

对于细节问题,可以参考文末的资料。

1. CMA是什么?

CMA的全称是Contiguous Memory Allocator。顾名思义,CMA是分配连续物理内存的一种机制。

CMA的应用场景是DMA(Direct Memory Access)。在DMA中,我们需要分配连续的物理内存。有一种方法是在系统启动前预留一部分连续物理内存,分配给DMA使用。但是,这个问题在于,对于预留的内存,伙伴系统是无法使用的,当预留内存空闲时,就会造成内存资源的浪费。

2. CMA是如何工作的?

首先介绍下背景知识:

When requesting memory from the buddy allocator, one provides a gfp_mask. Among other things, it specifies the “migrate type” of the requested page(s). One of the migrate types is MIGRATE_MOVABLE. The idea behind it is that data from a movable page can be migrated (or moved, hence the name), which works well for disk caches, process pages, etc.

To keep pages with the same migrate type together, the buddy allocator groups pages into “pageblocks,” each having a migrate type assigned to it. The allocator then tries to allocate pages from pageblocks with a type corresponding to the request. If that’s not possible, however, it will take pages from different pageblocks and may even change a pageblock’s migrate type. This means that a non-movable page can be allocated from a MIGRATE_MOVABLE pageblock which can also result in that pageblock changing its migrate type. This is undesirable for CMA, so it introduces a MIGRATE_CMA type which has one important property: only movable pages can be allocated from a MIGRATE_CMA pageblock.

So, at boot time, when the dma_contiguous_reserve() and/or dma_declare_contiguous() functions are called, CMA talks to memblock to reserve a portion of RAM, just to give it back to the buddy system later on with the underlying pageblock’s migrate type set to MIGRATE_CMA. The end result is that all the reserved pages end up back in the buddy allocator, so they can be used to satisfy movable page allocations.

总结一下:启动时,我们将一部分连续物理内存标记为MIGRATE_CMA,然后归还给伙伴系统。当DMA没有使用时,我们可以将这部分内存分配给movable page ,例如page cache。当DMA需要使用连续内存时,我们会将movable page迁移,然后让DMA使用这段连续的物理内存。

3. CMA vs IOMMU

CMA使用软件的方式为DMA分配连续的物理内存。IOMMU利用硬件提供的功能,使用DMA时,无需连续的物理内存。

若想深入研究,就需要去啃内核源码了。


参考资料:

  1. A deep dive into CMA
  2. Linux Contiguous Memory Allocator
  3. CMA模块学习笔记