Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
磁盘写入在C中不能与malloc一起工作_C_Io_Disk - Fatal编程技术网

磁盘写入在C中不能与malloc一起工作

磁盘写入在C中不能与malloc一起工作,c,io,disk,C,Io,Disk,我确实使用C代码写入磁盘 首先,我尝试使用malloc,发现write不起作用(write返回-1): 然后我用这个改变了第二行,它成功了: void *buff; posix_memalign(&buff,512,512); 但是,当我将lseek偏移量更改为1时:lseek(fd,1,SEEK_SET),写入再次无法工作 首先,为什么malloc不工作 然后,我知道在我的例子中,posix_memalign保证内存对齐的起始地址必须是512的倍数。但是,内存对齐和写入不应该是一个单

我确实使用C代码写入磁盘

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

然后我用这个改变了第二行,它成功了:

void *buff;
posix_memalign(&buff,512,512);
但是,当我将lseek偏移量更改为1时:
lseek(fd,1,SEEK_SET),写入再次无法工作

首先,为什么malloc不工作


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

可能文档中没有说明,但很有可能需要对齐块设备的写入和读取,并且整个块都要成功(这可以解释为什么在第一个和最后一个情况下会失败,但在第二个情况下不会)。如果您使用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
本身可能会失败(您可能希望对此可能性采取一些措施)。

来自Linux手册页的open(2):

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

以及:

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


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

是否检查了
malloc
的返回,
write
?当我说
write
不起作用时,它意味着retval=-1。我已经检查过malloc没有返回null@在linux中,以
/dev
开头的AMEYCAUNAME是特殊的块设备。如果您指定一个实际文件,会发生什么情况?@Vincentius:那么您应该选中
errno
。这是一个完整的示例吗?因为一个新的
malloc()
ed缓冲区有未初始化的字节,并且如果您在没有写入之前尝试从中读取,则行为是未定义的。因此,特别是,任何东西或任何东西都不能写入该文件。也许你想使用
calloc
来获得一个满是零字节的缓冲区?谢谢你的想法。实际上,我在代码中也有类似的错误处理,我只是展示了核心,以显示重要部分并避免长篇大论。@Vincentius如果你有这样的错误处理,它可能会告诉你更多关于发生了什么。
peror()
告诉你什么?啊,太好了,它回答了大部分问题。顺便说一句,我仍然不清楚的是,为什么
posix_memalign
可以代替
malloc
?因为它提供了这种对齐的内存o
posix_memalign
malloc
类似,只是它分配的内存是对齐的。也就是说,它从一个内存地址开始,这个地址是第二个参数的倍数。好的,就像在这个答案的第二个引号中所说的,那么malloc不起作用,因为它的分配可能不存在于“逻辑块大小的倍数-偏移量”中,而posix_memalign将保证这个条件。是吗?@Vincentius:是的,没错。malloc只保证以允许您存储和访问任何数据类型的方式对齐内存,在不同的处理器体系结构上,这可能意味着4或8的倍数,甚至没有。
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;
}