strerror(errno) return "Invalid argument" 当调用 read() & write() 时

strerror(errno) return "Invalid argument" when call read() & write()

我尝试通过本机方法访问 android 中的文件,但在调用读取或写入函数后我得到了 "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 忽略缓存和缓冲区直接访问硬件。

O_DIRECT 要求写入是底层文件系统的倍数:

The O_DIRECT flag may impose alignment restrictions on the length and address of user-space buffers and the file offset of I/Os. In Linux align‐ ment restrictions vary by filesystem and kernel version and might be absent entirely. However there is currently no filesystem-independent interface for an application to discover these restrictions for a given file or filesystem. Some filesystems provide their own interfaces for doing so, for example the XFS_IOC_DIOINFO operation in xfsctl(3).

Under Linux 2.4, transfer sizes, and the alignment of the user buffer and the file offset must all be multiples of the logical block size of the filesystem. Under Linux 2.6, alignment to 512-byte boundaries suffices.

GetByteArrayElements 不提供此类保证。它只是 returns 基本元素数组的基地址 - 在这种情况下,这是字节数组中字节的地址。这些由 Java 内存管理器分配。您要么必须复制字节(击败 O_DIRECT 的对象),删除 O_DIRECT 或使用其他一些策略来分配内存(例如使用 mmap(..., MAP_ANON) 自己分配它们) .