我面临着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和expected_count - > 2不匹配,因此会重复返回-EAGAIN。
在查看页面标记时,我发现了标记中的差异。
迁移成功 - > 0xc3a40059
迁移失败 - > 0xc3a0000d
旗帜中的差异是
观察标志 - > PG_dirty PG_active PG_swapbacked PG_referenced
迁移成功----> 组 组 组 NOTSET
迁移失败------> 没有设置 没有设置 没有设置 SET
任何建议都会有所帮助。
答案 0 :(得分:0)
有关CMA迁移可能在3.18之前的内核上失败的几个原因记录在案 here (伙伴分配器会计错误)和 here (KSM)不支持迁移)。
与流行的看法相反,Linux内核中的 Contiguous Memory Allocator 框架 并不保证在整个系统生命周期内连续内存的可用性。
CMA的核心概念如下......
每当请求大型连续缓冲区时,
一个。立即将上面 step2 中分配的页面迁移到常规内存池中。
湾为请求者提供一个大的连续缓冲区。
问题在于在某些情况下, 在步骤 3a 中迁移页面可能会失败。这可能是由于:
由于在更新/替换CMA的单一方法上没有任何理由,它在大多数情况下以其当前形式继续存在,但不能保证在所有可能情况下的连续存储器。随着SMMU的出现以及对其他控制器的分散 - 聚集DMA支持,对大型连续缓冲区的需求也越来越少。
也就是说,有两种主要方法可以改进CMA,这些方法已经尝试过并在某些圈子中被接受: