写入错误:使用O_DIRECT打开文件时,参数无效 [英] Write error: Invalid argument, when file is opened with O_DIRECT

查看:786
本文介绍了写入错误:使用O_DIRECT打开文件时,参数无效的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

O_DIRECT标志写入文件对我来说非常重要.

it is very important to me to write to a file with the O_DIRECT flag.

这是我打开文件的方式:

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;
}

我知道O_DIRECT的对齐限制.这就是为什么我用calloc初始化缓冲区的原因:

I know about O_DIRECT's alignment restrictions. This is why I initialize my buffer with 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).

And I get the write: Invalid argument error. 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).

当我注释掉O_DIRECT标志时,一切都会正常进行(但是I/O不是直接的,这正是我所需要的).

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不是在Android中实现的,则它应该在open()而不是在write()处失败;所以我一定做错了!

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(); so I must be doing something wrong!

谢谢 -LD

推荐答案

我已解决(根据您的指导)-并希望发布我的解决方案,以防将来有人遇到类似问题.

I solved it (with your guidance)- and wanted to post my solution in case anyone in the future has similar problems.

诀窍在于,使用O_DIRECT标志,您需要将内存地址和缓冲区都与文件系统的块大小对齐(或者至少对我来说块大小有效;扇区无效).

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).

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;
}

我做了两件事:

  1. 使用stat()并访问st_blksize属性找到了托管我的文件块大小的文件系统.
  2. 分配的align个字节超出了我的需要.然后,我将那些额外的align字节添加到指针地址,以便将这些位屏蔽为较低的块大小对齐方式,不会给我分配的内存少于我想要的.然后,当然,您可以将这些位与掩码(通过翻转align的位,即blksize -1的位而创建)进行对,并确保缓冲区是blksize对齐的.
  1. Found the filesystem hosting my file's block size using stat() and accessing the st_blksize attribute.
  2. Allocated align more bytes than I need. 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. 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.

还请注意,您写的数量还必须与块大小保持一致(至少在我的情况下如此).

Also note that the amount you write also has to be aligned to block size (at least in my case).

-LD

这篇关于写入错误:使用O_DIRECT打开文件时,参数无效的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆