读取二进制文件而不将其缓存在卷块缓存中

问题描述

较旧(现已不推荐使用)的macOS文件系统API提供了用于读取未缓冲文件的标志。

我寻求一种现代化的方法来实现相同目的,以便可以将文件的数据读取到内存中,而不必将其不必要地缓存在内存中的其他位置(例如卷缓存)。

例如,在我的测试中,使用fread进行读取并首先调用setvbuf (fp,NULL,_IONBF,0)并没有取得预期的效果。我正在寻找其他低级函数,这些函数可以让我读入准备好的内存缓冲区,并且可以避免缓冲整个数据。

背景

我正在编写文件搜索程序。它会读取大量的文件内容(许多GB),否则用户将不会使用它们。将所有这些数据缓存在卷缓存中将是一种浪费,因为无论如何它们很快就会再次被进一步的读取清除。这也可能导致清除用户或系统实际使用的文件数据,从而导致更多的缓存丢失。

因此,我应该能够告诉系统我不需要缓存的文件数据。集群边界所需的少量缓存不是问题。我将许多大块的内容简短地读取到内存中以进行搜索,不需要缓存。

解决方法

两个建议:

  • 使用read()系统调用代替stdio。
  • 使用fcntl()F_NOCACHE选项禁用数据缓存。

在Swift中,这类似于(为简洁起见,省略了错误检查):

import Foundation

let path = "/path/to/file"
let fd = open(path,O_RDONLY)
fcntl(fd,F_NOCACHE,1)

var buffer = Data(count: 1024 * 1024)
buffer.withUnsafeMutableBytes { ptr in
    let amount = read(fd,ptr.baseAddress,ptr.count)
}

close(fd)