讲师中心 微信公众号
AI工具推荐 视频效率加速

Linux 内存分配与回收机制详解

小芳姑娘_9130

小芳姑娘_9130

发布时间:2026-01-29 19:13:03

|

191人浏览过

|

来源于php中文网

原创

从 Linux 5.13 开始,vmalloc() 默认尝试使用大页映射,但需满足空闲大页充足、地址对齐及分配大小足够(通常 ≥ 几十 KB)等条件;可通过启用 CONFIG_DEBUG_VM_VALLOC 查看 dmesg 日志或结合 /sys/kernel/debug/page_owner 分析页 order 确认,小内存系统慎用,启动参数 nohugevmalloc 可全局禁用。

linux 内存分配与回收机制详解

vmalloc() 用大页了吗?怎么确认?

从 Linux 5.13 开始,vmalloc() 默认尝试使用大页(huge pages)映射,但不是所有情况都生效——它依赖 zone 的空闲大页数量、对齐要求和分配大小。你不能靠 cat /proc/vmallocinfo 直接看出是否用了大页,因为该接口不暴露页粒度信息。

内核提供了 is_vm_area_hugepages(const void *addr) 这个内联函数来判断,但它依赖未导出的 find_vm_area(),所以**树外模块(比如你自己写的 ko)根本没法调用**。实际调试时,更可行的方式是:在内核配置中启用 CONFIG_DEBUG_VM_VALLOC,然后触发分配后检查 dmesg 是否出现 vmalloc(): using hugepage 类似日志;或者用 /sys/kernel/debug/page_owner 配合 addr 查看对应页的 order(order ≥ 2 通常意味着 4KB → 2MB 映射)。

  • 嵌入式小内存系统慎用:大页可能导致内部碎片,比如只申请 16KB 却占掉一个 2MB 大页
  • 启动时加 nohugevmalloc 参数可全局禁用,比运行时 patch 更可靠
  • 注意:即使启用了,vmalloc(4096) 也大概率还是用 4KB 页——大页只对 ≥ 几十 KB 的分配有收益

SLAB 回收为什么有时“卡住”不释放?

SLAB 分配器本身不主动回收 slab 缓存,而是等 kmem_cache_shrink() 被显式调用或由内存压力触发的 shrink_slab() 路径间接执行。常见现象是:你调了 kmem_cache_destroy(),但 /proc/slabinfo 里对应缓存项仍存在,甚至 slabinfo -a 显示 active_objs > 0。

原因通常是对象还在被引用:比如某个 struct 被放在链表里但没删干净,或被 RCU 持有未完成宽限期。SLAB 不会强制回收正在使用的对象,也不会等待 RCU 宽限期自动结束。

  • 用 slabinfo -v cache_name 查看详细状态,重点关注 active_objs 和 num_objs 差值
  • RCU 场景下,必须确保所有 synchronize_rcu() 或 call_rcu() 回调已执行完毕
  • 驱动模块卸载前,务必先清空所有对象引用,再调 kmem_cache_destroy(),否则可能 oops

OOM 前内存回收到底按什么顺序走?watermark 是怎么起作用的?

不是等 free 内存归零才回收,而是在空闲页低于 watermark[WMARK_LOW] 时就启动快速回收(kswapd),低于 watermark[WMARK_MIN] 则触发直接回收(alloc_pages() 中同步阻塞执行)。三个水位关系固定:min ,且 low = min + min/4,high = min + min/2。

Expanso json-flatten
Expanso json-flatten

通过 CLI 或 MCP 服务器,使用 Expanso Edge 管道扁平化嵌套 JSON 对象。

下载

关键点在于:kswapd 只负责把空闲页拉回 high 水位以上;一旦进程分配触发 direct reclaim,说明 low 都守不住了,此时回收路径会更激进(比如扫描更多 LRU 链表、尝试 swap、甚至考虑 OOM)。

  • 查看当前水位:grep -A10 "Node.*DMA\|Node.*Normal" /proc/zoneinfo
  • echo 1 > /proc/sys/vm/swappiness 并不能阻止 page cache 回收——只要 anon 和 file 页面都在 LRU 上,file 页面永远优先被回收
  • 频繁触发 direct reclaim?说明工作负载长期压着 low 水位跑,要么加内存,要么减少 mmap 大量文件或 tmpfs 使用

用户态看到的 “free 内存少”,真缺内存吗?

Linux 把大量空闲内存用于 page cache 和 slab,free 命令显示的 “available” 才是真正可立即分配的预估值(含可回收 cache)。很多运维第一反应是 kill 进程,但往往杀的是正在用 cache 加速 I/O 的进程,反而让磁盘变慢、延迟飙升。

真正要查的是:有没有进程在疯狂分配 anon 内存又不释放(如内存泄漏)、是否 swapin/si 持续升高(说明已在用 swap)、/proc/meminfo 中 Inactive(file) 是否远高于 Active(file)(cache 没被有效利用)。

  • 别信 top 里的 %MEM 排序结果——它算的是 RSS,包含共享库和 mmap 共享内存,不代表独占消耗
  • 用 ps aux --sort=-vsz | head -10 看虚拟内存占用,再结合 pmap -x PID 看具体段分布
  • 如果 Available 还剩 1GB 以上,但系统卡顿,大概率是 I/O 或锁竞争问题,不是内存不足

水位计算是 per-zone 的,NUMA 系统里某 node 的 low 水位被击穿,可能只影响该 node 分配,不一定触发全局 OOM;而 slab 回收的时机藏在 shrink_slab() 的调用链深处,不深入到 mm/vmscan.c 很难看清它到底什么时候愿意放手。

热门AI工具

更多
WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Lovart
Lovart Hot

一款面向视觉设计创作的AI设计平台,可通过智能体和画布工作流辅助制作海报、Logo、网页、PPT及其他视觉内容。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

PixPix
PixPix Hot

PixPix是一款面向电商视觉生产的AI商品图生成工具。

讯飞绘文

讯飞绘文是一款由科大讯飞推出的一站式 AIGC 内容运营平台。

小橡皮AI

一款AI工具,主要用于小橡皮一键去AI味,将机器味重的内容改得更有活人感,防止因为 AI 内容被平台打上 AI 标签,以及限流,适合需要提升相关任务效率的用户。

Laper
Laper Hot

Laper是专为编剧、导演和制片人推出的 AI 原生剧本创作工具。

超级麦吉

一款通过数字员工协作完成调研、数据分析与文档制作的AI办公平台。

相关专题

更多
sort排序函数用法
sort排序函数用法

sort排序函数的用法:1、对列表进行排序,默认情况下,sort函数按升序排序,因此最终输出的结果是按从小到大的顺序排列的;2、对元组进行排序,默认情况下,sort函数按元素的大小进行排序,因此最终输出的结果是按从小到大的顺序排列的;3、对字典进行排序,由于字典是无序的,因此排序后的结果仍然是原来的字典,使用一个lambda表达式作为key参数的值,用于指定排序的依据。

1158

2023.09.04

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2318

2023.09.20

javascriptvoid(o)怎么解决
javascriptvoid(o)怎么解决

javascriptvoid(o)的解决办法:1、检查语法错误;2、确保正确的执行环境;3、检查其他代码的冲突;4、使用事件委托;5、使用其他绑定方式;6、检查外部资源等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

636

2023.11.23

java中void的含义
java中void的含义

本专题整合了Java中void的相关内容,阅读专题下面的文章了解更多详细内容。

371

2025.11.27

硬盘接口类型介绍
硬盘接口类型介绍

硬盘接口类型有IDE、SATA、SCSI、Fibre Channel、USB、eSATA、mSATA、PCIe等等。详细介绍:1、IDE接口是一种并行接口,主要用于连接硬盘和光驱等设备,它主要有两种类型:ATA和ATAPI,IDE接口已经逐渐被SATA接口;2、SATA接口是一种串行接口,相较于IDE接口,它具有更高的传输速度、更低的功耗和更小的体积;3、SCSI接口等等。

3188

2023.10.19

PHP接口编写教程
PHP接口编写教程

本专题整合了PHP接口编写教程,阅读专题下面的文章了解更多详细内容。

5129

2025.10.17

php8.4实现接口限流的教程
php8.4实现接口限流的教程

PHP8.4本身不内置限流功能,需借助Redis(令牌桶)或Swoole(漏桶)实现;文件锁因I/O瓶颈、无跨机共享、秒级精度等缺陷不适用高并发场景。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

3849

2025.12.29

java接口相关教程
java接口相关教程

本专题整合了java接口相关内容,阅读专题下面的文章了解更多详细内容。

486

2026.01.19

Vite 项目如何打包和部署
Vite 项目如何打包和部署

Vite项目打包部署专题汇集生产构建、产物预览、输出目录、资源路径、Nginx与GitHub Pages部署及常见白屏和路由404问题的已审核文章,帮助读者完成上线流程。

60

2026.10.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Python uv官方安装与入门文档
Python uv官方安装与入门文档

共0课时 | 0人学习

Buffalo框架快速入门指南
Buffalo框架快速入门指南

共0课时 | 0人学习

Valgrind支持平台说明
Valgrind支持平台说明

共0课时 | 0人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn