TheRiver | blog

You have reached the world's edge, none but devils play past here

0%

mmap共享内存

参考

brk/mmap

认真分析mmap:是什么 为什么 怎么用

Linux内存分配小结–malloc、brk、mmap

十三 Linux内存管理之vma/malloc/mmap

linux mmap 详解

函数定义

//用户空间函数
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.png

task_struct结构是linux上pcb的实现,用户空间函数mmap创建vm_area_struct数据结构,映射到进程的虚拟地址空间
内核空间函数mmap建立页表,将文件磁盘地址和虚拟空间地址进行映射

linux加载可执行程序(ELF)就是使用的mmap

mmap和read/write的区别

read/write是系统调用函数,用于内核态和用户态之间的数据读写。文件磁盘的数据–>buffer/cache–>用户空间
而mmap函数本身只是建立了一种进程虚拟地址空间到文件磁盘的映射关系,实际访问映射的这块地址时,才发生缺页异常,由操作系统将文件内容复制到内存的一个区域。文件磁盘的数据->内存中的页框(用户空间可见)

性能差异主要是系统调用,额外的复制与页错误的差异。

进程地址空间2.jpg

mmap与malloc

brk-mmap在虚拟地址空间中.jpg

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

malloc.png


sys_mmap

mmap.png


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

mmap_情形1.png

2 文件5000字节,映射15000字节。实际内存中是2页(2*4k),8192-15000之间不可读(sigbus)

mmap_情形2.png

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的区域,在使用的时候再加载回内存

ending

tumblr_p48vtapTM81sfie3io1_1280.jpg

----------- ending -----------