未定义参考' posix_fadvise'

时间:2015-03-30 13:29:55

标签: android caching android-ndk filesystems

我使用的是Android NDK版本:r9c

我需要posix_fadvise()建议操作系统不要缓存文件,我打开这个文件是为了绕过缓存并强制I / O访问存储设备,当我需要读/写这个文件时。

我没有使用O_DIRECT标志打开文件的原因O_DIRECT在不同设备上存在兼容问题。

我曾尝试直接调用__NR_arm_fadvise64_64但没有使用,并且NDK r9c中未定义__NR_fadvise

下面是示例代码,系统调用read不会触发I / O访问,这意味着页面缓存仍然具有此文件的记录。

ret= fdatasync(fd);
 ret = syscall(__NR_arm_fadvise64_64, fd, 0, 0, POSIX_FADV_DONTNEED);
 if(ret !=0){
    LOGE("syscall __NR_arm_fadvise64_64 errno: %s\n", strerror(errno));
}
ret = read(fd, buff, page_size);
if(ret<0){
    LOGE("read errno: %s\n", strerror(errno));
    return -1;
} 

是否有其他方法可以绕过缓存或如何让posix_fadvise函数调用到android系统?

2 个答案:

答案 0 :(得分:0)

Android 5.0(NDK)支持

posix_fadvise。

__ NR_arm_fadvise64_64也找不到。

答案 1 :(得分:0)

声明:

// for posix_fadvise64()
#if __ANDROID_API__ >= 21

// supported from Android NDK Native API level 21
#include <fcntl.h>

#else // __ANDROID_API__ >= 21

// for syscall()
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/fadvise.h>

int posix_fadvise64(int fd, off64_t offset, off64_t len, int advice);

#endif // __ANDROID_API__ >= 21

定义:

#if __ANDROID_API__ < 21

int posix_fadvise64(int fd, off64_t offset, off64_t len, int advice)
{
    // from man SYSCALL(2):
    /*
     * Architecture-specific requirements:
     * Each architecture ABI has its own requirements on how system call
     * arguments are passed to the kernel.  For system calls that have a
     * glibc wrapper (e.g., most system calls), glibc handles the details of
     * copying arguments to the right registers in a manner suitable for the
     * architecture.  However, when using syscall() to make a system call,
     * the caller might need to handle architecture-dependent details; this
     * requirement is most commonly encountered on certain 32-bit
     * architectures.
     *
     * For example, on the ARM architecture Embedded ABI (EABI), a 64-bit
     * value (e.g., long long) must be aligned to an even register pair.
     * Thus, using syscall() instead of the wrapper provided by glibc, the
     * readahead() system call would be invoked as follows on the ARM
     * architecture with the EABI:
     *
     *     syscall(SYS_readahead, fd, 0,
     *             (unsigned int) (offset >> 32),
     *             (unsigned int) (offset & 0xFFFFFFFF),
     *             count);
     *
     * Since the offset argument is 64 bits, and the first argument (fd) is
     * passed in r0, the caller must manually split and align the 64-bit
     * value so that it is passed in the r2/r3 register pair.  That means
     * inserting a dummy value into r1 (the second argument of 0).
     *
     * Similar issues can occur on MIPS with the O32 ABI, on PowerPC with
     * the 32-bit ABI, and on Xtensa.
     *
     * The affected system calls are fadvise64_64(2), ftruncate64(2),
     * posix_fadvise(2), pread64(2), pwrite64(2), readahead(2),
     * sync_file_range(2), and truncate64(2).
     */

    // from man POSIX_FADVISE(2):
    /*
     * Architecture-specific variants:
     * Some architectures require 64-bit arguments to be aligned in a
     * suitable pair of registers (see syscall(2) for further detail).  On
     * such architectures, the call signature of posix_fadvise() shown in
     * the SYNOPSIS would force a register to be wasted as padding between
     * the fd and offset arguments.  Therefore, these architectures define a
     * version of the system call that orders the arguments suitably, but is
     * otherwise exactly the same as posix_fadvise().
     *
     * For example, since Linux 2.6.14, ARM has the following system call:
     *
     *     long arm_fadvise64_64(int fd, int advice,
     *                           loff_t offset, loff_t len);
     *
     * These architecture-specific details are generally hidden from
     * applications by the glibc posix_fadvise() wrapper function, which
     * invokes the appropriate architecture-specific system call.
     */

#if defined(__arm__)
    // from "Procedure Call Standard for the ARM Architecture" (ARM IHI 0042E)
    /*
     * 5.1.1.1 Handling values larger than 32 bits:
     * Fundamental types larger than 32 bits may be passed as parameters to,
     * or returned as the result of, function calls. When these types are in
     * core registers the following rules apply:
     *
     *      A double-word sized type is passed in two consecutive registers
     *      (e.g., r0 and r1, or r2 and r3). The content of the registers is
     *      as if the value had been loaded from memory representation with
     *      a single LDM instruction.
     *
     *      A 128-bit containerized vector is passed in four consecutive
     *      registers. The content of the registers is as if the value had
     *      been loaded from memory with a single LDM instruction.
     */
    return syscall(
            __NR_arm_fadvise64_64,
            fd,
            advice,
#if defined(__BYTE_ORDER) && __BYTE_ORDER == __BIG_ENDIAN
            // big-endian: high word in r2, low word in r3
            (unsigned int)(offset >> 32),
            (unsigned int)(offset & 0xFFFFFFFF),
            // big-endian: high word in r4, low word in r5
            (unsigned int)(len >> 32),
            (unsigned int)(len & 0xFFFFFFFF));
#elif defined(__BYTE_ORDER) && __BYTE_ORDER == __LITTLE_ENDIAN
            // little-endian: low word in r2, high word in r3
            (unsigned int)(offset & 0xFFFFFFFF),
            (unsigned int)(offset >> 32),
            // little-endian: low word in r4, high word in r5
            (unsigned int)(len & 0xFFFFFFFF),
            (unsigned int)(len >> 32));
#else
#error "posix_fadvise64() unknown endianess for arch armeabi"
#endif
#elif defined(__aarch64__)
#error "posix_fadvise64() need to implement for arch arm64-v8a"
#elif defined(__i386__)
#error "posix_fadvise64() need to implement for arch x86"
#elif defined(__x86_64__)
#error "posix_fadvise64() need to implement for arch x86_64"
#elif defined(__mips__)
#error "posix_fadvise64() need to implement for arch mips"
#elif defined(__mips64)
#error "posix_fadvise64() need to implement for arch mips64"
#else // unknown
#error "posix_fadvise64() need to implement for arch unknown"
#endif
}

#endif // __ANDROID_API__ < 21

调用:

posix_fadvise64(fd, 0, 0, POSIX_FADV_DONTNEED);