我尝试通过native方法访问android中的文件,但是在调用read或write函数后我得到了“Invalid argument”。 data_ptr 与512字节对齐,并在java中声明为字节数组。
JNIEXPORT jint JNICALL
Java_com_aa_bb_NativeRead(JNIEnv* env, jobject clazz, jbyteArray data_ptr, jint length){
int ret=0;
jsize len = (*env)->GetArrayLength(env, data_ptr);
jbyte *body = (*env)->GetByteArrayElements(env, data_ptr, 0);
fd = open(filePath, O_CREAT | O_RDWR | O_DIRECT | O_SYNC, S_IRUSR | S_IWUSR);
ret = read(fd, body, length);
if(ret<0){
LOGE("errno: %s\n", strerror(errno));
}
(*env)->ReleaseByteArrayElements(env, data_ptr, body, 0);
return ret;
}
JNIEXPORT jint JNICALL
Java_com_aa_bb_NativeWrite(JNIEnv* env, jobject clazz, jbyteArray data_ptr, jint length){
int ret=0;
jsize len = (*env)->GetArrayLength(env, data_ptr);
jbyte *body = (*env)->GetByteArrayElements(env, data_ptr, 0);
fd = open(filePath, O_CREAT | O_RDWR | O_DIRECT | O_SYNC, S_IRUSR | S_IWUSR);
ret = write(fd, body, length);
if(ret<0){
LOGE("errno: %s\n", strerror(errno));
}
(*env)->ReleaseByteArrayElements(env, data_ptr, body, 0);
return ret;
}
修改:
如果我使用open(filePath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
,则错误消失。但我想使用 O_DIRECT 来忽略缓存和缓冲区来直接访问硬件。
答案 0 :(得分:1)
O_DIRECT
要求写入是底层文件系统的倍数:
O_DIRECT
标志可能会对长度和长度施加对齐限制 用户空间缓冲区的地址和I / O的文件偏移量。在Linux中对齐 - 限制因文件系统和内核版本而异,可能不存在 完全。但是,目前没有与文件系统无关的接口 为应用程序发现给定文件的这些限制或 文件系统。一些文件系统提供了自己的接口, 例如XFS_IOC_DIOINFO
中的xfsctl(3)
操作。在Linux 2.4下,传输大小,以及用户缓冲区的对齐方式 文件偏移量必须都是逻辑块大小的倍数 文件系统。在Linux 2.6下,对齐到512字节边界就足够了。
GetByteArrayElements
不提供此类保证。它只返回原始元素数组的基地址 - 在这种情况下,它是字节数组中字节的地址。这些由Java内存管理器分配。您必须复制字节(取消O_DIRECT
的对象),删除O_DIRECT
或使用其他策略来分配内存(例如使用{{1}自行分配它们})。