linux mmap 作用,LINUX 中的mmap浅析
LINUX 中的mmap浅析
一、mmap基本原理和分类
在LINUX中我们可以使用mmap用来在进程虚拟地址空间中分配创建一片虚拟内存地址映射
其可以是
1、文件映射
使用文件内容初始化内存
2、匿名映射
初始化全为0的内存空间(calloc也可以)
下面配图来自UNIX系统编程手册
而对于是否共享又分为
1、私有映射(MAP_PRIVATE)
多进程间数据共享,修改不反应到磁盘实际文件,
私有写时复制实现
2、共享映射(MAP_SHARED)
多进程间数据共享,修改反应到磁盘实际文件中。
那么总结起来有4种组合
1、私有文件映射
多个进程使用同样的物理内存页进行初始化,但是各个进程
对内存文件的修改不会共享,也不会反应到物理文件中,比如
我们LINUX .so动态库文件就采用这种方式映射到各个进程虚拟
地址空间中
2、私有匿名映射
mmap会创建一个新的映射,各个进程不共享,这种使用主要用于
分配内存(malloc分配大内存会调用mmap)。
3、共享文件映射
多个进程通过虚拟内存技术共享同样的物理内存空间,对内存文件
的修改会反应到实际物理文件中,他也是进程间通信(IPC)的一种机制
4、共享匿名映射
这种机制在进行fork的时候不会采用写时复制,父子进程完全共享
同样的物理内存页,这也就实现了父子进程通信(IPC).
下面也是UNIX系统编程手册截图
在/proc/PID/maps下我们可以找到一个当前进程使用mmap创建的映射比如:
379a000000-379a016000 r-xp 00000000 08:03 12320771 /lib64/libgcc_s-4.4.7-20120601.so.1
379a016000-379a215000 ---p 00016000 08:03 12320771 /lib64/libgcc_s-4.4.7-20120601.so.1
379a215000-379a216000 rw-p 00015000 08:03 12320771 /lib64/libgcc_s-4.4.7-20120601.so.1
379a400000-379a4e8000 r-xp 00000000 08:03 9700201 /usr/lib64/libstdc++.so.6.0.13
379a4e8000-379a6e8000 ---p 000e8000 08:03 9700201 /usr/lib64/libstdc++.so.6.0.13
379a6e8000-379a6ef000 r--p 000e8000 08:03 9700201 /usr/lib64/libstdc++.so.6.0.13
379a6ef000-379a6f1000 rw-p 000ef000 08:03 9700201 /usr/lib64/libstdc++.so.6.0.13
对于解释可以参考UNIX系统编程手册如下描述
二、mmap函数原型
void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
参数有点多
addr:映射放到哪里(虚拟地址),一般传NULL,让内核自己决定
length:映射的大小(直接),最小是系统页的整数倍(4K)
port:位图掩码
PROT_NONE 不能访问
PROT_READ 可读取
PROT_WRITE 可修改
PROT_EXEC 可执行
非法访问或报SIGSEGV段错误信号
flags:位图掩码
MAP_ANONYMOUS:创建一个匿名映射
MAP_PRIVATE:私有映射
MAP_SHARED:共享映射(注意并不能保证一定实际写入物理磁盘(MSYNC))
MAP_FIXED:addr必须是页对齐地址
其他标示不做解释
fd:映射文件的文件描述符
offset:从文件的哪个位置开始映射,必须是系统页的整数倍(4K)
返回值:
成功返回映射的虚拟内存地址的起始地址,失败返回MAP_FAILED
三、建立匿名映射
1、指针MAP_ANONYMOUS,并且fd指定为0
2、打开/dev/zero文件将文件描述符传递给mmap()
匿名映射会分配初始化全为0的虚拟内存空间
四、其他函数
int msync(void *addr, size_t length, int flags);
用于将kener buffer的数据同步到磁盘
int munmap(void *addr, size_t length);
用于解除映射
五、程序实例
下面我们通过mmap做私有匿名映射来完成一个小的线程间同步问题程序,用这片
内存区域来做线程间通信
点击(此处)折叠或打开#include
#include
#include
#include
#define uint unsigned int
#define MMSIZE (uint)(1<<23)
#define MSIZE (uint)(1<<20)
#define MPRT (uint)(1<<16)
using namespace std;
class tc
{
private:
uint a;
public:
tc():a(1)
{
;
}
~tc()
{
;
}
void add()
{
a=a+1;
}
void set()
{
a=1;
}
void prt(int i)
{
if(!(i%(MPRT)))
{
cout<
}
}
};
struct tt
{
tc* p1;
pthread_mutex_t* p2;
};
void* test(void* arg)
{
int i = 0;
tt* s = NULL;
s = (tt*)arg;
int maxloop = 50;
while(maxloop--)
{
i = MSIZE;
pthread_mutex_lock(s->p2);//MUTEX保护临界区
cout<
for(;i--;)
{
(s->p1+i)->prt(i);
(s->p1+i)->add();
}
cout<
pthread_mutex_unlock(s->p2);//解锁
}
}
int main(void)
{
pthread_t tid[3];
pthread_mutex_t pmut;
tt s1;
tc* p = (tc*)mmap(NULL,MMSIZE,PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);//MMAP分配一个匿名私有虚拟内存用于线程间通信
pthread_mutex_init(&pmut,NULL);
s1.p1 = p;
s1.p2 = &pmut;
int i = MSIZE+1;
for(;i--;)
{
(p+i)->set();//初始化所有的a=1
}
for(i=0;i<3;i++)
{
pthread_create(tid+i,NULL,test,(void*)&s1);//建立3个线程
}
for(i = 0;i<3;i++)
{
pthread_join( *(tid+i) , NULL);//堵塞回收线程
}
pthread_mutex_destroy(&pmut);
munmap(p,MMSIZE);
}
同时我们也观察到了线程由于失去CPU而放弃执行其他线程得到CPU继续执行,由于
我们使用MUTEX保护临界区这个数数还是正常进行。最后正常数到了150
Thread:140545405572864 work now!!!
:32:32:32:32:32:32:32:32:32:32:32:32:32:32:32:32
Thread:140545397180160 work now!!! (线程140545405572864 失去CPU线程140545397180160执行)
:33:33:33:33:33:33:33:33:33:33:33:33:33:33:33:33
..................
Thread:140545397180160 work now!!!
:58:58:58:58:58:58:58:58:58:58:58:58:58:58:58:58
Thread:140545405572864 work now!!!(线程140545405572864重新获得CPU)
:59:59:59:59:59:59:59:59:59:59:59:59:59:59:59:59
............
Thread:140545388787456 work now!!!
:150:150:150:150:150:150:150:150:150:150:150:150:150:150:150:150
linux mmap 作用,LINUX 中的mmap浅析相关推荐
- linux dm 作用,Linux dm中minor number的管理——idr
1. idr机制 Linux的dm中对minor number采用idr机制进行管理.idr即"ID Radix",内核中通过radix树对ID进行组织和管理,是一种将整数ID和指 ...
- linux poll 作用,Linux中poll机制的理解
首先分析下应用程序的执行过程: int main(int argc, char **argv) { int fd; unsigned char key_val; int ret; struct pol ...
- Linux locate 作用,linux中的locate命令的详细解释
linxu下的locate命令可以在搜寻数据库时快速找到档案,是个很方便的命令.下面由学习啦小编为大家整理了linux的locate命令的详细解释的相关知识,希望对大家有帮助! 一.linux中的lo ...
- linux tmpfs作用,linux ramfs和tmpfs区别及用法介绍
ramfs是Linux下一种基于RAM做存储的文件系统.在使用过程中你就可以把ramfs理解为在普通的HDD上建立了一个文件系统,而现在HDD被替换成了RAM,因为是RAM做存储所以会有很高的存储效率 ...
- linux strip作用,linux gcc strip命令简介
阅读目录 strip简介 strip经常用来去除目标文件中的一些符号表.调试符号表信息,以减小静态库.动态库和程序的大小. strip支持的选项可通过如下命令查看: strip --help stri ...
- linux 正则表达式 作用,Linux 正则表达式使用简介
正则表达式基本介绍 正则表达式使用单个字符串来描述.匹配一系列符合某个句法规则的字符串.在很多文本编辑里,正则表达式通常被用来检索.替换那些符合某个模式的文本. 正则表达式的基本元素包括普通字符和元字 ...
- linux acpi 作用,Linux ACPI服务ACPI 驱动体系简介
Linux ACPI服务DSDT: DSDT 称做 Differentiated Definition Block,存在于 BIOS 中并与当前的硬件平台兼容的,提供了系统的硬件特性(例如某些设备的内 ...
- linux tmpfs作用,Linux下tmpfs介绍与使用
1 Tmpfs是什么 tmpfs是Linux/Unix系统上的一种基于内存的文件系统.tmpfs可以使用您的内存或swap分区来存储文件.由此可见,tmpfs主要存储 暂存的文件. 优势 : 1. 动 ...
- linux文件目录作用,linux 文件目录,及其作用
/boot:系统启动相关的相关文件,如内核,initrd,以及grub(bootloader) /dev: 设备文件 设备文件: 块设备:随机访问,数据块 字符设备:线性访问,按字符文单位 设备号:主 ...
- linux dup作用,linux dup()\dup2()函数
dup函数的作用:复制一个现有的句柄,产生一个与"源句柄特性"完全一样的新句柄(也即生成一个新的句柄号,并关联到同一个设备) dup2函数的作用:复制一个现有的句柄到另一个句柄上, ...
最新文章
- 原子核与外围电子有非常大的空间为什么物体有光滑的平面
- 越小越好:为什么电子器件都这么小巧玲珑?
- 选择ButterKnife,告别findViewById
- strtus2改成springboot_jdk1.6环境下struts2改spring boot方案-阿里云开发者社区
- idea怎么搜索文件——search everywhere
- 新浪微博数据网络舆情分析客户端软件
- math库是python语言的数学模块_Python 数学模块(Math)
- 图解linux32位平台下进程线程长什么样子
- 微信分享签名无效php_php实现微信分享朋友链接功能
- 10年10亿才能烧好电子商务?
- ubuntu安装jdk
- 程序员如何用六年时间打造价值10亿的帝国?
- Linux 的 复制命令 【 cp 】 (copy)及其 (常用参数 -fp)
- Java开发 音视频会议
- 华为USG6000V防火墙telnet+安全策略
- 荣誉加持,驭势科技近期斩获奖项回顾
- 拓扑排序 POJ - 3687反向图跑字典序(重边)
- Springboot企业工资管理rycxe计算机毕业设计-课程设计-期末作业-毕设程序代做
- left join 和 left outer join (可解决多个表left join的问题)
- Java职责链模式详解
热门文章
- int转byte数组以及相关原理
- AOSP 隐藏 su
- ireport 3.6.0 增加PDF字体、加粗失效、PDF中文不显示等问题
- LeetCode——75. 颜色分类(面试题)
- 解决Mac无法识别移动硬盘以及无法识别BootCamp Windows分区的问题
- win10浏览器闪退_win10自带浏览器闪退解决方法
- jquery实现侧边栏手风琴三级导航菜单demo
- 深度学习教程(14) | 序列模型与RNN网络(吴恩达·完整版)
- Android应用帧率--FPS测试
- 米家扫地机器人是石头代工_石头扫地机器人T4全面评测 支持软件虚拟墙,清扫更高效...