页面迁移从CMA(连续内存分配器)区域失败

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了页面迁移从CMA(连续内存分配器)区域失败相关的知识,希望对你有一定的参考价值。

我面临着CMA的问题。我正在尝试通过CMA(连续内存分配)为运行linux 3.8内核的基于ARM的目标板分配设备内存。

在通过私有cma节点请求内存分配时,它会产生“NO memin CMA area”。尽管我们保留了所需的内存。在调试“_alloc_contig_migrate_range”函数时,我们发现某些页面的迁移失败并导致CMA区域中没有mem。

正在迁移满足“migrate_page_move_mapping(migrate.c)”功能中的以下条件的页面。

   if (!mapping) {
            /* Anonymous page without mapping */
             if (page_count(page) != 1) {
                         return -EAGAIN;
             }
             return MIGRATEPAGE_SUCCESS;
   }

其他页面失败并从migrate_page_move_mapping()返回

    if (page_count(page) != expected_count ||

                radix_tree_deref_slot_protected(pslot, &mapping->tree_lock) != page) {

                        spin_unlock_irq(&mapping->tree_lock);

        return -EAGAIN;

    }

而page_count(页) - > 3和预期计数 - > 2不匹配,因此重复返回-EAGAIN。

在查看页面标志时,我发现了标志中的差异。

迁移成功 - > 0xc3a40059

迁移失败 - > 0xc3a0000d

标志中的差异是

观察标志 - > PG_dirty PG_active PG_swapbacked PG_referenced

迁移成功----> SET SET SET NOTSET

迁移失败------> NOTSET NOTSET NOTSET SET

任何建议都会有所帮助。

答案

记录了为什么CMA迁移可能在早于3.18的内核上失败的几个原因 here(伙伴分配器会计错误)和here(不支持KSM迁移)。

与流行的看法相反,Linux内核中的Contiguous Memory Allocator框架 并不保证在整个系统生命周期内连续内存的可用性。

CMA的核心概念如下......

  1. 在引导时,允许将一定量的内存定义为连续缓冲池。
  2. 在运行时,允许从此连续缓冲池中为常规内存分配请求分配内存(作为最后的手段)。
  3. 每当请求大型连续缓冲区时, 一个。立即将上面步骤2中分配的页面迁移到常规内存池中。 湾为请求者提供一个大的连续缓冲区。

问题在于在某些情况下, 在步骤3a中迁移页面可能会失败。这可能是由于:

  • 缺少可用内存或交换作为目标来迁移已在CMA池中分配的非连续小页面。
  • 分配给他们的pin memory/buffers流程的能力。

由于在更新/替换CMA的单一方法上没有任何理由,它在大多数时间以其当前形式继续存在,但在所有可能的情况下都不能保证连续的存储。随着SMMU的出现和对其他控制器的分散 - 聚集DMA支持,对较大的连续缓冲区的需求较少。


也就是说,有两种主要方法可以改进CMA,这些方法已经尝试过并在某些圈子中被接受:

  1. GCMA
  2. ZONE CMA

基于他们认为可接受的妥协,这两种方法都有其自身的局限性。

以上是关于页面迁移从CMA(连续内存分配器)区域失败的主要内容,如果未能解决你的问题,请参考以下文章

Linux内存从0到1学习笔记(10.1 BugsShooter之cma配置过小导致页迁移繁忙而内存申请失败)

CMA连续物理内存用户空间映射---

Linux内存从0到1学习笔记(8.5,CMA内存分配)

如何在 Linux 中分配大的连续内存区域

如何减小内存碎片

09 管理内存对象