2

我尝试通过本机方法访问 android 中的文件,但在调用读取或写入函数后出现“无效参数”。data_ptr512 字节对齐,并在 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忽略缓存和缓冲区来直接访问硬件。

4

1 回答 1

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或使用其他一些策略来分配内存(例如自己使用 分配它们mmap(..., MAP_ANON))。

于 2015-01-27T11:16:16.633 回答