badblocks 坏块扫描工具的移植

 

e2fsprogs 是用于 ext2/3/4 文件系统的工具集,其中 badblocks 工具用于检测磁盘坏块。嵌入式系统使用的 eMMC 也可以用它来检测当前 Flash 的健康状况。我希望把它单独拿出来,做成一个测试工具

e2fsprogs 是用于 ext2/3/4 文件系统的工具集,其中 badblocks 工具用于检测磁盘坏块。嵌入式系统使用的 eMMC 也可以用它来检测当前 Flash 的健康状况。我希望把它单独拿出来,做成一个测试工具

badblocks 说明

badblocks 用于搜索设备(通常是磁盘分区)上的坏块。 device 是设备对应的特殊文件(例如 /dev/hdc1)。 last_block 是要检查的最后一个块,如果没有指定,则使用设备上的最后一个块作为默认值。 first_block 是一个可选参数,指定测试的起始块号,允许测试从磁盘中间开始。如果没有指定,则使用磁盘上的第一个块作为默认值。

重要提示:如果 badblocks 的输出要被送入e2fsckmke2fs程序,正确指定块大小是很重要的,因为生成的块数非常依赖于文件系统所使用的块大小,因此强烈建议用户不要直接运行badblocks,而是使用e2fsckmke2fs程序的-c选项。

选项说明

  • b: `block_size

    指定块的大小,单位为字节。默认值是1024。

  • c: 块的数量

    是指每次测试的块数。默认值是64。

  • d: 读取延迟因子

    这个参数如果有且不为零,如果在读操作中没有遇到错误,将导致坏块在读之间休眠;延迟时间将按读操作所需时间的百分比计算。换句话说,值为100时,将使每次读的延迟时间为前一次读所花费的时间,值为200时,则延迟时间为前一次读所花费的时间的两倍。

  • e: 最大坏块数 指定中止测试前的最大坏块数。默认值是0,意味着测试将继续进行,直到达到测试范围的终点。

  • f: force

    通常情况下,badblocks会拒绝对已挂载的设备进行读/写或非破坏性测试,因为即使它是只读挂载,也会导致系统潜在的崩溃和/或损坏文件系统。这个选项可以用-f标志覆盖,但几乎不应该使用—如果你认为你比badblocks程序更聪明,那你肯定不是。只有当/etc/mtab文件不正确,并且设备确实没有被挂载的时候,这个选项才可以安全使用。

  • i: input_file

    读取已经存在的已知坏块的列表。Badblocks将跳过对这些块的测试,因为它们是已知的坏块。如果 input_file 被指定为 “-“,那么这个列表将从标准输入中读取。该列表中列出的块将从标准输出或输出文件中产生的新坏块列表中被省略。dumpe2fs(8)-b 选项可以用来检索当前在现有文件系统中被标记为坏块的列表,其格式适用于这个选项。

  • n

    使用非破坏性读写模式。默认情况下,只进行非破坏性的只读测试。这个选项不能和-w选项结合使用,因为它们是相互排斥的。

  • o: output_file

    将坏块的列表写入指定的文件。如果没有这个选项,badblocks 会在它的标准输出中显示这个列表。这个文件的格式适合 e2fsck(8)mke2fs(8)-l 选项使用。

  • p: num_passes

    重复扫描磁盘,直到在连续扫描磁盘的num_passes中没有发现新的块。默认值是0,意味着坏块将在第一次扫描后退出。

  • s

    通过写出当前badblocks在磁盘上的大致完成百分比来显示扫描的进度。请注意,badblocks可能会在磁盘上进行多次测试,特别是当用户要求使用-p-w选项时。

  • t: test_pattern

    指定一个要读(和写)到磁盘块的测试模式。test_pattern可以是一个介于0和ULONG_MAX-1之间的数值,也可以是 “random”一词,指定磁盘块应该用一个随机的比特模式来填充。对于读/写(-w)和非破坏性(-n)模式,可以通过为每个需要的测试模式指定-t选项来指定一个或多个测试模式。对于只读模式,只能指定一个模式,而且不能是”随机”的。使用只读模式测试假定指定的模式已经被写入磁盘–如果没有,大量的块将无法通过验证。如果指定了多个模式,那么在进入下一个模式之前,所有的块都将用一个模式进行测试。

  • v

    Verbose模式,将读取错误、写入错误和数据损坏的数量写入stderr

  • w

    使用写入模式测试。使用该选项,badblocks会通过在设备的每个块上写入一些模式(0xaa、0x55、0xff、0x00)来扫描坏块,读取每个块并比较其内容。此选项不可与-n选项结合使用,因为它们是相互排斥的。

  • B

    使用缓冲I/O,不要使用Direct I/O,即使它是可用的。

  • X

    仅由 e2fsck(8)mke2fs(8) 使用的内部标志。它绕过了独占模式下的使用中设备安全检查。

警告 切勿在包含现有文件系统的设备上使用 -w 选项。这个选项会删除数据 如果你想在现有的文件系统上进行写模式测试,请使用 -n 选项。它的速度较慢,但它会保存你的数据。 -e选项会导致badblocks输出一个可能不完整的坏块列表。因此,建议只在想知道设备上是否有坏块时使用,而不是在想要坏块列表时使用。

编译配置

cd e2fsprogs-1.45.6/build

# 配置好编译选项
../configure --prefix=/home/wilson/gitRepos/e2fsprogs-1.45.6/build CC=/KIDE/tools/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-gcc --host=arm-linux-gnu

# 编译
make -j8

# 安装
make install

根据GNU惯例,软件构建中涉及到三个平台:

  • build 构建平台:编译工具执行的平台
  • host 主机平台:编译出来的程序将在其上运行的平台
  • target 目标平台:只有在构建编译器时,这才是编译器生成程序运行的平台

所以

  • 对于e2fsprogs项目,构建平台是 x86_64-pc-linux-gnu
  • 对于e2fsprogs项目,最终编译出来的程序是运行在arm板上的,根据编译工具链,可以知道 host = arm-linux-gnu
  • 对于e2fsprogs项目,它不是编译器,涉及不到 target 目标平台

完成安装后,可以找到 e2fsprogs-1.45.6/build/sbin/badblocks 程序

tasks.json

通过 build.sh 脚本先构建要调试的程序 badblocks

{
    // 有关 tasks.json 格式的文档,请参见
    // https://go.microsoft.com/fwlink/?LinkId=733558
    "version": "2.0.0",
    "tasks": [
        {
            "type": "shell",
            "label": "gcc build active file",
            "command": "${fileDirname}/build.sh",
            "options": {
                "cwd": "${fileDirname}"
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": "build"
        }
    ]
}

launch.json 的配置

在 vscode 中通过 gdb 下载编译好的代码并开始调试,launch.json 的设置如下

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "gcc - 生成和调试活动文件",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/sbin/badblocks",
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "setupCommands": [
                {
                    "description": "为 gdb 启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                },
                {
                    "description": "连接下位机gdbserver",
                    "text": "target extended-remote 128.249.182.116:9091"
                },
                {
                    "description": "读取符号信息",
                    "text": "file ${workspaceFolder}/build/sbin/badblocks"
                },
                {
                    "description": "删除调试程序",
                    "text": "remote delete badblocks",
                    "ignoreFailures": true
                },
                {
                    "description": "下载编译好的程序",
                    "text": "remote put ${workspaceFolder}/build/sbin/badblocks badblocks",
                },
                {
                    "description": "连接调试程序",
                    "text": "set remote exec-file badblocks"
                },
                {
                    "description": "设置参数",
                    "text": "set args -s -v /dev/mmcblk0"
                }
            ],
            "preLaunchTask": "gcc build active file",
            "miDebuggerPath": "/home/wilson/.wgdb/gdb",
        }
    ]
}