【问题标题】:Recently, i am on a project which needs raw read / write sector of drives最近,我正在进行一个需要原始读/写驱动器扇区的项目
【发布时间】:2010-12-11 13:26:57
【问题描述】:

之前,我在这里发布了一个问题,询问有关如何从驱动器读取和写入数据的建议,而不是通过像“aaa.txt”这样的文件标签,而只是扇区.. 我被建议尝试阅读和写作...... 但新的问题已经提出......毛茸茸的参数

int _read( int handle, void *buffer, unsigned int count );

当我使用该功能并希望从驱动器中读取扇区时...我似乎需要将计数设置为 x*512。它必须是512字节的几倍......

为什么???是否有一些原始函数允许我直接逐字节使用... 谢谢... btb,如果我想这样做,我应该开发自己的 I/O 驱动程序吗? 谢谢

【问题讨论】:

  • 您可能希望接受您之前问题的一些答案,以便花时间回答这些问题的人获得一些奖励。

标签: windows linux file-io sector


【解决方案1】:

对设备的读取和写入都必须是扇区对齐的,并且字节数必须是扇区大小的整数倍。

不要对扇区大小做出假设,您应该查询任何设备的扇区大小,并动态处理它。硬盘驱动器的典型尺寸为 512,光驱为 2048。

如果您想要允许您在设备上逐字节读取的功能,而不会产生浪费的开销,请尝试以下技巧:

FILE *file_pointer = fopen("/path/to/device", "rb");
size_t sector_size;
ioctl(fd, BLKSSZGET, &sector_size);
setvbuf(file_pointer, NULL, _IOFBF, sector_size);

如果您需要在 Windows 上获取扇区大小,您可以调用 DeviceIoControl()IOCTL_DISK_GET_DRIVE_GEOMETRY

Stdio 会将搜索与s 对齐并读取大小为s 的块。此外,如果您的底层 stdio 实现不这样做,您可以使用 posix_memalign()_aligned_malloc() 提供您自己的缓冲区。

编辑:消除评论中的一些混乱

您正在使用扇区大小为 512、FILE *f; 的设备。你 fseek() 偏移 37。f 的位置已更新,但未在设备上进行搜索。你fread() 500 字节。 lseek() 以 0 的偏移量调用。512 个字节被读入f 的缓冲区。字节 37 到 512 被复制到您提供的缓冲区。 lseek() 以 512 的偏移量调用。读取 512 个字节,并将您期望的剩余 463 个字节复制到您传递给 fread() 的缓冲区中。如果您现在将fread() 设为一个字节,那么只需将其从f 的现有缓冲区中复制出来,而不会影响设备。

【讨论】:

  • 但您仍然必须使用字节数作为参数发出 fread/fwrite,对吗?那并不能解决这个问题。正如您所说,他首先必须确定他的驱动器的扇区大小,然后读取 n*sector_size 数据以读取第 n 个扇区。如果我在这里错了,请纠正我。
  • 你错了。 :P 关键是在幕后 stdio 执行缓冲,包括读取大小为 s 的整个块,然后只提供您要求的部分。
  • 完全正确,例如第一个 1 字节 fread 实际上不会读取由 setvbuf 设置的字节(代码中的扇区大小),但它只会向应用程序提供一个字节。因此,要读取完整的扇区,应用程序必须执行扇区大小的 fread。现在要确定确切的扇区大小,应用程序首先必须发出一个 ioctl (BLKSSZGET)。我想这就是 Macroideal 想要的,以便他可以按扇区进行 I/O。
  • 似乎我无法逐字节读取,也许系统或驱动设备被设计为扇区对齐......我们没有特权改变这个特性......即使有驱动程序...... .thanx 都一样
【解决方案2】:

在这里,我假设您使用 linux 作为平台。在 linux 上,每个设备都是一个文件。您将在 /dev 中找到一个设备条目。这意味着您可以在该驱动器上使用读/写来执行 I/O,例如您可以通过打开 /dev/sda1 直接打开您的硬盘分区并读取 n 个字节。

使用以下代码确定驱动器的确切扇区大小(代码中没有错误处理)。如果要读取第 n 个扇区,则只需从打开的设备中读取 n*sector_size 字节。希望这有助于解决您的问题。

    #include <stdio.h>
    #include <linux/fs.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>

    #define SECTOR_NO 10 /*read 10th sector*/

    int main()
    {
            int sector_size;
            char *buf;
            int n = SECTOR_NO;

            int fd = open("/dev/sda1", O_RDONLY|O_NONBLOCK);
            ioctl(fd, BLKSSZGET, &sector_size);
            printf("%d\n", sector_size);
            lseek(fd, n*sector_size, SEEK_SET);

            buf = malloc(sector_size);
            read(fd, buf, sector_size);

            return 0;
    }

【讨论】:

    猜你喜欢
    • 2021-06-19
    • 2018-10-16
    • 2017-04-10
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    • 2012-08-18
    • 2020-02-22
    • 2011-03-20
    相关资源
    最近更新 更多