Write error: Invalid argument, when file is opened with O_DIRECT
Write error: Invalid argument, when file is opened with O_DIRECT
使用 O_DIRECT
标志写入文件对我来说非常重要。
这是我打开文件的方式:
//Open the file
int fd;
if((fd = open(inFilepath, O_WRONLY | O_CREAT |O_SYNC |O_DIRECT,S_IRUSR|S_IWUSR))<0) {
//Error handling
return;
}
我知道 O_DIRECT 的对齐限制。这就是我使用 calloc:
初始化缓冲区的原因
char *buff = (char *) calloc((size_t) 1,sizeof(char));
if(write(fd,buff,(size_t)1)<1) {
//Error logging
free(buff);
return -1;
}
我收到 write: Invalid argument
错误。
我什至尝试使用更极端的措施,例如 memalign 和 posix_memalign,但遇到了问题(memalign 卡住了,ARM 处理器缺少 posix_memalign)。
当我注释掉 O_DIRECT
标志时,一切正常(但 I/O 不是直接的,这正是我需要的)。
有人知道为什么会这样吗?如果 O_DIRECT
没有在 Android 中实现,那么它应该在 open()
中失败,而不是在 write()
中;所以我一定是做错了什么!
谢谢
-LD
在这种情况下,Calloc 将无法很好地对齐内存。分配比您需要更多的内存,并将其四舍五入到下一个 4k 左右的页面。另请阅读 open() 使用 O_DIRECT.
联机帮助页中的以下注释
我解决了它(在您的指导下)- 并且想 post 我的解决方案以防将来有人遇到类似问题。
诀窍在于,使用 O_DIRECT
标志,您需要将内存地址和缓冲区与文件系统的块大小对齐(或者至少,块大小对我有用;扇区没有)。
struct stat fstat;
stat(filepath, &fstat);
int blksize = (int)fstat.st_blksize;
int align = blksize-1;
const char *buff = (char *) malloc((int)blksize+align);
buff = (char *)(((uintptr_t)buff+align)&~((uintptr_t)align));
if(write(fd,buff,(size_t)blksize)<1) {
//Error handling
free((char *)buff);
return -1;
}
我主要做了两件事:
- 使用
stat()
并访问 st_blksize
属性找到托管我的文件块大小的文件系统。
- 分配的
align
字节比我需要的多。然后我将这些额外的 align
字节添加到指针地址,以便将这些位屏蔽为较低的块大小对齐不会让我分配的内存比我想要的少。然后当然你和带有掩码的位(通过翻转 align
的位创建,即 blksize
-1),瞧 - 你的缓冲区是 blksize
-aligned.
另请注意,您写入的数量也必须与块大小对齐(至少在我的情况下)。
-LD
使用 O_DIRECT
标志写入文件对我来说非常重要。
这是我打开文件的方式:
//Open the file
int fd;
if((fd = open(inFilepath, O_WRONLY | O_CREAT |O_SYNC |O_DIRECT,S_IRUSR|S_IWUSR))<0) {
//Error handling
return;
}
我知道 O_DIRECT 的对齐限制。这就是我使用 calloc:
初始化缓冲区的原因char *buff = (char *) calloc((size_t) 1,sizeof(char));
if(write(fd,buff,(size_t)1)<1) {
//Error logging
free(buff);
return -1;
}
我收到 write: Invalid argument
错误。
我什至尝试使用更极端的措施,例如 memalign 和 posix_memalign,但遇到了问题(memalign 卡住了,ARM 处理器缺少 posix_memalign)。
当我注释掉 O_DIRECT
标志时,一切正常(但 I/O 不是直接的,这正是我需要的)。
有人知道为什么会这样吗?如果 O_DIRECT
没有在 Android 中实现,那么它应该在 open()
中失败,而不是在 write()
中;所以我一定是做错了什么!
谢谢 -LD
在这种情况下,Calloc 将无法很好地对齐内存。分配比您需要更多的内存,并将其四舍五入到下一个 4k 左右的页面。另请阅读 open() 使用 O_DIRECT.
联机帮助页中的以下注释我解决了它(在您的指导下)- 并且想 post 我的解决方案以防将来有人遇到类似问题。
诀窍在于,使用 O_DIRECT
标志,您需要将内存地址和缓冲区与文件系统的块大小对齐(或者至少,块大小对我有用;扇区没有)。
struct stat fstat;
stat(filepath, &fstat);
int blksize = (int)fstat.st_blksize;
int align = blksize-1;
const char *buff = (char *) malloc((int)blksize+align);
buff = (char *)(((uintptr_t)buff+align)&~((uintptr_t)align));
if(write(fd,buff,(size_t)blksize)<1) {
//Error handling
free((char *)buff);
return -1;
}
我主要做了两件事:
- 使用
stat()
并访问st_blksize
属性找到托管我的文件块大小的文件系统。 - 分配的
align
字节比我需要的多。然后我将这些额外的align
字节添加到指针地址,以便将这些位屏蔽为较低的块大小对齐不会让我分配的内存比我想要的少。然后当然你和带有掩码的位(通过翻转align
的位创建,即blksize
-1),瞧 - 你的缓冲区是blksize
-aligned.
另请注意,您写入的数量也必须与块大小对齐(至少在我的情况下)。
-LD