在Golang中读取文件时如何跳过文件系统缓存?

mer*_*011 8 linux caching system-calls go

假设文件的内容Foo.txt如下.

Foo Bar Bar Foo
Run Code Online (Sandbox Code Playgroud)

考虑以下简短程序.

package main

import "syscall"
import "fmt"


func main() {
    fd, err := syscall.Open("Foo.txt", syscall.O_RDONLY, 0)
    if err != nil {
        fmt.Println("Failed on open: ", err)
    }
    data := make([]byte, 100)
    _, err = syscall.Read(fd, data)
    if err != nil {
        fmt.Println("Failed on read: ", err)
    }
    syscall.Close(fd)
}
Run Code Online (Sandbox Code Playgroud)

当我们运行上面的程序时,我们没有错误,这是正确的行为.

现在,我将该syscall.Open行修改为以下内容.

fd, err := syscall.Open("Foo.txt", syscall.O_RDONLY | syscall.O_SYNC | syscall.O_DIRECT, 0)
Run Code Online (Sandbox Code Playgroud)

当我再次运行程序时,我得到以下(不合需要的)输出.

Failed on read:  invalid argument
Run Code Online (Sandbox Code Playgroud)

我怎样才能正确地传递标志syscall.O_SYNCsyscall.O_DIRECT由指定的open手册页跳过文件系统缓存?

请注意,我syscall直接使用文件接口而不是os文件接口,因为我找不到将这些标志传递给提供的函数的方法os,但是我对使用os它们正常工作以禁用文件系统缓存的解决方案持开放态度读取.

还要注意,我正在上Ubuntu 14.04ext4我的文件系统.


更新:我尝试在下面的代码中使用@Nick Craig-Wood的软件包.

package main

import "io"
import "github.com/ncw/directio" 
import "os"
import "fmt"


func main() {
    in, err := directio.OpenFile("Foo.txt", os.O_RDONLY, 0666)
    if err != nil {
        fmt.Println("Error on open: ", err)
    }

    block := directio.AlignedBlock(directio.BlockSize)
    _, err = io.ReadFull(in, block)
    if err != nil {
        fmt.Println("Error on read: ", err)
    }
}
Run Code Online (Sandbox Code Playgroud)

输出如下

Error on read:  unexpected EOF
Run Code Online (Sandbox Code Playgroud)

Nic*_*ood 5

您可以享受我为此目的制作的直接套餐.

从网站

这是Go语言的库,可以在Go的所有支持的操作系统下使用Direct IO(openbsd和plan9除外).

直接IO在磁盘上执行IO而不在OS中缓冲数据.当您正在阅读或编写大量您不想填充操作系统缓存的数据时,它非常有用.

请参阅此处获取包文档

http://go.pkgdoc.org/github.com/ncw/directio


Rhy*_*man 2

open手册页的“注释”下:

\n\n
\n

O_DIRECT 标志可以对用户空间缓冲区的长度和地址以及 I/O 的文件偏移施加对齐限制。在 Linux 中,对齐限制因文件系统和内核版本而异,并且可能完全不存在。

\n
\n\n

因此,您可能会遇到内存或文件偏移量的对齐问题,或者您的缓冲区大小可能是“错误的”。对齐方式和尺寸应该是什么并不明显。手册页继续:

\n\n
\n

然而,当前没有独立于文件系统的接口供应用程序发现给定文件或文件系统的这些限制。

\n
\n\n

就连 Linus 也以他一贯低调的方式发表了自己的看法:

\n\n
\n

“O_DIRECT 一直让我感到不安的是,整个界面都很愚蠢,很可能是由一只精神错乱的猴子用一些严重的精神控制物质设计的。” \xe2\x80\x94Linus

\n
\n\n

祝你好运!

\n\n

ps 摸黑刺:为什么不读取512字节?

\n