Memtest86+ 是一款免费、开源、独立的内存测试器,适用于 x86 和 x86-64 架构计算机。它提供了比 BIOS 内存测试更彻底的内存检查。
它还能够访问几乎所有计算机内存,不受操作系统使用内存的限制,也不依赖于任何底层软件(例如 UEFI 库)。
Memtest86+ 可以直接由 PC BIOS(传统或 UEFI)加载和运行,也可以通过支持 Linux 16 位、32 位、64 位或 EFI 切换启动协议的中间启动加载程序加载和运行。它应该适用于任何 Pentium 级或更高版本的 32 位或 64 位 CPU。
二进制版本(稳定版本和夜间开发版本)可在 memtest.org 上获取。
Memtest86+ v6.00 基于 PCMemTest,它是早期 Memtest86+ v5 的分支和重写,而后者又是 MemTest-86 的分支。 PCMemTest 重写的目的是:
在创建 PCMemTest 的过程中,Memtest86+ v5 的一些并非测试系统内存严格需要的功能被删除。特别是,没有尝试测量高速缓存和主内存速度,或识别和报告 DRAM 类型。这些功能在 Memtest86+ v6.0 中重新添加和扩展,以创建一个统一的、功能齐全的版本。
Memtest86+ 是根据 GNU 通用公共许可证版本 2 (GPLv2) 的条款发布的。除 GPL 的规定外,对于私人或商业使用没有任何限制。有关详细信息,请参阅许可证文件。
构建仅在 Linux 系统上进行了测试,但应该可以在使用 GNU 工具链和 ELF 文件格式的任何系统上进行。所需的工具有:
要构建 32 位映像,请将目录更改为build32
目录并输入make
。结果是一个memtest.bin
二进制映像文件,可以通过传统 BIOS(软盘模式)或通过使用 Linux 16 位启动协议的中间引导加载程序直接启动,以及一个可以直接启动的memtest.efi
二进制映像文件通过 32 位 UEFI BIOS。任一映像都可以由中间引导加载程序使用 Linux 32 位或 32 位 EFI 切换引导协议来引导。
要构建 64 位映像,请将目录更改为build64
目录并输入make
。结果是一个memtest.bin
二进制映像文件,可以通过传统 BIOS(软盘模式)或通过使用 Linux 16 位启动协议的中间引导加载程序直接启动,以及一个可以直接启动的memtest.efi
二进制映像文件通过 64 位 UEFI BIOS。任一映像都可以由中间引导加载程序使用 Linux 32 位、64 位或 64 位 EFI 切换引导协议来引导。
无论哪种情况,要构建可用于创建可启动 CD、DVD 或 USB 闪存驱动器的 ISO 映像,请键入make iso
,结果是memtest.iso
ISO 映像文件。然后可以将其直接写入空白 CD 或 DVD,或 USB 闪存驱动器,然后可以通过传统或 UEFI PC BIOS 直接启动。
请注意,写入 USB 闪存驱动器时,必须使用dd
命令或使用提供相同功能的实用程序将 ISO 映像直接写入(“转储”)到原始设备。
使用中间引导加载程序时, memtest.bin
文件或memtest.efi
文件应存储在引导加载程序可以访问的磁盘分区中,并且引导加载程序配置应更新为从该文件引导,就像它是 Linux 内核一样没有初始 RAM 磁盘。可以识别多个引导命令行选项,如下所述。如果使用 16 位启动协议,Memtest86+ 将使用文本模式 (640x400) 显示。如果使用 32 位或 64 位引导协议,Memtest86+ 将使用文本模式或图形模式显示,如引导加载程序传递给它的boot_params
结构中指定的那样。如果在图形模式下,提供的帧缓冲区必须至少为 640x400 像素;如果更大,显示将居中。如果系统以 UEFI 模式启动,则必须使用图形模式。
出于测试目的,还可以选择构建使用 GRUB 作为中间引导加载程序的 ISO 映像。详细信息请参见build32
或build64
目录中的Makefile
。 ISO 映像既可以是旧版,也可以是 UEFI 可引导的,因此您需要在构建系统上安装用于旧版和 EFI 引导的 GRUB 模块(例如,在 Debian 上,所需的 GRUB 模块位于包grub-pc-bin
、 grub-efi-ia32-bin
中) grub-efi-ia32-bin
和grub-efi-amd64-bin
)。您可能需要调整 Makefile 中的某些路径和文件名以匹配系统上的命名。
grub
目录中包含的 GRUB 配置文件可在测试 ISO 上使用,但也可作为如何从 GRUB 引导 Memtest86+ 的示例。
中间引导加载程序可以将引导命令行传递给 Memtest86+。命令行可以包含一个或多个选项,以空格分隔。每个选项都由一个选项名称组成,后面可以选择跟一个=
号和一个或多个参数,参数之间用逗号分隔。可以识别以下选项:
0x
前缀(例如:0xFEDC9000) Memtest86+ 支持传统键盘接口(使用 I/O 端口 0x60 和 0x64)和 USB 键盘(使用其自己的 USB 设备驱动程序)。可以通过启动命令行选择其中之一或两者,如果在命令行上未指定,则默认情况下系统以 UEFI 模式启动时使用两者,否则仅使用旧版界面。
较旧的 BIOS 通常支持 USB 传统键盘模拟,这使得 USB 键盘就像连接到端口 0x60 和 0x64 的传统键盘一样。通常可以在 BIOS 设置菜单中启用或禁用此功能。如果 Memtest86+ 的 USB 设备驱动程序已启用,它们将覆盖此设置并直接访问任何 USB 键盘。其缺点是 USB 控制器和设备驱动程序需要保留一些内存供其私人使用,这意味着内存测试无法覆盖这些内存。因此,为了最大限度地提高测试覆盖率,如果支持,请启用 USB 传统键盘模拟,如果在 UEFI 模式下启动,请在启动命令行上添加keyboard=legacy
。
注:当您在 BIOS 设置中启用兼容性系统模块 (CSM) 时,某些 UEFI BIOS 仅支持 USB 传统键盘模拟。其他人仅在实际以传统模式启动时才支持它。
许多 USB 设备并不完全符合 USB 规范。如果 USB 键盘探针挂起或无法检测到键盘,请尝试“usbinit”引导选项提供的各种解决方法。
注意:Memtest86+ USB 驱动程序当前不支持热插拔。使用这些时,您的 USB 键盘应在运行 Memtest86+ 之前插入,并在整个测试过程中保持插入状态。
一些二合一机器使用 LCD 面板,该面板本身是纵向模式显示器,但在连接到键盘时安装在侧面。当在图形模式下使用显示器时,Memtest86+可以旋转其显示器以匹配。根据 LCD 面板的方向,在启动命令行上添加“screen.rhs-up”或“screen.lhs-up”选项。当在文本模式下使用显示器时,BIOS 应该会自动处理这个问题。
当以传统模式启动时,Memtest86+ 将使用 BIOS 或中间引导加载程序设置的屏幕分辨率。在 UEFI 模式下启动时,Memtest86+ 通常会选择包含 640x400 像素显示屏的最小可用屏幕分辨率。某些 BIOS 返回有关可用显示模式的错误信息,因此您可以通过在引导命令行上添加“screen.mode=”选项来覆盖此信息。
请注意,使用显示旋转时,指定的屏幕分辨率适用于未旋转的显示。
启动后,Memtest86+ 将初始化其显示,然后暂停几秒钟以允许用户配置其操作。如果没有按下任何键,它将自动开始使用单个 CPU 核心运行所有测试,无限期地继续,直到用户重新启动或停止机器。
在启动和运行测试时,Memtest86+ 响应以下按键:
请注意,当启用滚动锁定并且滚动区域已满时,测试会停止。
配置菜单允许用户:
在所有情况下,数字键都可以用作功能键的替代键(1 = F1、2 = F2、...0 = F10)。
错误报告模式可以随时改变,而不会中断当前的测试序列。无论当前错误报告模式如何,都会收集错误统计信息(因此切换到错误摘要模式将显示自当前测试序列开始以来累积的统计信息)。 BadRAM 模式仅在处于 BadRAM 模式时才会累积。 Linux memmap 区域仅在处于 memmap 模式时累积。坏页码仅在坏页模式下才会累积。
对所选测试、地址范围或 CPU 排序模式的任何更改都将启动新的测试序列并重置错误统计信息。
仅错误计数模式仅显示自当前测试序列开始以来发现的错误总数。
错误摘要模式显示以下信息:
单独的错误模式显示每个错误实例的以下信息:
BadRAM 模式模式会累积并显示错误模式,以便与 Linux BadRAM 功能或 GRUB badram 命令一起使用。行以badram=F1,M1,F2,M2...
形式打印。在每个F,M
对中, F
表示故障地址, M
是该地址的位掩码。这些模式表明故障发生在 M 中所有1
位上等于 F 的地址中。这种模式可能捕获比实际存在的错误更多的错误,但至少捕获了所有错误。这些模式旨在以简洁的语法捕获由硬件结构引起的错误的常规模式。
BadRAM 模式是增量增长的,而不是根据所有错误的概览来计算。出于多种实际原因,对的数量限制为 20。因此,在特殊情况下,从地址打印模式的输出中手工制作图案可能会产生更好的结果。
注:正如各个测试描述中提到的,步行地址测试(测试 0)和块移动测试(测试 7)不会影响 BadRAM 模式,因为这些测试不允许确定故障的确切地址。 。
Linux memmap 模式会累积并显示错误内存区域,以便与 [Linux memmap 引导命令行选项] (https://www.kernel.org/doc/Documentation/admin-guide/kernel-parameters.txt) 一起使用。行以memmap=S1$A1,S2,A2...
形式打印。在每个S,A
对中, A
表示区域中的第一个地址, S
是区域的大小(以字节为单位)。最多可记录 20 个故障内存区域。一旦发现超过20个连续故障位置的区域,区域将被合并,这意味着一些区域包括非故障位置。该程序将尝试最小化所包含的无故障位置的数量。
注:正如各个测试描述中提到的,步行地址测试(测试 0)和块移动测试(测试 7)不会导致故障内存区域,因为这些测试不允许故障的准确地址被确定。决定。
坏页模式会累积并显示错误的内存页号。这些可以与 Windows bcdedit 命令一起使用,将这些页面添加到 Windows PFA 内存列表中。页码要么显示为单个十六进制数字(例如0x20
),要么显示为一系列十六进制页码(例如0x20..0x2a
)。最多可记录 20 个范围的错误页面。一旦发现超过 20 个连续故障页面范围,范围将被合并,这意味着某些范围包含非故障页面。程序将尝试最小化所包含的无故障页面的数量。
注:正如各个测试描述中所提到的,步行地址测试(测试 0)和块移动测试(测试 7)不会对错误页码产生影响,因为这些测试不允许确定错误的确切地址。决定。
请注意,并非 Memtest86+ 报告的所有错误都是由于内存不良造成的。该测试隐式测试 CPU、缓存和主板。测试不可能确定导致故障发生的原因。大多数失败都是由于内存问题造成的。如果不是这样,唯一的选择就是更换零件,直到故障得到纠正。
一旦检测到内存错误,确定故障模块就不是一个明确的过程。由于主板供应商数量众多,内存插槽的组合也可能很多,因此要收集有关特定错误如何映射到故障内存模块的完整信息,即使不是不可能,也是很困难的。然而,可以采取一些步骤来确定故障模块。以下是您可能希望使用的一些技术:
移除模块
旋转模块
更换模块
有时,由于组件不兼容,会出现内存错误。内存模块可能在一个系统中工作正常,但在另一系统中则不然。这并不罕见,也是造成混乱的根源。这些组件不一定是坏的,但可能需要避免某些组合。
在绝大多数情况下,Memtest86+ 报告的错误都是有效的。有些系统会导致 Memtest86+ 对内存大小感到困惑,并且会尝试测试不存在的内存。这将导致大量连续地址被报告为错误,并且通常会有许多位出错。如果故障地址的数量相对较少,并且只有一两位错误,则可以确定这些错误是有效的。此外,间歇性错误始终有效。
所有有效的内存错误都应该被纠正。正常操作中可能永远不会出现特定错误。然而,使用边际内存进行操作是有风险的,可能会导致数据丢失甚至磁盘损坏。
Memtest86+无法诊断多种类型的PC故障。例如,导致操作系统崩溃的 CPU 故障很可能会导致 Memtest86+ 以同样的方式崩溃。
完全通过 Memtest86+ 所需的时间会根据 CPU 速度、内存速度和内存大小的不同而有很大差异。 Memtest86+ 无限期执行。每次运行所有选定的测试时,通过计数器都会递增。一般来说,一次通过就足以捕获除最隐蔽的错误之外的所有错误。然而,当怀疑出现间歇性错误时,为了获得完全的信心,建议进行较长时间的测试。
有很多测试记忆力的好方法。然而,许多测试只是简单地向内存抛出一些模式,而没有过多考虑或了解内存架构或如何最好地检测错误。这对于硬内存故障来说效果很好,但对于发现间歇性错误几乎没有作用。基于 BIOS 的内存测试对于发现间歇性内存错误毫无用处。
存储芯片由大量紧密封装的存储单元组成,每个存储单元对应一位数据。绝大多数间歇性故障是这些存储单元之间相互作用的结果。通常,写入存储单元可能会导致相邻单元之一被写入相同的数据。有效的记忆测试试图测试这种情况。因此,测试内存的理想策略如下:
显然,该策略需要准确了解存储单元在芯片上的布局方式。此外,针对不同芯片类型和制造商,可能的芯片布局数量无穷无尽,使得这种策略不切实际。然而,有一些测试算法可以近似这种理想策略。
Memtest86+ 使用两种算法提供上述理想测试策略的合理近似。第一个策略称为移动反转。移动反转测试的工作原理如下:
该算法非常接近理想的内存测试,但存在一些局限性。如今大多数高密度芯片都存储 4 至 16 位宽的数据。对于超过一位宽的芯片,不可能选择性地仅读取或写入一位。这意味着我们不能保证所有相邻细胞都经过了相互作用测试。在这种情况下,我们能做的最好的事情就是使用一些模式来确保所有相邻单元至少都已写入所有可能的一和零组合。
还可以看出,缓存、缓冲和乱序执行都会干扰移动反转算法并使其效率降低。可以关闭缓存,但新高性能芯片中的内存缓冲无法禁用。为了解决这个限制,创建了一种名为 Modulo-20 的新算法。该算法不受缓存或缓冲的影响。该算法的工作原理如下:
该算法几乎可以完成与移动反转相同水平的邻接测试,但不受缓存或缓冲的影响。由于对所有内存进行了单独的写入传递(1.1、1.2)和读取传递(1.4),因此我们可以确保所有缓冲区和高速缓存都已在传递之间刷新。选择 20 作为步幅有点随意。更大的步伐可能更有效,但执行起来会花费更长的时间。选择 20 似乎是速度和彻底性之间的合理折衷。
Memtest86+ 执行一系列编号测试来检查错误。这些测试由测试算法、数据模式和缓存的组合组成。这些测试的执行顺序经过精心安排,以便尽快检测到错误。每个测试的描述如下。
为了允许在 32 位 CPU 上测试超过 4GB 的内存,物理地址范围被分为 1GB 窗口,每次将一个窗口映射到虚拟内存窗口中。每个 1GB 窗口可能包含一个或多个连续的内存区域。对于大多数测试,测试是依次在每个内存区域上执行的。除第一个测试外,所有测试均启用缓存。
在每个内存区域中,使用步行地址模式依次测试所有地址位。此测试中的错误不会导致 BadRAM 模式、memmap 区域或坏页区域。
在每个内存区域中,每个地址依次写入自己的地址,然后检查每个地址的一致性。无论用户选择哪种 CPU 排序模式,都会对每个可用的 CPU 按顺序执行此测试。
在所有内存区域中,每个地址都写入自己的虚拟地址加上窗口号(对于 32 位图像)或自己的物理地址(对于 64 位图像),然后检查每个地址的一致性。这可以捕获高阶地址位中的任何错误,这些错误在依次测试每个窗口时可能会被遗漏。无论用户选择哪种 CPU 排序模式,都会对每个可用的 CPU 按顺序执行此测试。
在每个内存区域中,依次针对每个模式,使用具有全 1 和全 0 模式的移动反转算法。
在每个存储区域中,依次针对每个模式,使用具有 8 位宽步行 1 和步行 0 模式的移动反转算法。
在每个存储区域中,依次针对每个模式,使用具有随机数及其补码模式的移动反转算法。每次测试通过的随机数都不同,因此多次通过可以提高有效性。
在每个内存区域中,依次对每个模式使用移动反转算法,其中模式为 32 位宽(在 32 位构建上)或 64 位宽(在 64 位构建上)移动 1 和移动 0 。与之前的测试不同,该模式在每个连续地址上循环 1 位。
该测试通过使用块移动 (movs) 指令来强调内存,并且基于 Robert Redelmeier 的 burnBX 测试。
在每个内存区域中,内存依次使用每 8 个字节反转一次的移位模式进行初始化。然后使用 movs 指令移动内存块。移动完成后,检查数据模式。由于仅在内存移动完成后才检查数据,因此无法知道错误发生在哪里。报告的地址仅适用于发现不良模式的位置。因此,此测试中的错误不会导致 BadRAM 模式、memmap 区域或坏页区域。
在每个内存区域中,依次向每个地址写入随机数,然后检查每个地址的一致性,并写入原始数据的补码,然后再次检查每个地址的一致性。
在每个内存区域中,依次针对每个模式,使用具有随机数及其补码模式的 Modulo-20 算法。每次测试通过的随机数都不同,因此多次通过可以提高有效性。
跨所有内存区域,依次针对每个模式,用模式初始化每个内存位置,休眠一段时间,然后检查每个内存位置的一致性。使用全零和全一的模式执行测试。
请参阅 GitHub 上的未决问题和增强请求列表。
请随时提交错误报告!
欢迎贡献代码,无论是修复错误还是进行增强。请参阅 doc 目录中的 README_DEVEL.md 了解一些基本指南。
Memtest86+ v6.0 基于 Martin Whitaker 开发的 PCMemTest,后者基于 Samuel Demeulemeester 开发的 Memtest86+ v5.01,而后者又基于 Chris Brady 开发的 Memtest86,并获得了下列资源和帮助:
源文件 bootsect.S、setup.S、head.S 和 build.c 的初始版本来自 Linux 1.2.1 内核,并已进行了大量修改。
Doug Sisk 提供了支持通过串行端口连接的控制台的代码。 (目前未使用)
创建 BadRAM 模式的代码由 Rick van Rein 提供。
块移动测试基于 Robert Redelmeier 的 burnBX 测试。
屏幕缓冲区代码由 Jani Averbach 提供。 (Memtest86+ v6.0 未使用)
Eric Biederman 提供了 3.0 版的所有功能内容以及许多错误修复和重要的代码清理。
Samuel Demeulemeester(来自 Memtest86+ v1.11、v1.60 和 v1.70)在 3.2、3.3 和 3.4 版中对硬件检测和报告进行了重大增强。
此外,还从 anphsw/memtest86 导入了 Memtest86+ 的多个错误修复。