2015-10-29 22 views
2

我用C代码写入磁盘。磁盘写入不能在malloc中使用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的倍数。但是,内存对齐和写入不应该是一个单独的过程吗?那么为什么我不能写任何我想要的偏移?

+1

您是否检查过'malloc','write'的返回? – ameyCU

+0

当我说'写'不起作用时,这意味着retval = -1。我已经检查过malloc没有返回null。 @ameyCU – Algorithman

+0

在linux中以'/ dev'开头的名字是特殊的块设备。如果你指定一个实际的文件,会发生什么? – Mike

回答

5

从Linux手册页开放(2):

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

和:

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

O_DIRECT的意思是“尽量减少I/O,并从该文件的缓存效应”,如果我理解正确的话就意味着内核应该从用户空间缓冲区直接复制,因此可能需要更严格的数据对齐。

+0

好啊,它回答了大部分问题。顺便说一句,我还不清楚的是,为什么'posix_memalign'工作而不是'malloc'? – Algorithman

+1

呃,因为它给你这个对齐的内存? :o –

+0

'posix_memalign'就像'malloc',只是它分配的内存是对齐的。也就是说,它从一个内存地址开始,它是第二个参数的倍数。 –

2

也许文档没有说,但是很有可能写入和读取/从块设备读取需要对齐并且整个块成功(这可以解释为什么您在第一个和最后一个失败但不在第二个)。如果你使用Linux的开放文档(2)基本上是这样说:

的O_DIRECT标志可以在长度和用户空间的缓冲区 地址和文件I/O的偏移强加对齐限制。在Linux 中,对齐限制因文件系统和内核版本而异,并且 可能完全不存在。但是,存在一个应用程序发现给定文件或文件系统的这些限制的文件系统无关接口。一些 文件系统提供它们自己的接口来执行此操作,例如 xfsctl(3)中的XFS_IOC_DIOINFO操作。

您的代码显示缺少错误处理。代码中的每行都包含可能会失败的函数,并且open,lseekwrite也会报告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本身可能会失败(并且您可能想要对此做一些处理)。

+0

谢谢你的想法。其实我在代码里面有类似的错误处理,我只是展示了髓子来显示重要的部分,并避免了长时间的后处理。 – Algorithman

+0

@Vincentius如果你有这样的错误处理,它可能会告诉你更多关于发生了什么。 “perror()”告诉你什么? – glglgl