简体   繁体   English

写入错误:使用O_DIRECT打开文件时,参数无效

[英]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: 我做了两件事:

  1. Found the filesystem hosting my file's block size using stat() and accessing the st_blksize attribute. 使用stat()并访问st_blksize属性找到托管我文件块大小的文件系统。
  2. Allocated 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.

相关问题 如何以Java方式直接从设备读取/写入文件(如O_DIRECT标志的效果)? - How to directly read/write file from and to device (like effect of O_DIRECT flag) in Java way? 如何使用Android KitKat在外部SD卡上使用O_DIRECT或O_SYNC - How can I use O_DIRECT or O_SYNC on an external SD card with Android KitKat 写:无效的参数 - write: Invalid argument Firebase 存储错误:无效参数:“_File”实例 - Firebase Storage error : Invalid argument: Instance of '_File' 单击sdcard中的图像时出现“无效文件”错误 - “Invalid File” error when the images in sdcard are clicked Android Gradle错误:参数无效 - Android Gradle error : Invalid argument 尝试将对象写入libgdx中的文件时出错 - Error when trying to write an object to a file in libgdx 从 php base64 字符串解码时,Node Js 从 base64 写入文件结果错误“无效的 JPEG 结构:两个 SOF 标记” - Node Js write File from base64 result error "Invalid JPEG structure : two SOF Marker" when decode from php base64 string 尝试从我的应用程序中的服务器下载文件时收到无效的参数错误 - Getting an invalid argument error while trying to download file from a server in my app 运行时出现Flutter项目,显示错误无效参数:源不得为null - Flutter project when run showing Error Invalid argument(s): The source must not be null
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM