简体   繁体   English

如何直接写入具有4GB以上数据的USB驱动器?

[英]How do I write directly to a USB drive with over 4GB data?

I have a research project where I need to be able to fill a USB stick with a known pattern of data directly, no files or file system. 我有一个研究项目,我需要能够直接用已知的数据模式(没有文件或文件系统)填充USB记忆棒。 My goal is to fill a drive from top to bottom with my pattern; 我的目标是用样式填充从上到下的驱动器; I have written a program for writing to /dev/sd* but it is slow and does not work if the drive is over 4GB in size. 我已经编写了一个用于写入/ dev / sd *的程序,但是它很慢,并且如果驱动器的大小超过4GB,则无法正常工作。 The writing will stop at offset oxFFFFFFF or 2^32. 写入将在偏移oxFFFFFFF或2 ^ 32处停止。

My code 我的密码

#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;

} 

I realize my program isn't great and is dangerous as I could wipe out a HDD, but all I am looking for at this point is tips to make this work on drives over 4GB and hopefully make the process faster. 我意识到我的程序不是很好,而且很危险,因为我可能会擦掉HDD,但是目前我想要的是在4GB以上的驱动器上完成这项工作的技巧,并希望可以使过程更快。 It will have limited use by myself and possibly another. 我自己和其他人可能会限制使用它。

A push in the right direction would be appreciated. 朝正确方向的推动将不胜感激。

Use size_t for bytesize in memory, and off_t for file offsets on disk. 使用size_t表示内存中的字节大小,使用off_t表示磁盘上的文件偏移量。 For general integers, use intptr_t in your program. 对于一般整数,请在程序中使用intptr_t So your for loops should start with for (intptr_t i=0; 因此,您的for循环应以for (intptr_t i=0;

And don't write in small blocks of 512 bytes, but in something bigger (but a power of two), eg 16384 bytes. 并且不要以512字节的小块来写,而要以更大的(但为2的幂)来写,例如16384字节。

If your program still does not work, use strace to find out the failing syscalls. 如果您的程序仍然无法运行,请使用strace找出失败的系统调用。 And use perror in your program on failure of any syscall. 并且在任何系统调用失败时在程序中使用perror

your code is 'effectively' writing to a hard disk that is larger than a 32bit int. 您的代码正在“有效地”写入大于32位int的硬盘。

Therefore, I suggest paying attention to the built-in USB interface on the USB stick, where you can specify which logical block to write and so forth. 因此,我建议您注意USB记忆棒上的内置USB接口,您可以在其中指定要写入的逻辑块等等。

Note; 注意; USB sticks with built-in load levelling will NOT write sequentially on the media, irregardless of what you pass to it in the way of commands. 内置负载均衡的USB记忆棒不会按顺序写入媒体,无论您通过命令传递给它的内容如何。 However, most USB sticks can be told to format and so forth so you might be able to use that feature. 但是,大多数USB记忆棒都可以格式化等等,因此您可以使用该功能。 Or you could use some utility for setting disk sectors to all (for instance) 0's Just be carefully to not overwrite the sector/block formatting information. 或者,您可以使用一些实用程序将磁盘扇区设置为全0(例如)。小心不要覆盖扇区/块格式化信息。

You can make off_t into a 64 bit value by placing this before any of the includes. 您可以通过将off_t放在任何include之前将其设置为64位值。

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

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

This also apparently also causes the read() , write() , fread() , fwrite() , etc. calls manage a 64-bit file offset internally. 显然,这也会导致read()write()fread()fwrite()等调用在内部管理64位文件偏移。 I have used it for a similar purpose when porting to Linux. 移植到Linux时,我已将其用于类似目的。

Ditto the advice not to use such a small buffer. 同样建议不要使用这么小的缓冲区。 Make it 64K (65,536 bytes) to greatly improve performance. 将其设置为64K(65,536字节)可大大提高性能。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM