转自: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 系统调用 的使用相关推荐
- 【Linux 内核 内存管理】Linux 内核堆内存管理 ② ( 动态分配堆内存方式 | brk 系统调用 | mmap 系统调用 | brk 系统调用源码介绍 )
文章目录 一.Linux 系统 动态分配堆内存 方式 二.brk 系统调用 动态分配堆内存 一.Linux 系统 动态分配堆内存 方式 Linux 系统中 , 提供了 222 种方式 进行 " ...
- 内存映射(mmap系统调用)
映射虚拟内存-->物理内存/Swap/文件 文件映射到内存,内存访问取代IO访问 可以映射同一个文件以(进程)共享内存 Linux进程虚拟地址空间---(分成)-->虚拟内存区 虚拟内存区 ...
- linux mmap系统调用
brk/mmap linux 提供了两个比较重要的系统调用brk 和mmap,用于向内核申请相应用户空间,内核会根据系统运行状态判定是否申请新的VMA来管理新申请的用户空间,brk和mmap在整个系统 ...
- Linux内存管理 brk(),mmap()系统调用源码分析2:brk()的内存释放流程
Linux brk(),mmap()系统调用源码分析 brk()的内存释放流程 荣涛 2021年4月30日 内核版本:linux-5.10.13 注释版代码:https://github.com/Rt ...
- 【Linux 内核 内存管理】mmap 系统调用源码分析 ④ ( do_mmap 函数执行流程 | do_mmap 函数源码 )
文章目录 一.do_mmap 函数执行流程 二.do_mmap 函数源码 调用 mmap 系统调用 , 先检查 " 偏移 " 是否是 " 内存页大小 " 的 & ...
- Linux brk(),mmap()系统调用源码分析3:brk()的内存申请流程
Linux brk(),mmap()系统调用源码分析 brk()的内存申请流程 荣涛 2021年4月30日 内核版本:linux-5.10.13 注释版代码:https://github.com/Rt ...
- Linux内存管理 brk(),mmap()系统调用源码分析1:基础部分
Linux内存管理 brk(),mmap(),munmap()系统调用源码分析 基础部分 荣涛 2021年4月30日 内核版本:linux-5.10.13 注释版代码:https://github.c ...
- mmap系统调用使用-学习笔记
文章目录 1. mmap函数参数说明 2. mmap父子进程通信 3. 匿名映射 4. mmap基本使用示例 5. mmap使用常见问题 6. 总结 1. mmap函数参数说明 头文件:#includ ...
- 内存分配的原理__进程分配内存有两种方式,分别由两个系统调用完成:brk和mmap(不考虑共享内存)
如何查看进程发生缺页中断的次数? 用ps -o majflt,minflt -C program命令查看. majflt代表major fault,中文名叫大错误,minflt代表minor faul ...
- 【Linux 内核 内存管理】内存管理架构 ④ ( 内存分配系统调用过程 | 用户层 malloc free | 系统调用层 brk mmap | 内核层 kmalloc | 内存管理流程 )
文章目录 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) 二.内存管理流程 一.内存分配系统调用过程 ( 用户层 | 系统调用 | 内核层 ) " 堆内存 " ...
最新文章
- 修改Activity响应音量控制键修改的音频流
- latex 插图解释_大O符号-只需插图和视频即可解释
- 64位IIS(IIS6/IIS7)上跑Asp + Jet.Oledb的设置要点
- 下面哪个字段是http请求中必须具备的_HTTP协议及其工作原理介绍
- 企业项目开发--切分配置文件
- springmvc的执行流程_springmvc执行流程
- oracle or 循环 查询,Oracle的循环和Corsor
- rem、px、em之间的区别以及网页响应式设计写法
- android drawable转bitmap_Android 内存泄漏优化汇总
- 这本京东断货王的Python神书,刷爆整个编程圈!| 测评
- 谷歌浏览器获取主题图片
- 数字乡村大数据可视化平台建设方案 智慧乡村 美丽乡村 智慧农村
- A 股历年三大财务报表 API 接口
- python求不规则图形面积_python计算不规则图形面积算法
- Latex PDF文档目录乱码
- matlab识别中国象棋棋盘,c – 使用OpenCV在棋盘中检测中国象棋棋子
- 弦理论能成为新的万物理论吗?
- 干货!如何快速拥有自己的商城APP
- c#中屏蔽窗体关闭的消息
- k8s client-go 出现错误net/http: TLS handshake timeout
热门文章
- 汉字注音符号学习(引用自维基百科)
- NYOJ 822 画图
- getnumdevices.c setgetdevicetype例程
- f-admin——基于Laravel框架开发的基础权限后台系统
- 数据结构与算法之递归和分治思想
- BZOJ1861:[ZJOI2006]书架——题解
- php 用header()下载文件在firefox下没有后缀名
- 阿里天池大赛实战记录之菜鸟-需求预测与分仓规划
- Android--读取通讯录并添加联系人
- mysql 交互式和非交互式操作(interactive_timeout和wait_timeout)