6.3.11.7. mmap

内存映射函数mmap负责把文件内容映射到进程的虚拟内存空间,通过对这段内存的读取和修改,来实现对文件的读取和修改,而不需要再调用read/write等操作。

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

其中addr指定映射的起始地址, 通常设为NULL, 由内核指定。 length表示映射到内存区域的大小。

prot映射区的保护方式,可以是:

  • PROT_EXEC: 映射区可被执行

  • PROT_READ: 映射区可被读取

  • PROT_WRITE: 映射区可被写入

  • PROT_NONE: 映射区域不能存取

flags表示映射区的特性,可以是:

  • MAP_FIXED: 如果参数 start 所指的地址无法成功建立映射时,则放弃映射,不对地址做修正,通常不鼓励用此flag。

  • MAP_SHARED: 对映射区域的写入数据会复制回文件内,而且允许其他映射该文件的进程共享。

  • MAP_PRIVATE: 对映射区域的写入操作会产生一个映射文件的复制,即私有的写入时复制(copy-on-write)对此区域作的任何修改都不会写回原来的文件内容。

  • MAP_ANONYMOUS: 建立匿名映射。此时会忽略参数fd,不涉及文件,而且映射区域无法和其他进程共享。

  • MAP_DENYWRITE: 只允许对映射区域的写入操作,其他对文件直接写入的操作将会被拒绝。

  • MAP_LOCKED: 将映射区域锁定住,这表示该区域不会被置换(swap)。

fd是由open返回的文件描述符, 代表要映射的文件,如果使用匿名内存映射时,fd设为-1。当系统不支持匿名内存映射时,则可以使用fopen打开/dev/zero文件。

offset表示以文件开始处的偏移量,必须是分页大小的整数倍,通常为0,表示从文件头开始映射。

若映射成功则返回映射区的内存起始地址,否则返回MAP_FAILED(-1),错误原因存于errno 中。

具体的错误代码如下:

  • EBADF: 参数fd 不是有效的文件描述词

  • EACCES: 存取权限有误。如果是MAP_PRIVATE 情况下文件必须可读,使用MAP_SHARED则要有PROT_WRITE以及该文件要能写入

  • EINVAL: 参数start、length 或offset有一个不合法

  • EAGAIN: 文件被锁住,或是有太多内存被锁住

  • ENOMEM: 内存不足

解除映射可使用 munmap 函数,原型为

int munmap(void *start, size_t length);