strerror(errno)在调用read()&时返回“无效参数”。写()

时间:2015-01-27 09:22:06

标签: android c linux android-ndk fcntl

我尝试通过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 来忽略缓存和缓冲区来直接访问硬件。

1 个答案:

答案 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}自行分配它们})。