磁盘写入不适用于C中的malloc

时间:2015-10-29 06:32:52

标签: c io disk

我使用C代码写入磁盘。

首先我尝试使用malloc并发现写入不起作用(写入返回-1):

fd = open('/dev/sdb', O_DIRECT | O_SYNC | O_RDWR);
void *buff = malloc(512);
lseek(fd, 0, SEEK_SET);
write(fd, buff, 512);

然后我用这个更改了第二行,它起作用了:

void *buff;
posix_memalign(&buff,512,512);

然而,当我将lseek偏移量更改为1:lseek(fd, 1, SEEK_SET);时,写入不再起作用。

首先,为什么没有malloc工作?

然后,我知道在我的情况下,posix_memalign保证内存对齐的起始地址必须是512的倍数。但是,内存对齐和写入不应该是一个单独的进程吗?那么为什么我不能写任何我想要的偏移?

2 个答案:

答案 0 :(得分:5)

从Linux手册页中打开(2):

  

O_DIRECT标志可能会对长度施加对齐限制   和用户空间缓冲区的地址以及I / O的文件偏移量。

  

在Linux 2.4下,传输大小和用户的对齐方式   缓冲区和文件偏移量必须都是逻辑块的倍数   文件系统的大小。在Linux 2.6下,对齐到512字节   边界就足够了。

O_DIRECT的意思是“尝试最小化I / O与此文件之间的缓存效果”,如果我理解正确,则意味着内核应该直接从用户空间缓冲区复制,因此也许要求更严格地对齐数据。

答案 1 :(得分:2)

也许文档没有说,但很可能需要对块设备进行写入和读取以及整个块成功(这可以解释为什么在第一个和最后一个案例中出现故障的原因)但不是在第二个)。如果你使用linux,open(2)的文档基本上就是这样说的:

  

O_DIRECT标志可能会对长度和长度施加对齐限制   用户空间缓冲区的地址和I / O的文件偏移量。在Linux中   对齐限制因文件系统和内核版本而异   可能完全没有。然而,有 -          实际上没有文件系统独立的接口,应用程序可以发现给定文件或文件系统的这些限制。一些   例如,文件系统提供了自己的接口   xfsctl(3)中的XFS_IOC_DIOINFO操作。

您的代码显示缺少错误处理。代码中的每一行都包含可能失败的函数,openlseekwrite也会在errno中报告错误原因。因此,通过某种错误处理,它将是:

fd = open('/dev/sdb', O_DIRECT | O_SYNC | O_RDWR);

if( fd == -1 ) {
    perror("open failed");
    return;
}

void *buff = malloc(512);

if( !buff ) {
    printf("malloc failed");
    return;
}

if( lseek(fd, 0, SEEK_SET) == (off_t)-1 ) {
    perror("lseek failed");
    free(buff);
    return;
}

if( write(fd, buff, 512) == -1 ) {
    perror("write failed");
    free(buff);
    return;
}

在这种情况下,你至少会对出了什么问题得到更详细的解释。在这种情况下,我怀疑你从write电话中获得了EIO(输入/输出错误)。

请注意,上述内容可能并非完整的错误处理,因为perrorprintf本身可能会失败(您可能希望对此可能做些什么)。