程序员

mmap 函数:原理与使用(含代码)

2017-08-11  本文已影响903人  找不到工作

参考

中文资料
英文资料
使用场景

介绍

除了标准的文件 IO,例如 open, read, write,内核还提供接口允许应用将文件 map 到内存。使得内存中的一个字节与文件中的一个字节一一对应。

mmap 原理

使用方法

函数原型为:

#include <sys/mman.h>

void * mmap (void *addr,
             size_t len,
             int prot,
             int flags,
             int fd,
             off_t offset);

如果失败,mmap 函数将返回 MAP_FAILED

页面对齐

内存拥有独立权限的最小单位就是页。因此,mmap 的最小单位也是页。addroffset 参数都必须页对齐,len 会被 roundup。被 roundup 的多余的内存会以 \0 填充。对这一部分的写入操作不会影响文件。我们可以通过如下方式获取本机的页面大小:

#include <unistd.h>

long page_size = sysconf(_SC_PAGESIZE);

代码实现

因为项目需求并发写入,为了提高性能,实现了一个可以并行写入的mmap。
具体代码可以查看我的Github

遇到的问题

  1. 写入时发生错误
bus error(core dump)

stackoverflow 大佬的原话:

You are creating a new zero sized file, you can't extend the file size with mmap. You'll get a bus error when you try to write outside the content of the file.

因此使用 lseek 先把文件扩展到需要的大小。

  // solve the bus error problem:
  // we should allocate space for the file first.
  lseek(fd, size_lim_-1, SEEK_SET);
  write(fd,"",1);
  1. 文件权限设置
int fd = open(file_path_.c_str(), O_RDWR | O_CREAT | O_TRUNC, 0644);

打开的时候忘了加 0644 设置权限。

  1. 文件大小

由于文件最初利用 lseek 扩张了一次,中间有大量的'\0'段。导致文件在验证中出错,而且打开缓慢。

// resize the file to actual size
truncate(file_path_.c_str(), cur_pos_.load());

在析构函数中增加 truncate 解决。

上一篇 下一篇

猜你喜欢

热点阅读