我使用的是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系统?
答案 0 :(得分:0)
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);