系统调用mmap详解整理

概述

  • 将磁盘文件映射到进程的虚拟地址空间, 通过对这段内存的读取和修改,来实现对文件的读取和修改,而不需要再调用read,write等操作。

接口与形参解析

 void * /*返回开辟的虚拟地址空间的首地址*/
     mmap(void *addr, /*指定映射的起始地址, 建议设为NULL*/
          size_t len, /* 映射到内存的文件长度*/
          int prot, /* 映射区的保护方式 */
          /* 
           * PROT_EXEC: 映射区可被执行
           * PROT_READ: 映射区可被读取
           * PROT_WRITE: 映射区可被写入
          */
          int flags, 
          /*
           * MAP_SHARED: 写入映射区的数据会写回磁盘文化部, 
                         且允许其他映射该文件的进程共享。
           * MAP_PRIVATE:对映射区的写入操作会产生一个映射区的复制(copy-on-write), 
                         对此区域所做的修改不会写回原文件。
           */
          int fd, /* 由open返回的文件描述符, 代表要映射的文件 */ 
          off_t offset); /* 从文件中offset的位置开始映射 */
     

执行原理(步骤)

clipboard.png

<其中,pgd记录了第一级页表的首地址>

  • 在虚拟地址空间中为系统调用mmap创建vm_area_struct
  • 通过文件描述符fd, 找到内核中该文件对应的文件结构体(struct file)
  • 通过该文件的文件结构体, 调用file.file_operations.mmap函数, 实现了文件fd和内存虚拟地址的映射关系
//不同于系统调用mmap函数
int mmap(struct file* filp, struct vm_area_struct* vma);
  • 需要指出的是,当前磁盘中文件内容并没有读入相应的内存地址空间中,需要通过缺页中断机制,将文件内容读入到内存中。

特性

缺陷

  • 通过mmap无法追加文件内容
  • mmap减少了内核态到用户态的数据拷贝,但是当写操作过多时,从page cache写回磁盘的操作无法避免(其耗时远远大于内存的相互拷贝),这大大减少了mmap的作用。

相关函数

munmap

int munmap( void * addr, size_t len ) 

msync

int msync( void *addr, size_t len, int flags )

疑惑点:flags: MS_INVALIDATE
REF1
FEF2

mlock / munlock

int mlock(void* addr, size_t len);
int munlock(const void *addr, size_t len);

延伸

direct_io

man 2 open

  • Try to minimize cache effects of the I/O to and from this file. In general this will degrade performance, but it is useful in special situations, such as when applications do their own caching. File I/O is done directly to/from user-space buffers. The O_DIRECT flag on its own makes an effort to transfer data synchronously, but does not give the guarantees of the O_SYNC flag that data and necessary metadata are transferred. To guarantee synchronous I/O, O_SYNC must be used in addition to O_DIRECT. See NOTES below for further discussion.

参考资料