15

有谁知道现代 x86 系统上的内存映射文件支持区域分配了哪种类型的 CPU 缓存行为或策略(例如不可缓存的写入组合)?

有什么方法可以检测是哪种情况,并可能覆盖默认行为?

Windows 和 Linux 是人们感兴趣的主要操作系统。

(编者注:这个问题以前被表述为memory mapped I/O,但该短语具有不同的特定技术含义,尤其是在谈论 CPU 缓存时。即实际的 I/O 设备,如 NIC 或与负载交谈的视频卡/ 商店。

mmap(some_fd, ...)这个问题实际上是关于当您不使用 MAP_ANONYMOUS 并且它由磁盘上的常规文件支持时,您从哪种内存中获得。)

4

2 回答 2

15

TL:DR 内存映射文件对它们映射到进程地址空间的页面缓存页面使用正常的回写策略。如果您想要不是 WB 的页面,您必须做一些特殊的和特定于操作系统的事情。


应用于地址空间区域的缓存策略通常与操作系统无关,并且仅取决于地址空间页面后面的设备类型。事实上,操作系统可以自由地将任何缓存策略应用于任何内存区域,但错误分配的缓存策略会降低系统性能或完全破坏系统逻辑。

至少有四种缓存策略:

  1. 完全缓存(回写,又名 WB)。应用于映射到主存 (RAM) 的物理地址空间。用于提高内存子系统性能的性能。这种设备的主要特性是它的状态只能由软件改变,并且只能影响软件。

    内存映射文件实现使用完全缓存,因为它们完全由软件(操作系统)实现,从磁盘读取文件块并将其放置在内存中,然后将该块(可能已修改)放回磁盘。硬件更新页表中的“脏”位,以让操作系统找出需要同步到磁盘的内容。

  2. 直写式缓存。(WT) 此类设备的主要属性是其状态只能通过软件更改,但更改必须立即对设备产生影响。根据该策略,写入内存映射IO设备寄存器的数据将同时放置在两个地方:缓存中和设备中。但是当开始读取数据时,数据将从缓存中捕获,而无需昂贵的设备访问。

    这种缓存策略对于不写入内存、只读取 CPU 写入内容的 MMIO 设备可能很有用。在实践中,它很少用于任何事情。GPU不是那样的,并且会写入视频内存,因此它不用于视频RAM。(GPU 没有使该区域的 CPU 缓存失效的机制,因为 GPU 不是 CPU 缓存一致性域的一部分)

  3. Uncacheable, write-combining (WC aka USCW):弱排序内存,通常用于映射视频 RAM。与不可缓存类似,只是 NT 存储可以让您一次有效地写入整个缓存行。 movntdqa加载让您可以有效地读取整个缓存行,这是您无法从 WC 区域执行的任何其他方式。正常加载为每个加载单独获取数据,即使在同一行中,因为它是不可缓存的。
  4. 禁用缓存。(UC) 适用于几乎所有的 IO 设备,因为写入内存映射的 IO 设备寄存器必须立即生效,从内存映射的 IO 设备寄存器读取必须从设备返回给读取器的实际数据。如果缓存将应用于内存映射的 IO 设备,则会引入两个负面影响:
    1. 写入内存映射的 IO 设备寄存器将被延迟,直到缓存控制器决定用写入的数据刷新缓存行。结果,驱动程序将无法知道写入设备的命令何时生效。
    2. 可以缓存从内存映射的 IO 设备寄存器读取的数据。从同一个内存映射的 IO 设备寄存器读取的后续数据可能不会从设备返回实际数据,而是从缓存中返回过时的数据。因此,驱动程序很难捕获设备的实际状态。

由于软件可以指定缓存策略的方式仅取决于处理器,因此可以在任何操作系统中应用相同的算法。最简单的方法是捕获 CR3 寄存器的内容,并使用它找到与您想知道的缓存策略地址对应的页表条目,并检查 PCD 和 PWT 标志。但是这种方式并不完整,因为几乎没有其他功能会影响缓存(例如,可以在 CR0 上完全禁用缓存,另请参阅 MTRR、PAT)。

于 2013-04-07T17:20:31.577 回答
2

添加到 ZarathustrA 的现有答案:在 Windows 上,SEC_NOCACHE关闭此缓存。有一个SEC_WRITECOMBINE, 但它似乎已损坏(它仅适用于SEC_RESERVEor SEC_COMMIT,这意味着仅适用于页面文件,并且您不想对其进行设置SEC_WRITECOMBINE)。

于 2013-04-07T23:28:31.837 回答