文件支持的内存映射的CPU缓存行为/策略?

时间:2013-04-06 16:53:24

标签: c++ x86 operating-system cpu-architecture cpu-cache

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

有没有办法检测是哪种情况,并可能覆盖默认行为?

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

(编者注:此问题之前的措辞是memory mapped I/O,但该短语具有不同的特定技术含义,特别是在谈论CPU缓存时,即您说话的实际I / O设备,如NIC或视频卡与装载/商店。

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

2 个答案:

答案 0 :(得分:15)

TL:DR内存映射文件对页面缓存的页面使用正常的回写策略,这些页面映射到进程的地址空间。如果您想要非WB的页面,则必须执行特殊操作和特定于操作系统。


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

至少有四种缓存策略:

  1. 完全缓存(回写,又称WB)。 应用于映射到主存储器(RAM)的物理地址空间。用于提高内存子系统性能的性能。这些设备的主要特性是其状态只能通过软件进行更改,并且只能影响软件。

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

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

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

  3. Uncacheable,write-combining(WC aka USCW):弱排序的内存,通常用于映射视频RAM。像不可缓存一样,除了NT存储允许您一次有效地写入整个缓存行。 movntdqa loads let you efficiently read whole cache lines,你不能从WC地区做任何其他方式。正常加载为每个加载分别获取数据,即使在同一行内也是如此,因为它是不可缓存的。
  4. 禁用缓存。 (UC) 应用于几乎所有IO设备,因为写入内存映射IO设备寄存器必须立即生效,并且从内存映射IO设备寄存器读取必须从设备返回读取器实际数据。如果缓存将应用于内存映射的IO设备,则会引入两个负面影响:
    1. 对内存映射IO设备寄存器的写入将被延迟,直到缓存控制器决定使用写入的数据刷新缓存行。因此,驱动程序将无法知道写入设备的命令何时生效。
    2. 可以缓存来自内存映射IO设备寄存器的读取数据。从同一内存映射IO设备寄存器读取的后续数据不能返回来自设备的实际数据,而是来自缓存的过时数据。因此,驱动程序很难捕获设备的实际状态。
  5. 由于软件指定缓存策略的方式仅依赖于处理器,因此可以在任何操作系统中应用相同的算法。 最简单的方法是捕获CR3寄存器的内容,并使用它找到适合您想要知道的缓存策略的地址的页表条目,并检查PCD和PWT标志。但这种方式并不完整,因为很少有其他功能可以影响缓存(例如,可以在CR0上完全禁用缓存,另请参阅MTRR,PAT)。

答案 1 :(得分:2)

添加到ZarathustrA的现有答案:在Windows上,SEC_NOCACHE转换此缓存。有一个SEC_WRITECOMBINE,但显示已损坏(仅适用于SEC_RESERVESEC_COMMIT,这仅表示页面文件,并且您不想设置SEC_WRITECOMBINE在那)。