【发布时间】:2015-12-09 15:24:42
【问题描述】:
写入带有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 不是直接的,这是我需要的)。
有人知道为什么会这样吗?如果O_DIRECT 没有在Android 中实现,那么它应该在open() 失败,而不是在write();所以我一定是做错了什么!
谢谢 -LD
【问题讨论】:
-
使用直接 IO 的 IO 操作也可以有大小限制。一个字节可能不起作用。
-
对于
O_DIRECT,I/O 大小需要与磁盘文件块大小相同(通常为 4096 字节)并在页面上对齐(地址可被 4096 整除)。您可能希望将setbuf()函数视为可行的替代方案。calloc()唯一的特殊之处是将分配的内存设置为全 0x00。 malloc、calloc 和 realloc 都返回一个指向内存块的指针,这些地址可以被底层硬件总线大小整除。 (32 位或 64 位) -
@user3629249 - Linux 上直接 IO 的限制比这复杂得多。例如,ext4 文件系统似乎允许未对齐的直接 IO。请参阅lxr.free-electrons.com/source/fs/ext4/file.c#L102 我还注意到,在最近的 Linux 版本中,对仅页面或块大小 IO 操作的要求已经放宽,这是有道理的,因为很少有文件是这些值的精确倍数。尽管存在明显的用例(例如,流式传输永远不需要在任何页面缓存中的大量数据),但在 Linux 上使用直接 IO 还是有些难以预测。
标签: android c android-ndk java-native-interface invalid-argument