我使用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的倍数。但是,内存对齐和写入不应该是一个单独的进程吗?那么为什么我不能写任何我想要的偏移?
答案 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操作。
您的代码显示缺少错误处理。代码中的每一行都包含可能失败的函数,open
,lseek
和write
也会在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(输入/输出错误)。
请注意,上述内容可能并非完整的错误处理,因为perror
和printf
本身可能会失败(您可能希望对此可能做些什么)。