FreeBSD 如何分配内存?

Mar*_*tin 9 freebsd kernel

我知道这是简化/概括的解释,但top(1)实用程序将 FreeBSD 中的内存划分为六个池Active- InactiveWiredCacheBuffersFreetop(1)输出示例:

Mem: 130M Active, 42M Inact, 51M Wired, 14M Cache, 34M Buf, 648K Free
Swap: 512M Total, 512M Free
Run Code Online (Sandbox Code Playgroud)

Active由正在运行的进程Wired使用,主要用于内核。Inactive是来自关闭进程的内存,如果需要重用,它仍然Cache被缓存,是缓存数据,Buffers是磁盘缓冲区(我猜它类似于cachedLinuxfree(1)输出(?))并且Free是完全未使用的内存。我是正确的是FreeBSD内核自动分配的空间InactiveCacheBuffersActive或者Wired如果需要的话?

Rap*_*ens 13

简而言之,活动有线使用的内存不应或不能换出以释放内存。虽然inactive可以被适当地换出,但仍由进程或内核拥有(未释放),因此这不是大量使用的内存,但仍在使用。

新的洗衣程序是脏内存页列表,可能需要写入交换设备。无论是否需要交换脏内存,它们都会被添加回非活动队列。

为了安全(在内核的情况下)或用户态进程优化(如 ZFS),不应交换有线内存。有线内存用于文件系统的缓存,内核可能会释放这些缓存。至少对于 ZFS,这可以被视为主要是空闲内存。

免费内存绝对是免费的。

缓存(现在已弃用,我猜)已准备好被释放,因为它已经被换出并且只在那里进行可能的重新分配。

缓冲区被大多数文件系统(UFS、FAT 等)用作缓存,是文件系统使用的内存量。它可以是活动的、非活动的或有线的。

ARC(Adaptive Replacement Cache)是 ZFS 使用的缓存,它是可以在需要时释放的内存。

来自FreeBSD Wiki on Memory

内存类

积极的

  • 包含用户空间“主动”(最近)引用的页面
  • 包含干净和脏页的混合
  • 页面由页面守护程序定期扫描(每个页面每 vm.pageout_update_period 秒访问一次)
  • 扫描检查以查看自上次扫描以来该页面是否已被引用
  • 如果在没有看到引用的情况下完成了足够多的扫描,则页面将移至非活动队列
  • 实现伪 LRU

不活动

  • 包含在活动队列外老化的页面
  • 包含从缓冲区缓存中驱逐的页面
  • 包含干净和脏页的混合
  • 当内存不足时,页面守护程序(从队列的头部开始)扫描页面:
    • 被引用的页面被移回活动队列或非活动队列的尾部
    • 脏的页面被移动到洗衣队列的尾部
    • 未引用的、干净的页面可能会被立即释放和重用
  • 实现二次机会 LRU

洗衣店

  • 用于管理脏的非活动页面的队列,必须先清理(“清洗”)才能重新使用它们
  • 由单独的线程管理,洗衣线程,而不是页面守护进程
  • 洗衣线程清洗少量页面以平衡非活动和洗衣队列
  • 洗涤频率取决于:
    • 页面守护进程释放了多少干净页面;更多的自由有助于更高的洗钱频率
    • 洗衣队列相对于非活动队列的大小;如果洗衣排队越来越多,我们会更频繁地洗衣服
  • 洗衣线程扫描页面(从队列的头部开始):
    • 被引用的页面被移回活动队列或洗衣队列的尾部
    • 脏页被清洗,然后移近非活动队列的头部

自由

  • 可供系统其余部分使用的内存。

有线

  • 不可分页内存:在所有者明确释放之前无法释放
  • 用户空间内存可以通过 mlock(2) 连接(受系统和每个用户的限制)
  • 内核内存分配器返回有线内存
  • ARC 的内容和缓冲区缓存是连线的
  • 一些内存是永久连接的并且永远不会被释放(例如,内核文件本身)

摘自FreeBSD 操作系统的设计与实现章节 6.12 页面替换(不再完全准确,但这里供参考旧问题):

内核将主存划分为五个列表:

  1. 有线:有线页面被锁定在内存中,无法调出。通常,这些页面正被内核或物理内存分页器使用,或者它们已被mlock 锁定。此外,用于保存已加载(即未换出)进程的线程堆栈的所有页面也已连接。
  2. Active:活动页面正被一个或多个虚拟内存区域使用。尽管内核可以将它们分页,但这样做可能会导致活动进程再次将它们故障返回。
  3. Inactive:非活动页面可能是脏的并且具有仍然已知的内容,但它们通常不属于任何活动区域。如果页面的内容是脏的,则必须先将内容写入后备存储,然后才能重新使用该页面。一旦页面被清除,它就会被移动到缓存列表中。如果系统内存不足,pageout 守护进程可能会尝试将活动页面移动到非活动列表中,以期找到真正未使用的页面。本节稍后将介绍 pageout 守护程序用于选择要从活动列表移动到非活动列表的页面的选择标准。当空闲内存和缓存列表下降到低时,pageout 守护进程遍历非活动列表以创建更多缓存和空闲页面。
  4. 缓存:缓存页面的内容仍然是已知的,但它们不是映射的一部分。如果它们故障进入活动区域,则它们不是任何映射的一部分。如果它们在活动区域​​出现故障,它们将从缓存列表移动到活动列表。如果它们用于读取或写入,它们将首先从缓存列表移动到缓冲区缓存,并最终释放到非活动列表。一个m锁系统调用可以回收从缓存列表的页面,并将其连接。缓存列表中的页面类似于非活动页面,除了它们不是脏的,因为它们在被分页后未被修改,或者因为它们已被写入其后备存储。当需要页面时,它们可以被声明用于新用途。
  5. Free:免费页面没有有用的内容,将用于完成新的页面错误请求。

回答你原来的问题

如果需要,FreeBSD 内核会自动将空间从 Inactive、Cache 和 Buffers 池分配给 Active 或 Wired,我是否正确?

如果一段时间未使用,活动页面可能会变为非活动状态。如果内核换出一个不活动的页面,这个页面就会被移到缓存列表中。页面在缓存列表不是任何进程的虚拟映射的一部分,但可以很容易地被回收,作为活性有线。或者当 I/O 需要作为缓冲区缓存时。

有线内存不能换出主内存。如果它是由进程连接的,则需要取消连接以再次munlock成为活动内存的调用。

活动非活动有线内存可以被进程或内核释放并添加到空闲列表中。