【发布时间】:2016-01-10 18:06:18
【问题描述】:
假设文件Foo.txt的内容如下。
Foo Bar Bar Foo
考虑以下短程序。
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)
}
当我们运行上面的程序时,我们没有收到任何错误,这是正确的行为。
现在,我将syscall.Open 行修改为以下内容。
fd, err := syscall.Open("Foo.txt", syscall.O_RDONLY | syscall.O_SYNC | syscall.O_DIRECT, 0)
当我再次运行程序时,我得到以下(不希望出现的)输出。
Failed on read: invalid argument
如何正确传递open man page 指定的标志syscall.O_SYNC 和syscall.O_DIRECT 以跳过文件系统缓存?
请注意,我直接使用syscall 文件接口而不是os 文件接口,因为我找不到将这些标志传递给os 提供的函数的方法,但我愿意接受以下解决方案使用os,前提是它们可以正常工作以禁用读取时的文件系统缓存。
还要注意,我在 Ubuntu 14.04 上运行,ext4 作为我的文件系统。
更新:我尝试在下面的代码中使用@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)
}
}
输出如下
Error on read: unexpected EOF
【问题讨论】:
-
您是否尝试过在 go(可能是 C)中使用这些确切的参数来执行 open-read-close?从我在手册页上可以看到,O_SYNC 只影响写入操作,而 O_DIRECT 需要用户空间中某种精确大小的(?)缓冲区,这可能是一个特定于 go 的问题,但我首先尝试让它工作C...
-
@mrd0ll4r,实际上我在 C 端运行了this program 并得到了相同的错误
EINVAL。所以不,它不是特定的。
标签: linux caching go system-calls