【问题标题】:Search for bad sectors of a device in C在C中搜索设备的坏扇区
【发布时间】:2020-12-13 00:40:36
【问题描述】:

我正在尝试在 c 中创建一个简单的脚本,该脚本能够识别(设备)的坏扇区以用于教育目的。在我的示例中,我使用具有只读模式的 HD。背后的想法很简单,但也许太简单了,我会知道这是否正确,并最终了解实现我目标的任何其他方式。

让我们看看我的代码:

#include<stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>

int main(int argc, char ** argcv){
        size_t size_block = 512;
        int fd = open("/dev/disk2",O_RDONLY);
        ssize_t bytes_read = 1;
        char *buff = malloc(size_block * sizeof(char));

        if (buff == NULL){
           exit(EXIT_FAILURE);
        }

        while (bytes_read > 0){
                bytes_read = read(fd,buff,size_block);
                int position = lseek(fd, 0, SEEK_CUR);
                if (bytes_read == -1){
                        perror("main");
                }
                //printf("%s",buff); //prints the content of what I read
                if (bytes_read < size_block){
                        printf("the block at %p address is probably damaged",&position);
                }
        }
        free(buff);
        close(fd);
        return 0;
}

所以我尝试通过每次查找 512 字节的文件指针来使用读取系统调用来读取我的 HD 扇区。这是第一个问题:由于首选的 I/O 块大小是 2048 字节(使用 sys/stat.h 的 stat 检索的信息),每次 512 字节而不是 2048 字节是否正确查找? 另外,为了检查一个扇区是否坏,我会比较(bytes_read &lt; size_block),因为我假设如果我无法读取一个扇区的全部字节,它可能会被损坏。但是,如果我到达“文件的末尾”并且使用这种方法它不是 512 的倍数,我会得到该扇区无论如何都已损坏,如果它不是。我写的真的有用吗?不然怎么做这个检查?

【问题讨论】:

  • 总是检查malloc是否不返回NULL
  • 每个循环的 malloc/free 没有意义。只需 malloc 一次,在循环之前。 lseek 返回 off_t,而不是 intread 返回 ssize_t,而不是 intdo not cast result of malloc(int)size_block 演员也很奇怪 - 删除它。而且我不认为我遵循read+lseek 操作-read 自己寻找光标,所以通过调用lseek,您一次移动到2*size_block
  • bytes_read 设置为 1 只是为了让 while 循环第一次运行……是违反直觉的。只需使用 do {} while 循环而不是 while{}
  • @Hawk 我忘了,谢谢。
  • @KamilCuk 你确定读指针的行为吗?有参考吗?

标签: c system-calls hard-drive sector


【解决方案1】:

至少在 Linux 上,我相当肯定块设备的可读大小总是 512 字节的倍数,而不管底层设备容量如何。如果没有足够的物理数据来填充 512 字节,内核会填充最后一个块。在设备上创建文件系统时,文件系统工具会向下舍入分配的大小以解决此问题。

这意味着大小为 512 的 read() 将始终返回 512 或错误,即使它是最后一次读取并且它没有填满整个 512 字节的缓冲区。

但是,我认为坏扇区不太可能导致看起来很短的读取。我认为 read() 更有可能只是失败并返回-1,或者只是看起来成功并返回一些废话。我怀疑你需要读写来检查坏扇区。

【讨论】:

  • “我怀疑您需要读写来检查坏扇区” 但是在扇区上写入可能会取代我的真实数据,并且像 badblocks 这样的软件不会这样做。 link(在文章末尾阅读时说:默认情况下,badblocks 命令将执行只读测试。)。也看看这个程序:github 第一个功能说:“只读扫描坏块”。所以我认为是可以做到的。
  • 如果您知道可以做您想做的事情的实用程序,为什么不联系作者呢?但是,我怀疑只读测试只会显示坏块,如果它们已经被驱动器固件或文件系统标记为坏块。这种标记通常发生在详尽的测试期间,但我认为如果应用程序不幸编写了不可写的块,也可能发生这种情况。我不认为简单的读取可以可靠地找到系统不知道的坏块,但我之前错了。
  • 如果驱动器固件在块校验和中发出错误信号,读取可能会失败。这表明磁盘上的数据不可靠,但这并不一定意味着该扇区不能再次使用。我真的认为你需要写来确定这一点。可以想象,这里的问题是缺乏对“坏”的精确定义。尽管如此,我仍然认为你不必担心得到一个不是缺陷结果的简短阅读,我认为这就是你最初所要求的。
  • 好吧,我的第一个想法是,对于坏的“扇区”,我们指的是既不能用于写入也不能用于独立于坏定义的读取的扇区。在这一点上,我知道很难准确地确定一个扇区是否真的是坏扇区,所以无论如何我都会很满意地确定哪些扇区是我们无法独立于写入状态读取的。
  • 如果块的校验位错误并且驱动器固件无法恢复数据,则读取将失败。一旦块被标记为坏,写入它将使用一个备用扇区,因此磁盘将显示为已修复。写入未经过验证,因此通常不会失败。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-18
  • 1970-01-01
  • 2022-01-24
  • 2021-09-10
  • 2014-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多