写入错误:使用O_DIRECT

时间:2015-12-09 15:24:43

标签: android c android-ndk java-native-interface invalid-argument

使用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不是直接的,这就是我需要的)。

任何人都知道为什么会发生这种情况?如果Android中未实现O_DIRECT,那么它应该在open()失败,而不是write();所以我一定做错了!

由于 -LD

2 个答案:

答案 0 :(得分:2)

在这种情况下,Calloc不会将内存对齐得足够好。分配比您需要的更多内存,并将其四舍五入到下一个4k左右的页面。另请阅读使用O_DIRECT打开()的联机帮助页中的以下注释。

答案 1 :(得分:1)

我解决了它(在你的指导下) - 并希望发布我的解决方案,以防将来有人遇到类似的问题。

诀窍是,使用O_DIRECT标志,您需要将内存地址和缓冲区与文件系统的块大小对齐(或者至少,块大小对我有效;扇区没有&#39 ; 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 - 对齐。
  3. 另请注意,您编写的金额也必须与块大小对齐(至少在我的情况下)。

    -LD