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

Lon*_*uck 3 c java-native-interface android invalid-argument android-ndk

写入文件对我来说非常重要 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;
}
Run Code Online (Sandbox Code Playgroud)

我知道 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;
}
Run Code Online (Sandbox Code Playgroud)

我得到了 write: Invalid argument错误。我什至尝试使用更极端的措施,例如 memalign 和 posix_memalign,但遇到了问题(memalign 卡住了,并且 ARM 处理器缺少 posix_memalign)。

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

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

谢谢-LD

Lon*_*uck 6

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

诀窍是使用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;
}
Run Code Online (Sandbox Code Playgroud)

我主要做了两件事:

  1. 使用stat()和访问st_blksize属性找到了托管我的文件块大小的文件系统。
  2. 分配的align字节数比我需要的多。然后我将这些额外的align字节添加到指针地址,以便将位屏蔽到较低的块大小对齐不会让我分配的内存比我想要的少。然后当然你用掩码和位(通过翻转位alignblksize-1 创建),瞧——你的缓冲区是对齐的blksize

另请注意,您写入的数量也必须与块大小对齐(至少在我的情况下)。

-LD