Linux内存
Linux 内存管理的核心策略是「闲着的内存就是浪费的内存」:内核会主动把空闲内存拿去做磁盘缓存。这导致 free 看起来总是所剩无几——理解缓存机制才能分清"内存紧张"和"缓存在工作"。
虚拟内存与分页
每个进程看到的都是独立的虚拟地址空间,内核通过页表把虚拟页映射到物理页(通常 4KB 一页)。这样做的收益:进程间天然隔离(互相看不到对方的内存)、物理内存可以超卖(10 个进程各声明 1GB 但实际只用 100MB 时不会爆)、缺页时才真正分配物理页(lazy allocation)。
进程 malloc 后不写入就不占物理内存;真正访问触发缺页中断,内核才分配物理页——这就是 top 里 VIRT 远大于 RES 的原因(VIRT 是声明的虚拟空间,RES 是实际占用的物理页)。
buffer 与 cache:free 输出的正确读法
free -h
# total used free shared buff/cache available
# Mem: 15Gi 3.2Gi 1.1Gi 200Mi 11Gi 11Gi| 列 | 含义 |
|---|---|
| used | 进程真实占用 |
| free | 完全空闲 |
| buff/cache | buffer + cache 之和,都是可回收的缓存 |
| available | 新进程实际能拿到的内存估计,看内存是否够用只认这一列 |
buffer 与 cache 的分工:
| cache(页缓存) | buffer(缓冲) | |
|---|---|---|
| 缓存对象 | 文件内容(读过的文件页留在内存) | 块设备的元数据(目录项、inode 等写磁盘前的暂存) |
| 方向 | 主要加速读 | 主要服务写 |
举例:第二次 cat 同一个大文件飞快,就是页缓存命中。判断内存是否紧张看 available 而不是 free——free 小只说明内核把内存用满了缓存,属于健康状态;available 低于总内存 10% 左右才需要警惕。
页回收与 swap
内存吃紧时内核按代价从小到大回收:先丢干净的可重建页(页缓存、代码段),再压缩/换出不活跃的匿名页(堆、栈)到 swap。/proc/sys/vm/swappiness(0-100)控制换出倾向,值越大越倾向用 swap:
cat /proc/sys/vm/swappiness # 查看,默认 60
sysctl vm.swappiness=10 # 临时调低数据库服务器通常设为 10 甚至 1(宁可回收缓存也别换出热数据),或直接关闭 swap——一旦开始频繁换页,响应延迟会断崖式劣化(磁盘比内存慢几个数量级)。代价是完全失去兜底,内存真耗尽会直接触发 OOM。
OOM killer
物理内存和 swap 都耗尽时,内核必须杀掉某个进程来自保,否则整机卡死。OOM killer 按打分选目标:占用内存越大分越高,再叠加调整因子。
dmesg | grep -i "out of memory" # 确认发生过 OOM
journalctl -k | grep -i oom # 谁被杀了
cat /proc/<pid>/oom_score # 查看某进程当前得分保护关键进程不被误杀:调低它的调整值(-1000 等于豁免)。
echo -1000 > /proc/<pid>/oom_score_adj # 运行时
# 或在 systemd unit 里配置 OOMScoreAdjust=-1000OOM 日志是容量规划的第一手证据
服务"偶发消失"十有八九是 OOM。确认方式就是上面两条命令;确认后要么加内存、要么修内存泄漏、要么给服务设内存上限(systemd 的 MemoryMax 或 cgroup),别让整机陪葬。
内存查看命令 free/vmstat/top 的用法见 Linux系统管理 的系统监控章节。