转自:http://blog.chinaunix.net/uid-24774106-id-365941.html?utm_source=jiancool

mmap这个领域有很多优秀的书籍 博文介绍,本文做的事情只是将这些东西串起来,以更好懂的方式讲一下。

本文绝非原创,从很多博文及书籍中copy的东西。写成文章,也为了防止自己遗忘。
OK  我们开始
1 mmap的应用
mmap的本质是,把一个文件或者posix 共享内存区队形映射到调用进程的地址空间。
三个目的
a)使用普通文件提供内存映射IO
b)使用特殊文件提供匿名映射IO
c)使用shm_open 以提供无亲缘关系的进程间的posix共享内存区
mmap系统调用并不是完全为了用于共享内存而设计的。它本身提供了不同于一般对普通文件的访问方式,进程可以像读写内存一样对普通文件的操作。而Posix或系统V的共享内存IPC则纯粹用于共享目的,当然mmap()实现共享内存也是其主要应用之一。
mmap系统调用使得进程之间通过映射同一个普通文件实现共享内存。普通文件被映射到进程地址空间后,进程可以像访问普通内存一样对文件进行访问,不必再调用read(),write()等操作。
#include
void *mmap(void *addr ,size_t len,int prot,int flags,int fd,off_t offset)
如果成功返回被映射区域的起始地址。
下面挨个解释每个参数的含义
第一个参数 是个地址,指向用户地址空间的一个地址,当然我们的函数就是为了寻找一个可用的地址空间,将文件描述符fd 对应的文件从偏移量 offset 开始,copy文件的len个字符进入用户地址空间。将起始地址返回。为什么第一个参数就是用户地址空间的指针呢?这不是骑驴找驴吗?
这个addr参数可以NULL,这种情况我们比较容易理解。当addr不为NULL的时候,这其实是个建议查找地址,用来指导内存区定位的线索,是个用户指定的经验值。
还记得进程虚拟地址空间之arch_get_unmapped_area中有 如下代码:
1) 如果用户打上了MAP_FIXED标志,表示用户王八吃秤砣,铁了心要addr这个地址作为映射起始地址,
     OK,直接把 addr 返回给这个二杆子用户。
2)如果没打上 MAP_FIXED标志,则首先在建议地址addr附近寻找合适的区域。
3)addr 为NULL,方法进程虚拟地址空间之arch_get_unmapped_area中有详细介绍。
从可移植性考虑,一般不能指定MAP_FIXED这个标记。
if (flags & MAP_FIXED)
return addr;
if (addr) {
addr = PAGE_ALIGN(addr);
vma = find_vma(mm, addr);
if (TASK_SIZE - len >= addr &&
(!vma || addr + len <= vma->vm_start))
return addr;
}
第二个参数len,没啥好说的,干脆和fd、offset 一起介绍了。 这个含义是将fd对应的文件,从offset位置开始,长为len的内容映射到内存地址空间
需要解释的是fd,存在一种情况叫匿名映射,所谓匿名映射,表示不存在fd这么个真实的文件。
1 BSD 提供匿名映射的办法是fd =-1,同时 flag 指定为MAP_SHARE|MAP_ANON(hy:MAP_PRIVATE)。
ptr = mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,
MAP_SHARED|MAP_ANON,-1,0);
2 SVR4 提供匿名映射的办法是 open  /dev/zero设备文件,把返回的文件描述符,作为mmap的fd参数。
fd = open("/dev/zero",O_RDWR);
跑一下题,/dev/zero 是一个特殊的文件,当你读它的时候,它会提供无限的空字符(NULL, ASCII NUL, 0x00)
一个作用是用它作为源,产生一个特定大小的空白文件。下面的命令产生出一个bean 文件在当前目录下。
大小为1M。
dd if=/dev/zero of=bean count=1024 bs=1024
OK,言归正传,第三个参数 prot,这个是负责保护作用的
PROT_READ 数据可读
PROT_WRITE 数据可写
PROT_EXEC 数据可执行
PROT_NONE 数据不可访问。
第四个参数 flags
MAP_SHARED 变动是共享的,换言之,如果映射的内存区域的数据变化了,磁盘上的文件也得跟着变
MAP_PRIVATE 变动是私有的,换言之,映射的内存区域 爱怎么折腾怎么折腾,fd对应的文件不变化
MAP_FIXED 这个就是前面提到的二杆子参数,非addr这个地址不可。。
OK 映射完成后,fd对应的文件可以close ,没啥影响。

OK,学习完了mmap,来个直观的感受:
#include  
#include
#include
#include
#include
#define FILE_LENGTH 0x400
int main(int argc, char *argv[])
{
int fd;
void *map_memory;
/* Open a file to be mapped. */
fd = open("/tmp/shared_file", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
lseek(fd, FILE_LENGTH-1, SEEK_SET);
write(fd, "", 1);
lseek(fd, 0, SEEK_SET);
/* Create map memory. */
map_memory = mmap(0, FILE_LENGTH, PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
/* Write to mapped memory. */
if (strlen(argv[1]) < FILE_LENGTH)
sprintf((char *)map_memory, "%s", argv[1]);
sleep(100);
exit(0);
}
# ./mmap_write hello&
[1] 14667
# cat /proc/14667/maps
08048000-08049000 r-xp 00000000 16:42 213757     /tmp/mmap_write
08049000-0804a000 rw-p 00000000 16:42 213757     /tmp/mmap_write
40000000-40015000 r-xp 00000000 16:42 12828674   /lib/ld-2.3.2.so
40015000-40016000 rw-p 00014000 16:42 12828674   /lib/ld-2.3.2.so
40016000-40017000 rw-p 00000000 00:00 0
40017000-40018000 -w-s 00000000 16:42 213753     /tmp/shared_file
42000000-4212e000 r-xp 00000000 16:42 13991938   /lib/tls/libc-2.3.2.so
4212e000-42131000 rw-p 0012e000 16:42 13991938   /lib/tls/libc-2.3.2.so
42131000-42133000 rw-p 00000000 00:00 0
bfffe000-c0000000 rwxp fffff000 00:00 0
我们看到 /tmp/shared_file 文件已经映射到内存中取了,占用空间0x40018000 - 0x40017000 = 4K。FILE_LENGTH  大小是0x400 = 1K,但是映射的分配是以页面为单位分配的,即最小分配4K

mmap 系统调用 的使用相关推荐

  1. 【Linux 内核 内存管理】Linux 内核堆内存管理 ② ( 动态分配堆内存方式 | brk 系统调用 | mmap 系统调用 | brk 系统调用源码介绍 )

    文章目录 一.Linux 系统 动态分配堆内存 方式 二.brk 系统调用 动态分配堆内存 一.Linux 系统 动态分配堆内存 方式 Linux 系统中 , 提供了 222 种方式 进行 " ...

  2. 内存映射(mmap系统调用)

    映射虚拟内存-->物理内存/Swap/文件 文件映射到内存,内存访问取代IO访问 可以映射同一个文件以(进程)共享内存 Linux进程虚拟地址空间---(分成)-->虚拟内存区 虚拟内存区 ...

  3. linux mmap系统调用

    brk/mmap linux 提供了两个比较重要的系统调用brk 和mmap,用于向内核申请相应用户空间,内核会根据系统运行状态判定是否申请新的VMA来管理新申请的用户空间,brk和mmap在整个系统 ...

  4. Linux内存管理 brk(),mmap()系统调用源码分析2:brk()的内存释放流程

    Linux brk(),mmap()系统调用源码分析 brk()的内存释放流程 荣涛 2021年4月30日 内核版本:linux-5.10.13 注释版代码:https://github.com/Rt ...

  5. 【Linux 内核 内存管理】mmap 系统调用源码分析 ④ ( do_mmap 函数执行流程 | do_mmap 函数源码 )

    文章目录 一.do_mmap 函数执行流程 二.do_mmap 函数源码 调用 mmap 系统调用 , 先检查 " 偏移 " 是否是 " 内存页大小 " 的 & ...

  6. Linux brk(),mmap()系统调用源码分析3:brk()的内存申请流程

    Linux brk(),mmap()系统调用源码分析 brk()的内存申请流程 荣涛 2021年4月30日 内核版本:linux-5.10.13 注释版代码:https://github.com/Rt ...

  7. Linux内存管理 brk(),mmap()系统调用源码分析1:基础部分

    Linux内存管理 brk(),mmap(),munmap()系统调用源码分析 基础部分 荣涛 2021年4月30日 内核版本:linux-5.10.13 注释版代码:https://github.c ...

  8. mmap系统调用使用-学习笔记

    文章目录 1. mmap函数参数说明 2. mmap父子进程通信 3. 匿名映射 4. mmap基本使用示例 5. mmap使用常见问题 6. 总结 1. mmap函数参数说明 头文件:#includ ...

  9. 内存分配的原理__进程分配内存有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)

    如何查看进程发生缺页中断的次数? 用ps -o majflt,minflt -C program命令查看. majflt代表major fault,中文名叫大错误,minflt代表minor faul ...

  10. 【Linux 内核 内存管理】内存管理架构 ④ ( 内存分配系统调用过程 | 用户层 malloc free | 系统调用层 brk mmap | 内核层 kmalloc | 内存管理流程 )

    文章目录 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) 二.内存管理流程 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) " 堆内存 " ...

最新文章

  1. 修改Activity响应音量控制键修改的音频流
  2. latex 插图解释_大O符号-只需插图和视频即可解释
  3. 64位IIS(IIS6/IIS7)上跑Asp + Jet.Oledb的设置要点
  4. 下面哪个字段是http请求中必须具备的_HTTP协议及其工作原理介绍
  5. 企业项目开发--切分配置文件
  6. springmvc的执行流程_springmvc执行流程
  7. oracle or 循环 查询,Oracle的循环和Corsor
  8. rem、px、em之间的区别以及网页响应式设计写法
  9. android drawable转bitmap_Android 内存泄漏优化汇总
  10. 这本京东断货王的Python神书,刷爆整个编程圈!| 测评
  11. 谷歌浏览器获取主题图片
  12. 数字乡村大数据可视化平台建设方案 智慧乡村 美丽乡村 智慧农村
  13. A 股历年三大财务报表 API 接口
  14. python求不规则图形面积_python计算不规则图形面积算法
  15. Latex PDF文档目录乱码
  16. matlab识别中国象棋棋盘,c – 使用OpenCV在棋盘中检测中国象棋棋子
  17. 弦理论能成为新的万物理论吗?
  18. 干货!如何快速拥有自己的商城APP
  19. c#中屏蔽窗体关闭的消息
  20. k8s client-go 出现错误net/http: TLS handshake timeout

热门文章

  1. 汉字注音符号学习(引用自维基百科)
  2. NYOJ 822 画图
  3. getnumdevices.c setgetdevicetype例程
  4. f-admin——基于Laravel框架开发的基础权限后台系统
  5. 数据结构与算法之递归和分治思想
  6. BZOJ1861:[ZJOI2006]书架——题解
  7. php 用header()下载文件在firefox下没有后缀名
  8. 阿里天池大赛实战记录之菜鸟-需求预测与分仓规划
  9. Android--读取通讯录并添加联系人
  10. mysql 交互式和非交互式操作(interactive_timeout和wait_timeout)