目录
mmap 系统调用
Linux 支持通过 mmap系统调用 将文件映射到内存中,然后我们读写映射之后的虚拟内存就可以了,不用再用 write/read 系统调用读写文件。系统会将我们对内存读写 flush 到文件中,flush 是由系统自动执行的,我们也可以调用 Flush 强制刷盘。
void *mmap(void addr[.length], size_t length, int prot, int flags,
int fd, off_t offset);
addr 表示映射内存的起始地址(可填0,由系统给我们指定),length 表示映射的内存大小。
支持的 prot 保护标志有:1)PROT_EXEC: 映射的 pages 可被执行;2)PROT_READ: 读;3)PROT_WRITE: 写;4)PROT_NONE: 不能被访问。
支持的 flags 有:1)MAP_SHARED: 对内存的读写能被其他进程看到,并且能被刷回磁盘;2)MAP_PRIVATE: 其他进程看不到,不能被刷回磁盘;3)MAP_ANON: 映射匿名内存,用于子进程之间通信。
在 Go 中使用 mmap
在 Go 可以使用 syscall 系统调用。但是有一个第三方的 package https://github.com/edsrzf/mmap-go 可以帮我们做这个事情。一个例子:
package main
import (
"github.com/edsrzf/mmap-go"
"os"
)
func main() {
f, _ := os.OpenFile("./file", os.O_RDWR, 0644)
f.WriteString("hello, world")
defer f.Close()
mmap, _ := mmap.Map(f, mmap.RDWR, 0)
defer mmap.Unmap()
mmap[0] = 'X' // 覆盖文件中的第一个字节
mmap.Flush() // 强制刷盘
}
映射的文件不能是空的,否则会报 invalid arguments 错误。所以一开始我们写入了一个字符串 “hello,world”。在代码执行之后,我们再看文件中的内容变成 “Xello, world”
lr90@mo mmap % cat file
Xello, world%
参考
https://brunocalza.me/discovering-and-exploring-mmap-using-go/