FreeBSD 吃掉了我的 RAM
上个月,我发布了迁移我的站点服务器从旧的 Ubuntu 服务器到 FreeBSD 的过程。一些 Hacker News 的用户注意到,当我展示 fastfetch 结果时,我表示对 RAM 使用情况与 btop 的比较感到困惑,并评论说 fastfetch 可能更准确。我决定深入研究这个话题,试图理解为什么在现代操作系统中报告空闲或已使用内存比看起来更复杂。另一位用户分享了 "Linux 吃掉了我的 RAM",为 Linux 上的同样效果提供了快速解释。如果你也想要 FreeBSD 的快速答案:使用情况看起来有时不准确,因为操作系统会尽可能将磁盘中的所有内容缓存到 RAM 中以提高整体性能,但该缓存是易失性的,如果需要更多内存,将会被释放。如果你想要一个稍微长一点的答案,请继续阅读。不过,在此之前有个快速的免责声明:我并不是操作系统内部的专家,尤其是 FreeBSD 方面。这是我在业余时间进行的几周研究的总结。如果你发现任何特别错误的地方,请评论出来:分享(知识)就是关心!RAM 使用量难以定义 "Linux 吃掉了我的 RAM" 完全是为了说明未使用的 RAM 是浪费的 RAM。就像 CPU 缓存会缓存 RAM 内容,因为 CPU 可以更快地访问那部分数据一样,RAM 也会缓存磁盘数据以改善用户在系统中的体验。缓存是如何工作的稍微复杂一些,但在此之前,了解内核如何管理 RAM 是重要的。大多数现代操作系统都有虚拟内存 (VM) 系统。其基本原理是将物理内存划分为通常为 4KiB 的页面。每个页面然后被添加到不同的队列,以便内核可以调整它们,以确保所有进程在需要的时候都有内存,并且整个系统在紧缺时刻依然能够正常工作。例如:交换内存。我从未想过交换内存是如何使用的,只知道它是磁盘中一个单独的空间,将临时存储部分 RAM(如果需要)。但总的来说,当操作系统看到分配的 RAM 未被充分使用时,会以一种方式将其设置,使其可以存储到磁盘中,以备需要更多内存时使用。当程序再次请求这些页面时,它们将被移动回 RAM。每个操作系统都有不同的页面管理规则。在 FreeBSD 上,页面队列的类型如下: #define PQ_NONE 255 #define PQ_INACTIVE 0 #define PQ_ACTIVE 1 #define PQ_LAUNDRY 2 #define PQ_UNSWAPPABLE 3 #define PQ_COUNT 4 你可以在 sys/vm/vm_page.h 找到这些。所有其他基于 Unix 的系统都有类似的东西:Linux、OpenBSD、NetBSD、DragonFlyBSD。如果我们检查 top,我们会看到它不仅报告内存使用情况,还将其划分为几个类别: top 报告每个内存部分、交换和磁盘缓存的详细信息 active:活跃页面是当前正在被(主要是)用户级进程使用的页面 inactive:一段时间未被这些进程访问的页面将被移入非活动状态 laundry:这是需要写入交换空间的页面的队列。当系统需要分配不在空闲队列中的空间时,它将把非活动页面移动到此队列 wired:这是在 PQ_NONE、PQ_UNSWAPPABLE 中的内存以及内核自身使用的内存,而这些内存不受 VM 管理 free:完全未使用的内存 当曾经处于非活动状态、进入洗衣队列、被写入磁盘(交换)后,再次被拥有它的进程请求时,它将从磁盘中检索出来并转入非活动状态,最后再转到活动状态。现在我们可以开始看到,确切地说有多少内存被使用,有多少内存是空闲的,并不是那么容易。空闲队列中的内存保证是空闲的,但我们也可以争辩说,在非活动队列中的内存也是空闲的,因为它是可回收的,因为内核会在需要更多内存时释放它。然而,固定内存通常是锁定的,这就是磁盘缓存所在的地方,因此,固定内存中的一部分也是可回收的,这使得它也变得 "空闲"! 磁盘缓存 ZFS,当前 FreeBSD 的默认文件系统,具有 ARC(自适应替换缓存),一个专门的系统,用于缓存最近使用的数据到内存中,从而改善从磁盘读取的效率。该缓存会随着系统占用更多内存而收缩。内核本身具有执行这种缓存的机制,但 ARC 可以绕过这一点。所有相关统计信息可以通过内核参数 kstat.zfs.misc.arcstats.* 访问。使用 sysctl,我们可以将其全部提取: sysctl kstat.zfs.misc.arcstats 这将显示所有可用参数,但现在只有以下这些是重要的: sysctl -n kstat.zfs.misc.arcstats.size sysctl -n kstat.zfs.misc.arcstats.c_min sysctl -n kstat.zfs.misc.arcstats.c_max 这些将显示当前缓存以及配置的最小值和最大值,所有以字节为单位。使用 gnumfmt,我们可以将其转换为可读单位: $ sysctl -n kstat.zfs.misc.arcstats.size | gnumfmt --to = iec 3
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡