内存、虚拟内存与 OOM

Linux 内存:怎么看、底层机制与 OOM

都知道 free -h 查看内存,但是真的看懂输出了吗?虚拟内存是什么?OOM 是什么? 本节讲的是怎么看内存 ,以及系统内存的底层原理与机制。


一、内存怎么看

bash 复制代码
free -h
text 复制代码
              total        used        free      shared  buff/cache   available
Mem:           15Gi       6.2Gi       1.1Gi       412Mi       8.4Gi       8.9Gi
Swap:         4.0Gi          0B       4.0Gi

这么多字段,哪个字段才能看内存?

free 字段显示只有 1.1Gi,是不是只有 1Gi 了?不是! 还是说要看 used 字段?也不是! 那 buff/cache 占比这么大,是不是说明内存不足了?这是缓存 (Linux 拿空闲内存缓存文件数据加速),应用需要时会自动回收。

其实真正要看的是 available 字段,真正缺内存的信号是 si/so ------ 如果 vmstat 里 si/so 持续不为 0,才说明内存真的紧张。至于 Swap 是什么,后续会讲。

free 各字段的含义:

字段 含义
total 物理内存总量
used 已用(= total − free − buff/cache)
free 完全没用的空闲(很小是正常的)
shared tmpfs / 共享内存占用
buff/cache 块设备缓冲 + 文件页缓存(可回收)
available 应用真正还能拿到的内存(看这个)

1. 能不能手动释放 cache?

能但生产慎用 :echo 3 > /proc/sys/vm/drop_caches。它是缓存,不是泄漏;释放后系统还要重新读盘,性能反而变差。

2. 内存不够会有什么现象

  • 系统变慢(频繁换页到 swap,wa 变高)
  • 进程被 OOM Killer 杀掉 → dmesg | grep -i oom 能查到
  • 容器里的进程被杀 → 状态显示 OOMKilled
  • 新进程 fork 失败(Cannot allocate memory)
  • 日志里出现 "Out of memory: Killed process ..."

3. 用 top 怎么排查进程的内存

这个专门写一节怎么运用 top 指令的,等待更新


二、虚拟内存与缺页中断(机制层)

涉及的概念

概念 一句话
虚拟内存 进程看到的地址空间;提供隔离、连续地址、可换出到 swap、可共享
物理内存 真正装在机器上的内存条
页(page) 内存管理的最小单位,通常 4KB
页表 / TLB 虚拟地址 → 物理地址的映射表 / 它的高速缓存
匿名页 没有对应文件的页(堆、栈、malloc 出来的内存)→ 回收时只能写 swap
文件页 对应磁盘文件的页(程序、数据、page cache)→ 可直接丢弃再读回

1. 为什么需要虚拟内存

① 隔离 :进程 A 碰不到进程 B 的内存; ② 连续假象 :不必要求物理内存连续,解决碎片; ③ 超量使用:可以换出到 swap、可以按需加载。

2. 什么是缺页中断

  1. 进程访问一个虚拟地址
  2. CPU 查页表:发现这一页"不在物理内存"(页表项无效)
  3. 触发缺页异常(page fault),陷入内核
  4. 内核判断属于哪种情况:
    • 从来没分配过 → 分配一个物理页(可能填零)
    • 页在 page cache / 已在内存但没建立映射 → 建立映射
    • 页被换出到 swap 或存在文件里 → 发起磁盘 IO 读回来
  5. 更新页表(并刷新 TLB)
  6. 返回用户态,重新执行刚才那条指令 ------ 这次就成功了

根据页是否在物理内存里,分成了两种缺页:

类型 定义 代价 典型场景
minor(次要)缺页 页其实已经在物理内存里,只是还没建立映射 小(不涉及磁盘) 首次访问 malloc 的堆、mmap 建立映射、写时复制 COW
major(主要)缺页 页不在内存,必须读磁盘(swap 或文件) 大(一次磁盘 IO) 进程被换出后又被唤醒、首次读大文件

性能经验 :major fault 持续很高 = 在疯狂读磁盘 / swap,系统会明显变卡 (这时候 si/so、wa 一般也高)。

3. 内存映射(mmap)是什么?有什么用?

mmap = 把一个文件(或一块匿名内存)映射到进程的虚拟地址空间 。 之后进程"读写内存"就等于"读写文件",不用 read/write 系统调用搬运 ------ Linux 的一切皆文件。

类型 说明 典型用途
文件映射 映射一个文件,页来自 page cache 加载动态库(libc.so)、大文件随机读写
匿名映射 不关联文件,只能放内存 / swap malloc 的大块内存、共享内存
私有(MAP_PRIVATE) 写时复制(COW),改动不回写文件 加载程序段
共享(MAP_SHARED) 多个进程看到同一份改动 进程间共享内存(IPC)

它的好处:

  1. 快:少一次用户态 ↔ 内核态的数据拷贝(对大文件尤其明显)
  2. 共享:多个进程映射同一个文件 / 同一段匿名内存,天然共享
  3. 按需加载:只有真正访问到的页才读进来(配合缺页中断)

联系前面 :free 里的 buff/cache 很大一部分就是这些文件映射带来的 page cache ------ 它是缓存,不是内存不够。


三、swap 与 OOM

1. 什么是 swap?什么情况会用到 swap

text 复制代码
swap = 磁盘/SSD 上划出来的一块空间,作为内存的后备。
内存紧张时,内核会先回收"文件页"(直接丢掉,需要时再读回来),
再回收不动就只好把"匿名页"写到 swap(换出),等进程再用到时再读回来(major fault)
bash 复制代码
free -h ; swapon --show ; cat /proc/swaps  # 查看 swap
vmstat 1 5                                 # 看 si/so
sysctl vm.swappiness                       # 看当前值

什么情况下"会用 swap" :① 内存压力大(available 低于水位);② swappiness 偏高;③ 应用有大量"长时间不访问的匿名页";④ 内存限制(容器 / cgroup)被触发。 注意 :swap 用起来不是"故障",但 swap 频繁读写就是性能灾难(机械盘随机 IO 比内存慢几万倍)。很多数据库 / 中间件要求关掉 swap 或调到很低。

生产环境要不要开 swap?

普通服务器建议留一点(内存的 12 倍或按需,比如 4 8G)当缓冲 ,防止一次内存尖峰直接触发 OOM; 但数据库 / 中间件(MySQL、Redis)和 K8s 节点 一般要求关掉或把 vm.swappiness 调到 1~10,避免换页导致延迟抖动。

2. 什么是 OOM?什么导致了 OOM?

text 复制代码
物理内存 + swap 都回收不出空间,新的内存申请无法满足
  → 内核的 OOM Killer 介入,按 oom_score 挑一个进程杀掉,回收它的内存
  → 目的是保住系统本身不崩
类别 具体原因
应用层 ① 内存泄漏 (只申请不释放) ② 并发/流量激增,瞬时申请太多 ③ 一次性加载大文件、大查询结果集 ④ JVM/进程堆参数设得比物理内存还大(-Xmx 超配)
内核参数 ⑤ overcommit (允许超量分配,vm.overcommit_memory=1 时更容易 OOM) ⑥ swappiness / 水位设置不当,缓存回收不及时
资源规划 ⑦ swap 太小或没开,没有缓冲 ⑧ 多个服务挤在一台机器上,总量超过物理内存 ⑨ 容器 / cgroup 内存 limit 设太小(容器里报 OOMKilled)
不可回收 ⑩ 内核页、共享内存段、锁定内存(mlock)太多,page cache 回收不动
OOM Killer 怎么挑人?

等待更新

出了 OOM 怎么查?

等待更新


四、内存泄漏排查

等待更新

相关推荐
贞明电子3 小时前
工业三色报警灯怎么接入项目系统?开关量与RS485控制应用指南
运维·网络·微信公众平台·贞明电子
HideF4 小时前
Linux
linux·服务器·网络
万联WANFLOW4 小时前
海外网络故障怎么排查?Cloudflare 三季度断网报告解读与 mtr 实战
运维·网络·故障分析
Ruiery6 小时前
Linux 6.6内核内存管理深度解析(十三):slab/slub 分配器
linux·运维·服务器
Decay__7 小时前
04_MySQL DBA 日常运维手册 —— 会话管理、锁与阻塞、事务监控、慢查询与日志巡检
运维·数据库·sql·mysql·架构
丰锋ff8 小时前
压缩命令笔记
linux
江华森8 小时前
数据中心基础设施运维实战:概述与实验环境搭建
运维
迪菲赫尔曼8 小时前
【基础篇 11】把官方源码放到服务器:版本、解压层级和安装位置,一次弄清楚
运维·服务器·开发语言·人工智能·python·yolo·目标检测
GeW9 小时前
产业新优势基础软件的人才底盘,从Linux与数据库开始
linux·数据库
by2099910 小时前
Linux GCC/G++ 编译与 Makefile 构建
linux·运维·服务器·经验分享