参考
函数定义
//用户空间函数
void *mmap(void *start, size_t length, int prot, int flags, int fd, off_t offset);
//内核空间函数
int mmap(struct file *filp, struct vm_area_struct *vma)
task_struct结构是linux上pcb的实现,用户空间函数mmap创建vm_area_struct数据结构,映射到进程的虚拟地址空间
内核空间函数mmap建立页表,将文件磁盘地址和虚拟空间地址进行映射
linux加载可执行程序(ELF)就是使用的mmap
mmap和read/write的区别
read/write是系统调用函数,用于内核态和用户态之间的数据读写。文件磁盘的数据–>buffer/cache–>用户空间
而mmap函数本身只是建立了一种进程虚拟地址空间到文件磁盘的映射关系,实际访问映射的这块地址时,才发生缺页异常,由操作系统将文件内容复制到内存的一个区域。文件磁盘的数据->内存中的页框(用户空间可见)
性能差异主要是系统调用,额外的复制与页错误的差异。
mmap与malloc
1、brk是将数据段(.data)的最高地址指针_edata往高地址推;
2、mmap是在进程的虚拟地址空间中(堆和栈中间,称为文件映射区域的地方)找一块空闲的虚拟内存。
brk/mmap各有优略
brk会造成一定程度的内存碎片问题,指针移到高位,地位已经释放的虚拟内存
一定时间内未使用.但已经释放的虚拟内存
不会立即返回给OS,有一定的缓存作用
mmap会造成多次缺页异常(size/4k),但是申请的虚拟内存
是在栈和堆中间的区域,可以随时释放(munmap)
mallopt() could set parameters to control behavior of malloc(), and there is a parameter named M_MMAP_THRESHOLD, in general:
- 如果请求的内存少于它,brk()将使用;
- 如果请求的内存大于或等于它,mmap()则将使用;
brk/mmap实现
图片来自:
十三 Linux内存管理之vma/malloc/mmap
sys_brk
sys_mmap
brk/sbrk
int brk(void *addr);
brk() sets the end of the data segment to the value specified by addr, when that value is reasonable, the system has enough memory, and the process does not exceed its maximum data size.
On success, brk() returns zero. On error, -1 is returned, and errno is set to ENOMEM.
void *sbrk(intptr_t increment);
sbrk() increments the program’s data space by increment bytes. Calling sbrk() with an increment of 0 can be used to find the current location of the program break.
On success, sbrk() returns the previous program break. (If the break was increased, then this value is a pointer to the start of the newly allocated memory). On error, (void *) -1 is returned, and errno is set to ENOMEM.
要注意的问题
1 映射文件的5000个字节实际映射到内存中的是2页(2*4k),5000-8191之间在内存中值是0
2 文件5000字节,映射15000字节。实际内存中是2页(2*4k),8192-15000之间不可读(sigbus)
3 文件初始大小为0,映射10004K的大小,只要访问ptr指针前,扩展文件大小n字节(n<10004k),则0-n之间的空间是可以读写并更新到文件的
free命令
[root@localhost ~]# free
total used free shared buffers cached
Mem: 3869020 3439104 429916 61128 764 400284
-/+ buffers/cache: 3038056 830964
Swap: 4079612 0 4079612
第一行的used/free就是使用和剩余的实际内存,buffers/cached是内存中缓冲磁盘文件的区域,随时可能被换掉的
第二行的used/free是第一行中实际使用内存减去buffers/cached后剩余的空间下的[used/free used = 3439104 - 764 - 400284 = 3038056]
swap是内存中没被当前使用的部分缓冲到磁盘中,作为back log的区域,在使用的时候再加载回内存