系统调用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的位置开始映射 */
执行原理(步骤)
<其中,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.