Linux系统:内存映射概念以及相关函数(mmap、munmap、msync)介绍
Linux系统:内存映射概念以及相关函数(mmap、munmap、msync)介绍
1.1 基本概念
- 内存映射根据种类分为:
- 文件映射:将一个文件的一部分直接映射到虚拟进程地址空间中,虚拟进程地址空间会对应一部分内存RAM分页
- 共享文件映射:在同一个文件上面的映射变更,对其它共享该文件映射的进程是可见的(应为这个时候多个进程共享同一个物理内存分页),并且会把变更反映到磁盘文件上
- fork创建的子进程会继承父进程的映射关系,并且共享相同的物理内存分页
- 对应的内存分页最初以映射部分的文件内容进行初始化
- exec会丢失映射关系
- 用途:
- 内存映射I/O,一种替代write和read的比较好的方案
- 共享内存
- 私有文件映射:在同一个文件上面的映射变更,对其它共享该文件映射的进程是不可见的,并且对一个分页的修改的时候,会通过写时复制技术重新分配一个分页,把原来需要修改的分页内容复制到新分页中,并且会修改进程相应的页表内容,所以这种修改不会对底层磁盘文件发生影响
- fork创建的子进程会继承父进程的映射关系,并且共享相同的物理内存分页
- 对应的内存分页最初以映射部分的文件内容进行初始化
- exec会丢失映射关系
- 用途:
- 用文件的内容来初始化内存分页,比如用共享库文件或者二进制文件
- 共享文件映射:在同一个文件上面的映射变更,对其它共享该文件映射的进程是可见的(应为这个时候多个进程共享同一个物理内存分页),并且会把变更反映到磁盘文件上
- 匿名映射:将一个虚拟文件(没有对应的文件)映射到虚拟进程地址空间中
- 共享文件映射
- 私有文件映射
- 文件映射:将一个文件的一部分直接映射到虚拟进程地址空间中,虚拟进程地址空间会对应一部分内存RAM分页
1.2 创建一个映射
函数功能:系统调用在调用进程的虚拟地址空间创建一个映射
函数返回值:成功返回映射之后的对应的虚拟地址,错误返回MAP_FAILED((void *)-1)
函数原型:
#include <sys/mman.h>void *mmap(void *addr, size_t length, int prot, int flags,int fd, off_t offset);
函数参数:
addr:指定了映射被放置的开始虚拟地址,一般设置为NULL,表示内核自己选择一个分页边界的整倍数的地址,如果是一个非NULL值,内核会把他作为一个提示地址,选择相邻的分页边界的整倍数的地址返回,如果设置了MAP_FIXED标志,addr就必须为一个分页边界的整倍数的地址
length:制定了映射的字节数,系统会自动选择一个分页整倍数的长度,所以实际大小可能比length大
prot:一个位掩码,指定了施加于映射之上的保护信息,可以选择多个,这里需要注意这个部分的权限是访问虚拟地址对应的那部分内存分页的权限
flag:控制映射操作的选项位掩码,只能选择一个,举例常用的如下:
- MAP_SHARED:创建共享映射
- MAP_PRIVATE:创建私有映射
fd:被映射的文件的描述符
offset:被映射文件的起点值
1.3 解除映射
函数功能:从调用进程的虚拟进程地址空间删除一个映射关系
函数返回值:返回0成功,失败返回-1
函数原型:
#include <sys/mman.h> int munmap(void *addr, size_t length);
函数参数:
- addr:映射被放置的开始虚拟地址
- length:映射的长度
需要解除的映射范围是可以调整的,并不一定是全部
进程终止和使用exec()都会使得映射关系被接触,需要使用msync()确保修改从内存分页写入底层文件
1.4 文件映射详细概念
文件映射的具体步骤:
- open打开一个文件获得文件描述符fd
- 将文件描述符作为参数传入mmap
- 映射完毕之后,可以关闭fd,不会造成任何影响
- 这里需要注意,fd上面的权限和mmap的prot权限一定要匹配,后果后面会讲到
共享文件映射,这部分主要讲解其映射原理,看以下博客链接:
http://blog.csdn.net/joejames/article/details/37958017
物理内存到底层文件之间的数据交换是靠内核完成的
内核空间高速缓存:存在于物理内存的内核地址空间部分
用户空间高速缓存:存在于物理内存的用户地址空间部分
内存映射用于内存I/O时候的特点:
- 内核空间和用户空间可以理解为共享同一个缓存
- 内存映射I/O相比write和read的提升主要体现在少了一次内核空间高速缓存到用户空间高速缓存的复制过程,如果文件很大,多次磁盘I/O就有多次复制,很浪费时间。但是内核空间高速缓存足够大到容纳任何一个数据(也就是只需要一次磁盘I/O),那么想比如write和read的提升几乎没有,因为内核空间高速缓存到用户空间高速缓存的复制过程也只有一次了,毕竟时间主要浪费在磁盘I/O上面
1.5 边界情况
- 情况1:
情况2:mmap(0,2199,prot,MAO_SHARED,fd,0)
- 因为2199不满足分页的整倍数,一个分页大小是4bytes(4096),所以扩充到了4095,扩充部分可以访问,但是这部分内存会被初始化为0,不会映射到底层文件,也不可以被其它进程共享,即使指定了足够大的length
情况3:
- 8192超出了向上舍入区域(2200到4095),访问4096到8191时候会发生SIGBUS错误
1.6 内存保护和文件访问模式交互
- 一般情况下:
- PORT_READ和PORT_EXEC和O_RDONLY或者O_RDWR配合使用
- PORT_WRITE和O_WRONLY或者O_RDWR配合使用
- 注意:特殊架构下
- O_RDWR与所有内存保护兼容
- 没有任何内存保护与O_WRONLY兼容
- O_RDONLY标记打开一个文件:
- MAP_PRIVATE:任意内存保护组合
- MAP_SHARE:PORT_REA(PORT_READ | PORT_EXEC)
1.7 同步映射区域msync()
对映射区域的修改,内核不一定会马上把数据从内核高速缓存区域刷入磁盘,所以这个时候可以用msync()认为控制这个过程
函数功能:控制映射部分内存与映射文件的同步
函数返回值:成功返回0,失败返回-1
函数原型:
#include <sys/mman.h> int msync(void *addr, size_t length, int flags);
函数参数:
- addr:映射被放置的开始虚拟地址
- length:映射的长度
- flags:
- MS_SYNC:执行同步操作,阻塞到所有被修改的内存分页写入底层文件为止。内核高速缓存区域马上同步底层文件
- MS_ASYNC:执行异步操作,后面某个时候写入磁盘。内核高速缓存区域后面某个时刻同步底层文件
Linux系统:内存映射概念以及相关函数(mmap、munmap、msync)介绍相关推荐
- Linux 系统内存分析
1. 内存基本介绍 1.计算机基本结构: 电脑之父--冯·诺伊曼提出了计算机的五大部件:输入设备.输出设备.存储器.运算器和控制器 如图: 输入设备:键盘鼠标等 CPU:是计算机的运算核心和控制核心, ...
- Linux系统内存知识总结
点击上方"朱小厮的博客",选择"设为星标" 后台回复"书",获取 来源:22j.co/dJ29 Linux 内存是后台开发人员,需要深入了解 ...
- Linux系统内存管理之伙伴系统分析 - 旭东的博客 - 博客园
Linux系统内存管理之伙伴系统分析 - 旭东的博客 - 博客园 Linux系统内存管理之伙伴系统分析 今天去面试,一位面试官提到了内存管理的伙伴系统,当时就懵了,因为根本就没有听说过.晚上回来在实验 ...
- Linux学习之CentOS(八)--Linux系统的分区概念
不知不觉已经记录了8篇Linux学习随笔了,虽然还是漂浮在Linux系统的表面,还有很多很多没有学,但是坚持学下去.坚持写下去就是成功的!!!! 在讲Linux系统分区之前,首先得介绍一下硬盘分区的知 ...
- 嵌入式linux+io+优化,嵌入式Linux系统内存优化使用方法研究
[摘要] 嵌入式系统功能的提高,占用了较大内存空间,继而时常出现运行无响应.基于用户方面看,由于系统内存问题影响运行,针对系统内存与进程应用状态研究,可以调整系统数值与执行文件elf分析,进行系统优化 ...
- linux map内存在哪里分配,brk mmap madvise 内存分配以及共享内存
mmap() vs read()/write()/lseek() 通过strace统计系统调用的时候,经常可以看到mmap()与mmap2().系统调用mmap()可以将某文件映射至内存(进程空间), ...
- 707-详解32位Linux系统内存地址映射
详解32位Linux系统内存地址映射 我们先看一段简单的C程序: 我们先来看一张图: 我们平时所说的x86 32位指的是:80386往后到现在的同一个体系的CPU处理芯片,但是x86这个芯片是从808 ...
- linux系统内存dump机制介绍(一)--kdump
本文来自 网易云社区 . kdump的原理介绍 按照linux系统的设计哲学,内核只提供dump内存的机制,用户想要dump什么样的内存,dump多少内存是属于策略问题,由用户来决定. 在真实的使用场 ...
- Linux系统端口映射(路由转发)
2019独角兽企业重金招聘Python工程师标准>>> Linux系统端口映射(路由转发),首先应该做的是/etc/sysctl.conf配置文件的 net.ipv4.ip_forw ...
最新文章
- Flink学习笔记:Operators之CoGroup及Join操作
- Android APP更新下载工具类——简单封装DownloadManager
- R语言计算杰卡德相似系数(Jaccard Similarity)实战:自定义函数计算Jaccard相似度、对字符串向量计算Jaccard相似度、将Jaccard相似度转化为Jaccard距离
- AI工程师必读的10本ML读物(附PDF下载)
- 可以对同一个html元素定义不同的样式,CSS的多种选择器的使用.ppt
- dataframe 加一行_虎牙公会是干嘛的?虎牙直播有必要加公会吗?
- 2020牛客暑期多校训练营(第六场)
- gateway中的局部过滤器_Spring Cloud Gateway中的过滤器工厂:重试过滤器
- C++:34---union:联合/共用体,一种节省空间的类
- Linux——如何打开或者安装g++
- html转为纯文本并且保留换行,使用jsoup将html转换为纯文本时,如何保留换行符?...
- 新一代CTR预测服务的GPU优化实践
- 前端 javascript 变量
- RGB转换为NV12的代码
- exfat最佳单元大小_ICLR2019最佳论文!神经网络子网络压缩10倍,精确度还能保持不变...
- vue中书写JSX一些坑-特殊属性名
- “无法保存该网页”的最简单解决方法
- 计算机网络(第七版)部分课后习题含答案第一章 概述1-02 试简述分组交换的要点。分组交换最主要的特点就是采用存储转发技术。我们把要发送的整块数据称为一个报文。在发送报文之前,先把较长的报
- Java聊天室(实现群聊、私聊功能)GUI界面
- PySpark机器学习 ML