linux cma内存分析

0,cma内存

1,linux cma开关

内核宏开关(如CONFIG_CMA)是编译时配置选项,用于决定是否在内核中启用CMA功能。若未启用该宏,整个CMA子系统将不会被编译进内核,系统完全失去连续内存分配能力

cma=0是内核启动时传递的命令行参数,用于动态禁用CMA功能。此时内核已编译支持CMA,但通过参数强制关闭其运行时行为,例如不预留或释放已预留的CMA内存区域

2,常用CMA宏及其功能

  1. CONFIG_CMA

    • 功能:决定是否在内核中启用CMA功能。
    • 说明:若启用,内核将支持CMA子系统,包括连续内存的分配和释放;若禁用,CMA相关代码将不会被编译进内核,系统将无法使用CMA功能。
  2. CONFIG_CMA_AREAS

    • 功能:定义系统中CMA区域的数量。
    • 说明:通过该宏可以指定内核支持的CMA区域数量,每个区域可以独立配置大小和用途,适用于多设备场景。
  3. CONFIG_CMA_DEBUG

    • 功能:启用CMA的调试功能。
    • 说明:开启后,内核会输出CMA相关的调试信息,便于开发者分析和排查问题。
  4. CONFIG_DMA_CMA

    • 功能:启用CMA与DMA(Direct Memory Access)的集成支持。
    • 说明:该宏用于配置CMA是否支持DMA操作,常用于需要高效内存管理的设备驱动程序1。
  5. CONFIG_CMA_SIZE 定义具体大小(例如 CONFIG_CMA_SIZE_MBYTES=64 表示预留 64MB)

3,GFP_ATOMIC与GFP_KERNEL的功能与区别

(1)GFP_ATOMIC

  • 功能:GFP_ATOMIC是一种内存分配标志,用于在原子上下文中分配内存。它不会引起休眠,因此适用于中断处理程序或持有自旋锁的场景12。
  • 特点
    • 不允许休眠,分配失败时立即返回。
    • 通常用于分配小块内存,不适合分配大块连续内存。
  • 与CMA的关系:GFP_ATOMIC不直接涉及CMA,因为它主要用于非连续内存的分配,且分配过程不会调用CMA的页面迁移机制12。

(2) GFP_KERNEL

  • 功能:GFP_KERNEL是内核中最常用的内存分配标志,用于在进程上下文中分配内存。如果内存不足,它会触发休眠,直到有可用内存为止12。
  • 特点
    • 允许休眠,适用于非原子上下文。
    • 可以分配连续内存和不连续内存,具体取决于分配方式。
  • 与CMA的关系:当使用GFP_KERNEL分配连续内存时,可能会调用CMA机制。如果普通内存区域不足,CMA会通过迁移页面来满足分配需求5

4,GFP_ATOMIC和 GFP_KERNEL的源码实现

(1)GFP_ATOMIC分析

#define GFP_ATOMIC (__GFP_HIGH | __GFP_ATOMIC | __GFP_KSWAPD_RECLAIM)

  • __GFP_HIGH:高优先级分配;
  • __GFP_ATOMIC:不允许休眠;
  • __GFP_KSWAPD_RECLAIM:允许 kswapd 进行后台回收。

(2)使用场景

GFP_ATOMIC 主要用于:

  • 中断处理程序;
  • 持有自旋锁的代码;
  • 不允许阻塞的上下文。

(3) 分配路径

GFP_ATOMIC 调用 kmalloc()__get_free_pages(),最终进入 alloc_pages()

(4)GFP_KERNEL 的源码实现

#define GFP_KERNEL (__GFP_RECLAIM | __GFP_IO | __GFP_FS)

  • __GFP_RECLAIM:允许页面回收;
  • __GFP_IO:允许进行 I/O 操作;
  • __GFP_FS:允许进行文件系统操作。

(5) 使用场景

GFP_KERNEL 适用于:

  • 进程上下文;
  • 允许休眠和阻塞的代码。

(6) 分配路径

GFP_KERNEL 同样调用 alloc_pages(),但在 __alloc_pages() 中:

  • 如果空闲内存不足,会触发 __alloc_pages_slowpath()
  • __alloc_pages_slowpath() 中,会尝试:
    • 页面回收(shrink_zones());
    • 直接回收(__perform_reclaim());
    • 如果配置了 CMA,会尝试从 CMA 区域分配连续内存。

5,代码分析

  • include/linux/gfp.h:GFP 标志定义;
  • mm/page_alloc.c:页面分配核心逻辑;
  • mm/cma.c:CMA 分配实现;
  • mm/slab.c:slab 分配器(kmalloc)
  • 连续内存 :通过 __get_free_pages()kmalloc()dma_alloc_coherent() 等函数分配,物理地址连续,适用于 DMA 设备;
  • 非连续内存 :通过 vmalloc()ioremap() 等函数分配,物理地址不连续,虚拟地址连续,适用于大块内存;

内核申请源码分析

特性 GFP_ATOMIC GFP_KERNEL
是否允许休眠 ❌ 不允许 ✅ 允许
是否支持 CMA ❌ 不支持 ✅ 支持
适用场景 中断、自旋锁等原子上下文 进程上下文,允许阻塞
连续内存分配 ❌ 不支持 ✅ 支持(通过 CMA)
不连续内存分配 ✅ 支持(通过伙伴系统) ✅ 支持(通过伙伴系统
相关推荐
IT运维爱好者15 分钟前
【Linux】LVM理论介绍、实战操作
linux·磁盘扩容·lvm
LEEE@FPGA17 分钟前
ZYNQ MPSOC linux hello world
linux·运维·服务器
郝学胜-神的一滴19 分钟前
Linux定时器编程:深入理解setitimer函数
linux·服务器·开发语言·c++·程序人生
冉佳驹22 分钟前
Linux ——— 系统中的用户身份切换、文件权限管理、特殊权限和粘滞位设置
linux·chmod·chown·粘滞位·su 命令·chgrp·umask
Tranquil_ovo28 分钟前
【Linux】Makefile 基础
linux
漏洞文库-Web安全29 分钟前
Linux逆向学习记录
linux·运维·学习·安全·web安全·网络安全·逆向
无奈笑天下36 分钟前
【银河麒麟高级服务器部署本地yum源】
linux·运维·服务器·经验分享
dodod20121 小时前
Ubuntu 24.04 LTS 使用清华大学的 Ubuntu 镜像源以加速下载和更新操作
linux·运维·ubuntu
轻颂呀1 小时前
TCP协议
linux·网络·网络协议·tcp/ip
知识分享小能手1 小时前
CentOS Stream 9入门学习教程,从入门到精通,CentOS Stream 9 用户和组管理 —语法详解与实战案例(6)
linux·学习·centos