Linux 是否有“清理”内存的机制?例如,测试内存,如果发生故障,则将区域标记为脏,以便即使安装了损坏的 RAM 芯片,系统也可以继续“安全”运行?!
答案1
答案是肯定的,并且是透明地完成的(前提是您有 ECC 内存来检测错误,并且您的内核版本至少为 2.6.30 才能继续安全运行)。
基本上,每次从处理器读取时都会检查您的内存,并定期清理*,以检查是否与错误纠正码 (ECC) 一致。如果发生错误,您将收到机器检查异常,然后由 mcelog 记录并抓取 (http://www.mcelog.org/)。
如果您的错误是可纠正的,它会递增“漏桶”计数器,这会导致频繁发生故障的物理 DIMM 无法透明地被另一个替换。因此,您的内存页面被复制到新位置,您的虚拟内存地址被更新以指向新页面,而旧页面被操作系统标记为不再使用。
这在 Linux 上称为“软离线”(在 Solaris 上称为内存页面退休,我不知道其他操作系统)。
但是,如果您的错误无法纠正,就会发生所谓的“硬脱机”,即您的内存页面将从正常的操作系统内存管理中移除,并且您的应用程序将被终止(注意:通过一些可捕获的 SIGBUS 信号告诉您错误发生的位置,但这种情况很少见,因此不必在意并尝试捕获它)。如果您的内存页面是从文件映射的并且是干净的,则操作系统也可以在另一个物理位置透明地重新加载它,而不是终止进程。
您可以在 mcelog 上阅读更多内容,其中有大量配置选项,您可以获得要触发的其他行为、选项和其他有关阅读内容以及如何确保 mcelog 在您的系统上运行的线索。
* 清理或“巡逻清理”包括读取内存、根据 ECC 检查错误,并在发现错误时用正确的内存字进行覆盖。巡逻清理这一术语用于反对在内存读取错误时覆盖不正确的数据,有时也称为“按需清理”。清理是一种硬件程序,通常可以通过 BIOS 启用。
答案2
这其实是个坏主意。快速扫描无法可靠地测试内存。这就是为什么像 memtest86 这样的软件使用具有不同位模式的多次扫描来测试内存的原因。解决方案:
内存映射=nn[KMG]$ss[KMG] [KNL,ACPI] 将特定内存标记为保留。 要使用的内存区域,从 ss 到 ss+nn。 示例:排除 0x18690000-0x1869ffff 之间的内存 内存映射=64K$0x18690000 或者 内存映射=0x10000$0x18690000
此外,您可以使用 ECC 内存,它将自动纠正 1 位错误并检测内存中的 2 位错误(如果发生无法纠正的内存问题,您将从内核获得有关这些问题的日志消息)
答案3
帖子和答案误解了这个问题。内存清理旨在防止可纠正的单比特错误变成不可纠正的双比特错误。清理器偶尔只会清理所有物理内存(强制缓存未命中)。如果有任何单比特错误,它们将被纠正(并且纠正必须使用比较和交换重写正确值),从而清除错误。
否则,如果在已经有一个错误的单词中出现第二个错误,则整个单词将无法纠正,操作系统将不得不采取一些激烈的措施。
清理非常重要,因为如果没有清理,那些只读但未写的内存(比如代码页)可能会随着时间的推移而积累错误。
答案4
如果你有 ECC 内存,你可能需要仔细看看https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-edac(我发现“sdram_scrub_rate”特别有趣。)
(如果此链接在某个时候中断(它真的不应该)我建议下载适当的 Linux 文档并搜索“scrub”。)