[英]Write error: Invalid argument, when file is opened with O_DIRECT
it is very important to me to write to a file with the O_DIRECT
flag. 对我来说,使用O_DIRECT
标志写入文件非常重要。
This is how I open the file: 这是我打开文件的方式:
//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;
}
I know about O_DIRECT's alignment restrictions. 我知道O_DIRECT的对齐限制。 This is why I initialize my buffer with calloc: 这就是为什么我用calloc初始化缓冲区的原因:
char *buff = (char *) calloc((size_t) 1,sizeof(char));
if(write(fd,buff,(size_t)1)<1) {
//Error logging
free(buff);
return -1;
}
And I get the write: Invalid argument
error. 我得到这样write: Invalid argument
错误。 I even tried to use more extreme measures such as memalign and posix_memalign, but had issues with them (memalign got stuck, and posix_memalign is missing for the ARM processor). 我什至尝试使用更极端的措施,例如memalign和posix_memalign,但是它们存在问题(memalign卡住了,ARM处理器缺少posix_memalign)。
When I comment out the O_DIRECT
flag, everything works as it should (but I/O is not direct, which is what I need). 当我注释掉O_DIRECT
标志时,一切都会正常工作(但是I / O不是直接的,这是我所需要的)。
Anyone has any insight as to why this is happening? 任何人都知道为什么会这样吗? If O_DIRECT
was not implemented in Android, then it should've failed at open()
, not at write()
; 如果O_DIRECT
不是在Android中实现的,那么它应该在open()
而不是write()
处失败; so I must be doing something wrong! 所以我一定做错了!
Thanks -LD 谢谢-LD
Calloc will not align the memory good enough in this case. 在这种情况下,Calloc将无法充分对齐内存。 Allocate more memory than you need, and round it up to the next 4k or so page. 分配超出您需要的内存,并将其向上舍入到下一个4k左右的页面。 Also read the notes below in the manpage for open() with O_DIRECT. 另请阅读O_DIRECT的open()手册中的以下注释。
I solved it (with your guidance)- and wanted to post my solution in case anyone in the future has similar problems. 我(在您的指导下)解决了该问题,并希望发布我的解决方案,以防将来有人遇到类似问题。
The trick was that with the O_DIRECT
flag you need to align both the memory address and your buffer to the filesystem's block size (or at least, block size worked for me; sector didn't). 诀窍在于,需要使用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;
}
I did two main things: 我做了两件事:
stat()
and accessing the st_blksize
attribute. 使用stat()
并访问st_blksize
属性找到托管我文件块大小的文件系统。 align
more bytes than I need. 分配align
比我需要更多的字节。 I then added those extra align
bytes to the pointer address so that masking off the bits to the lower block size alignment wouldn't leave me with less memory allocated than I wanted. 然后,我将那些额外的align
字节添加到指针地址,以便将这些位屏蔽为较小的块大小对齐,不会给我分配的内存少于我想要的。 Then of course you AND the bits with the mask (created by flipping the bits of align
which is blksize
-1), and voila- your buffer is blksize
-aligned. 然后,当然,您将这些位与掩码(通过翻转align
的位blksize
-1创建)相结合,瞧,您的缓冲区是blksize
。 Also note that the amount you write also has to be aligned to block size (at least in my case). 还要注意,您写的数量也必须与块大小对齐(至少在我的情况下)。
-LD -LD
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.