0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

Linux内核大块内存申请:从场景到落地全解析

jf_44130326 来源:Linux1024 2026-02-09 16:41 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

一、为什么需要大块内核内存

先明确场景,避免盲目选择分配方式:

1.DMA传输场景:网卡、硬盘等外设的DMA控制器,要求内存物理地址连续(无法识别虚拟地址映射),且需一次性分配大尺寸缓冲区(如1GB网络帧缓存)。

2.大型内核缓存:文件系统(如EXT4)的索引缓存、数据库内核的内存池,需要持续占用GB级内存,且需虚拟地址连续(方便指针遍历)。

3.虚拟化场景KVM虚拟机的内存分配、容器运行时的共享内存,需为Guest OS分配大块连续内存,保障运行性能。

4.高性能设备驱动FPGAGPU等加速卡的驱动程序,需分配大块内存用于数据批量传输,减少IO次数。

二、3种核心申请方法(附实操代码)

Linux内核提供3种大块内存分配接口,核心差异在于物理连续与否性能开销,需按需选择:

1. alloc_pages ():物理连续,DMA首选

核心特点:分配2^order页的物理连续内存,返回struct page指针(需手动转换为虚拟地址),适合DMA、高性能IO等场景。

关键参数

gfp_mask:分配标志(如GFP_KERNEL允许睡眠,GFP_ATOMIC不睡眠);

order:分配阶数(order=0→1页,order=1→2页,order=10→1GB,最大order由内核配置MAX_ORDER决定,默认11→2GB)。

示例代码

#include#include// 分配1GB物理连续内存(order=10,假设PAGE_SIZE=4KB)structpage*page =alloc_pages(GFP_KERNEL | __GFP_ZERO,10);if(!page) { pr_err("alloc_pages failedn"); return-ENOMEM;}// 转换为虚拟地址(内核虚拟地址=物理地址+PAGE_OFFSET)void*virt_addr =page_address(page);// 释放内存(必须与alloc_pages配对)__free_pages(page,10);

2. __get_free_pages ()alloc_pages封装,简化使用

核心特点alloc_pages的封装接口,直接返回虚拟地址(无需手动转换struct page),功能与alloc_pages完全一致,物理连续。

示例代码

// 分配512MB物理连续内存(order=9,4KB*512=2GB?不:order=9→512页=2GB?哦,4KB*512=2MB?纠正:4KB*2^9=4KB*512=2048KB=2MB;order=19才是2GB,需注意order计算)void*virt_addr = (void*)__get_free_pages(GFP_KERNEL | __GFP_ZERO,9);if(!virt_addr) { pr_err("__get_free_pages failedn"); return-ENOMEM;}// 释放内存(与free_pages配对)free_pages((unsignedlong)virt_addr,9);

注意:__get_free_pages是宏定义,本质调用alloc_pages,仅简化地址转换。

3. vmalloc ():虚拟连续,物理离散

核心特点:分配虚拟地址连续、物理地址离散的大块内存,通过内核页表映射实现,适合对物理连续性无要求、但需大尺寸内存的场景(如内核缓存、低访问频率缓冲区)。

优势:支持更大尺寸(理论无上限,受内核虚拟地址空间限制),分配成功率高于物理连续方式。

劣势:访问需经过页表转换,性能比alloc_pages低(延迟高~20%),且不支持DMA

示例代码

#include// 分配2GB虚拟连续内存void*virt_addr =vmalloc(2*1024*1024*1024);if(!virt_addr) { pr_err("vmalloc failedn"); return-ENOMEM;}// 可选:初始化内存(vmalloc不默认清零)memset(virt_addr,0,2*1024*1024*1024);// 释放内存(必须用vfree,不能用kfree)vfree(virt_addr);

三、关键注意事项(避坑核心)

1.物理连续内存稀缺性

order越大,分配成功率越低(系统运行越久,物理内存越碎片化),建议尽量降低order(如拆分大内存为多个小order分配)。

避免在中断上下文申请物理连续大块内存(GFP_ATOMIC不允许睡眠,无法等待内存碎片整理)。

1.申请失败必须处理

大块内存分配失败是常态(尤其物理连续方式),需返回错误码或降级处理(如改用vmalloc),不可直接使用NULL指针。

1.释放接口必须配对

申请接口

释放接口

错误用法

alloc_pages()

__free_pages()

vfree ()释放

__get_free_pages()

free_pages()

kfree ()释放

vmalloc()

vfree()

free_pages ()释放

1.性能与场景匹配

高频访问的大块内存(如DMA传输)用alloc_pages(物理连续,无页表转换开销);

低频访问的大内存(如内核日志缓存)用vmalloc(分配成功率高,不浪费物理连续内存)。

1.NUMA架构优化

CPU节点服务器中,用alloc_pages_node(nid, gfp_mask, order)指定节点分配,避免跨节点访问(跨节点延迟是本地的2-3倍)。

1.内存泄漏风险

内核内存无GC机制,申请后必须在模块卸载、设备注销时释放,建议用devres机制(如devm_alloc_pages)自动释放,减少泄漏风险。

四、申请流程可视化(流程图)

wKgZO2kah4mAQRx5AAIA-CcgP7U613.png

五、知识脑图(快速梳理)

wKgZO2kah4mAWfauAAFo4smqTtc557.jpg  
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 内核
    +关注

    关注

    4

    文章

    1479

    浏览量

    43140
  • Linux
    +关注

    关注

    88

    文章

    11854

    浏览量

    219820
  • 内存
    +关注

    关注

    9

    文章

    3255

    浏览量

    76590
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    Linux内核内存泄漏怎么办

    Linux内核开发中,Kmemleak是一种用于检测内核内存泄漏的工具。
    发表于 07-04 11:04 1361次阅读

    Linux内存相关知识科普

    Linux 内核几种内存管理的方法,内存使用场景以及内存使用的那些坑。**
    发表于 07-25 14:43 1234次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内存</b>相关知识科普

    Linux内核内存规整总结

    分配需求,如下图所示: 内存外部碎片导致实际占用物理页不多,但是已无法申请>=4个页连续内存,理想当中我们希望内存没有外部碎片,如下图所示: 内核
    的头像 发表于 11-11 11:17 2542次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>内存</b>规整总结

    Linux内核内存管理架构解析

    内存管理子系统可能是linux内核中最为复杂的一个子系统,其支持的功能需求众多,如页面映射、页面分配、页面回收、页面交换、冷热页面、紧急页面、页面碎片管理、页面缓存、页面统计等,而且对性能也有很高
    的头像 发表于 01-04 09:24 2166次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b><b class='flag-5'>内存</b>管理架构<b class='flag-5'>解析</b>

    Linux内核地址映射模型与Linux内核高端内存详解

    Linux 操作系统和驱动程序运行在内核空间,应用程序运行在用户空间,两者不能简单地使用指针传递数据,因为Linux使用的虚拟内存机制,用户空间的数据可能被换出,当
    发表于 05-08 10:33 3878次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>地址映射模型与<b class='flag-5'>Linux</b><b class='flag-5'>内核</b>高端<b class='flag-5'>内存</b>详解

    流程场景落地 在线测长仪多方位部署 满足各种检测需求

    在钢厂,不同的位置都有长度的检测需求,如剪切位置、钢坯位置、成品位置等,在不同的位置部署在线测长仪,保证测量精度,提升产品品质。 流程场景落地:这些环节“吃劲”,管控效果明显 在线测长仪在钢铁生产
    发表于 11-04 14:23

    Linux内存系统: Linux 内存分配算法

    的大小· 它们的物理地址是连续的· 页块大小相同4、如何分配 4M 以上内存?1) 为何限制大块内存分配· 分配的内存越大, 失败的可能性越大·
    发表于 08-24 07:44

    Linux内存系统:内存使用场景

    指向的内容 copy q,返回 q。并将 p 所指向的内存空间删除3、内核内存分配函数函数分配原理最大内存其他_get_free_p
    发表于 08-25 07:42

    Linux内核的相关资料推荐

    Linux内核主要学习内容可以分为三大块:进程、内存及协议栈。今天就说说内存泄露的问题。相信你在平时的工作中,应该遇到过下面这些
    发表于 01-14 08:55

    LINUX内核中的内存是如何进行分配的

    必须申请大块内存时才使用,例如动态插入模块时。7、内存分配标志1、GFP_KERNEL:表示该次内存 分配由
    发表于 11-04 14:46

    一文解析Linux内存系统

    Linux 内存是后台开发人员,需要深入了解的计算机资源。合理的使用内存,有助于提升机器的性能和稳定性。本文主要介绍Linux 内存组织结构
    的头像 发表于 09-01 10:46 3227次阅读
    一文<b class='flag-5'>解析</b><b class='flag-5'>Linux</b><b class='flag-5'>内存</b>系统

    Linux内核中用GFP_ATOMIC申请内存意味着什么

    本文目的 本文补充校正一些Linux内核开发者关于GFP_ATOMIC的认知不完整的地方,阐述GFP_ATOMIC与free内存watermark的关系,并明确什么时候应该用GFP_ATOMIC
    的头像 发表于 01-04 13:43 4111次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>中用GFP_ATOMIC<b class='flag-5'>申请</b><b class='flag-5'>内存</b>意味着什么

    Linux内核源码分析-进程的哪些内存类型容易引起内存泄漏?

    Linux内核主要学习内容可以分为三大块:进程、内存及协议栈。今天就说说内存泄露的问题。相信你在平时的工作中,应该遇到过下面这些
    发表于 01-14 13:02 6次下载
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>源码分析-进程的哪些<b class='flag-5'>内存</b>类型容易引起<b class='flag-5'>内存</b>泄漏?

    Linux内核伙伴系统内存申请函数详解:原理到实战

    Linux 内核中,内存管理是整个系统稳定运行的基石,而伙伴系统(Buddy System) 作为内核物理内存分配的核心机制,更是驱动开
    的头像 发表于 02-10 16:58 3771次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>伙伴系统<b class='flag-5'>内存</b><b class='flag-5'>申请</b>函数详解:<b class='flag-5'>从</b>原理到实战

    Linux内核三大核心模块深度解析:调度、内存与I/O

    Linux内核作为操作系统的核心,其进程调度、内存管理和文件I/O三大模块共同决定了系统的性能与稳定性。无论是多核服务器的高并发处理,还是嵌入式设备的资源受限场景,深入理解这些底层机制
    的头像 发表于 03-12 09:00 327次阅读
    <b class='flag-5'>Linux</b><b class='flag-5'>内核</b>三大核心模块深度<b class='flag-5'>解析</b>:调度、<b class='flag-5'>内存</b>与I/O