我尝试通过本机方法访问android中的文件,但是在调用读取或写入函数后得到"无效参数"。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: %sn", 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: %sn", strerror(errno));
}
(*env)->ReleaseByteArrayElements(env, data_ptr, body, 0);
return ret;
}
编辑:
如果我使用open(filePath, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
错误就会消失。但是我想使用O_DIRECT忽略缓存和缓冲区来直接访问硬件。
O_DIRECT
要求写入是底层文件系统的倍数:
O_DIRECT
标志可能会对长度和 用户空间缓冲区的地址和 I/O 的文件偏移量。 在 Linux 中对齐‐ 限制因文件系统和内核版本而异,可能不存在 完全。 但是,目前没有独立于文件系统的接口 让应用程序发现给定文件的这些限制,或者 文件系统。 一些文件系统为此提供了自己的接口, 例如xfsctl(3)
中的XFS_IOC_DIOINFO
操作。在 Linux 2.4 下,传输大小、用户缓冲区和 文件偏移量必须全部是 的逻辑块大小的倍数 文件系统。 在 Linux 2.6 下,对齐 512 字节边界就足够了。
GetByteArrayElements
不提供此类保证。它仅返回元素基元数组的地址 - 在本例中,这是字节数组中字节的地址。这些由 Java 内存管理器分配。您要么必须复制字节(破坏O_DIRECT
的对象),删除O_DIRECT
或使用其他策略来分配内存(例如自己分配mmap(..., MAP_ANON)
)。