上个月我把网站服务器从Ubuntu迁到了FreeBSD,然后在Hacker News上贴了一张fastfetch的系统信息截图。很快有人注意到,我同时展示的btop读数里,内存占用对不上。我随口说了句“可能fastfetch更准确”,结果这句话把我拉进了一个深坑——现代操作系统上报的“已用内存”和“空闲内存”,为什么总在同一台机器上打架?

有用户甩来一篇经典文章《Linux ate my RAM》,几句话就讲清了Linux下的类似现象。FreeBSD这边其实也一样粗暴:操作系统会拼命把磁盘数据塞进内存当缓存,这层缓存随时可以丢弃,一旦某个进程真的需要内存,立刻腾地方。所以你看似“内存满了”,实际上只是系统在替你预支空闲资源。但如果你想要稍微长一点的解释,事情就复杂多了。

打开网易新闻 查看精彩图片

先统一一个概念:在现代操作系统眼里,不用满的RAM就是浪费。CPU用缓存来加速内存访问,操作系统就用内存来加速磁盘访问,逻辑一脉相承。但这套缓存机制怎么运作,得从内核的“页面队列”说起。几乎所有类Unix系统都靠虚拟内存把物理RAM切成4KiB大小的页,再把这些页分到不同队列里轮流调换。比如FreeBSD定义了五类队列:活跃(ACTIVE)、不活跃(INACTIVE)、洗衣房(LAUNDRY)、不可换出(UNSWAPPABLE)和一个预留的COUNT。这些队列决定了页的命运:长期不碰的可以被换出到磁盘上的交换空间,一旦程序回访,再换回来。

打开网易新闻 查看精彩图片

这时候分歧就来了。正方说,top命令把内存分成active、inactive、laundry、wired等好几刀,已经足够细致,你只要看懂“active才是进程真正在使用的页”,就不会被吓到。反方反驳:但free命令就简单一个“used”数甩给你,用户不看源码谁知道里面还包含了一堆随时可以服软的缓存?fastfetch和其他工具拿到的数字不一样,根源就在这里是各工具对“已用”的定义不同。

打开网易新闻 查看精彩图片

我的判断很简单:两个都对,只是回答的问题不一样。top回答的是“这些页现在挂着什么标签”,fastfetch或free回答的是“从某个角度算出还剩多少空间”。真正让人困惑的,是我们在界面里想当然地把一个复杂的分层体系简化成了一个进度条。下次再看到内存占用突然飙高,先别慌,翻一翻活跃页,那才是你最该关心的实报实销。