如何直接写入超过4GB数据的USB驱动器?

时间:2015-02-15 23:40:42

标签: c linux usb

我有一个研究项目,我需要能够直接用已知的数据模式填充USB记忆棒,没有文件或文件系统。我的目标是用我的模式从上到下填充驱动器;我编写了一个写入/ dev / sd *的程序,但它很慢,如果驱动器的大小超过4GB则不起作用。写入将在偏移量0xFFFFFFF或2 ^ 32处停止。

我的代码

#include <stdio.h>
#include <fcntl.h>
#include <linux/fs.h>
#include <errno.h>
#include <inttypes.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <ctype.h>



int main(int argc, char **argv)
{
    int fd;
    uint64_t numbytes=0;
    char response[4];
    long int nblocks = 0; // number of blocks up to 4GB


    int error;
    size_t fill_length = 8;
    char buf[512];
    char fill[] = "ABCDEFGH";

    printf("\n\n");
    fd = open(argv[1], O_RDWR);
    if(error = ioctl(fd, BLKGETSIZE64, &numbytes) != 0){
        printf("Failed to read block device, ioctl returned: %i\n", error);
        exit(0);
    }
    if (numbytes > 8589934592){ // Exit if more than 8 GB drive
        printf("Drive is too large.l\n");
        exit(0);
    }
    printf("Number of bytes: %lu, i.e. %.3f GiB\n", numbytes,
    (double)numbytes / (1024 * 1024 * 1024));
    nblocks = numbytes / 512;
    printf("Number of blocks on device: %lu\n", nblocks);

    strcpy(buf, fill); // fills with pattern, one time
    for(int i =0; i < (512 - fill_length); i += fill_length){ // Fills up the rest of the buffer
        strcat(buf, fill); // with the pattern to be repeated.
    } // 512 is the default & smallest block size
    printf("buf is:\n%s\n", buf);

    printf("\n*** The device at %s will be completely overwritten ***\n", argv[1]);
    printf("\nAre you sure you want to proceed? (Type:<Ctrl>-C to exit)\n");

    // printf("\n nblocks: %lu", nblocks);
    fgets(response, 3, stdin);
    printf("writting to: %s\n", argv[1]);

    for (int i = 0; i <= nblocks; i++)
    {
        write(fd, buf, 512);
    }


    printf("Closing...\n");
    close(fd);
    printf("Closed.\n");
    return 0;

} 

我意识到我的程序不是很好而且很危险,因为我可能会擦除硬盘驱动器,但此时我正在寻找的是在超过4GB的驱动器上进行此工作的提示,并希望使该过程更快。它将被我自己和另一个人限制使用。

赞赏正确的方向。

3 个答案:

答案 0 :(得分:0)

对内存中的bytesize使用size_t,对磁盘上的文件偏移使用off_t。对于常规整数,请在程序中使用intptr_t。因此,for循环应以for (intptr_t i=0;

开头

并且不要写入512字节的小块,而是写入更大的(但是2的幂),例如16384字节。

如果您的程序仍无效,请使用strace查找失败的系统调用。如果系统调用失败,请在程序中使用perror

答案 1 :(得分:0)

您的代码是有效的&#39;写入大于32位int的硬盘。

因此,我建议您注意USB记忆棒上的内置USB接口,您可以在其中指定要写入的逻辑块等等。

请注意;内置负载均衡的USB记忆棒不会在介质上顺序写入,无论您以命令的方式传递给它。但是,大多数USB记忆棒可以被告知要格式化等等,这样您就可以使用该功能。或者您可以使用一些实用程序将磁盘扇区设置为全部(例如)0&#39; s小心不要覆盖扇区/块格式化信息。

答案 2 :(得分:0)

您可以通过将off_t置于任何包含之前将其设置为64位值。

#define _FILE_OFFSET_BITS 64    // so off_t is 64 bit, see man fseeko

#include <stdio.h>
#include <unistd.h>
etc. ...

这显然也会导致read()write()fread()fwrite()等调用内部管理64位文件偏移。移植到Linux时,我将它用于类似的目的。

建议不要使用这么小的缓冲区。使其为64K(65,536字节)以大大提高性能。