一文了解Linux中的内存映射

news2024/11/29 6:30:37

目录

一、概念

工作原理:

特点:

适用场景:

二、详解mmap()函数

1. mmap的基本概念

2. mmap的特点

3. mmap的用途

4. mmap的优缺点

三、实验

实验一:基础读写实验

实验二:证明开始显示和最初赋值有关

实验三:开始打印的换行是哪来的

实验四:可打印长度和文件大小的关系


一、概念

        使一个磁盘文件与内存中的一个缓冲区相映射,进程可以像访问普通内存一样对文件进行访问,不必再调用read,write。

工作原理

  • 内存映射是在进程的虚拟地址空间中创建一个映射,主要分为文件映射和匿名映射。
    • 文件映射:把文件的一个区间映射到进程的虚拟地址空间,数据源是存储设备上的文件。
    • 匿名映射:没有文件支持的内存映射,把物理内存映射到进程的虚拟地址空间,没有数据源。
  • 创建内存映射时,在进程的用户虚拟地址空间中分配一个虚拟内存区域。内核采用延迟分配物理内存的策略,在进程第一次访问虚拟页时,产生缺页异常,然后分配物理页并将文件数据或匿名数据读入其中。

特点

  • 文件内容可以通过指针直接读写,而不需要使用read()和write()等系统调用。
  • 多个进程可以映射同一个文件,实现共享数据。
  • 对映射区的修改会影响到文件本身。

适用场景

  • 适用于对文件内容进行频繁读写的场景,如数据库、文本编辑器等。

二、详解mmap()函数

1. mmap的基本概念

  • mmap是一种内存映射技术,它将文件或其他对象映射到进程的地址空间,使得进程可以直接通过指针访问文件数据,而无需使用传统的read和write系统调用。
  • 通过mmap,文件内容可以被加载到进程的虚拟地址空间中,进程可以直接对这段内存进行读写操作,系统会自动将脏页面回写到对应的文件磁盘上。

2. mmap的特点

  • 内存访问接口连续:mmap向应用程序提供的内存访问接口是内存地址连续的,但对应的磁盘文件的block可以不是地址连续的。
  • 虚拟空间分配:mmap提供的内存空间是虚拟空间(虚拟内存),而不是物理空间(物理内存)。因此,可以分配远大于物理内存大小的虚拟空间。
  • 文件逻辑连续映射:mmap负责将文件逻辑上一段连续的数据(物理上可以不连续存储)映射为连续内存。
  • 线程共享:mmap由操作系统负责管理,对同一个文件地址的映射将被所有线程共享,操作系统确保线程安全以及线程可见性。

3. mmap的用途

  • 文件映射:将整个文件或文件的一部分映射到进程的地址空间,提高文件操作的性能,特别是对于大文件的随机访问。
  • 进程间通信(IPC):通过映射匿名内存(不与任何文件关联的内存区域),mmap可以在不同进程间进行数据共享。
  • 创建高效的缓冲区:使用mmap创建的内存区域可以用作自定义的缓冲区,如网络数据传输或音视频数据的快速缓存。
  • 动态内存管理:mmap还可以请求操作系统分配一块新的内存区域(匿名映射),用于自定义的内存管理策略。
  • 反射和修改程序的行为:mmap可以用于实现程序的代码部分的动态修改,如即时编译(JIT)技术。

4. mmap的优缺点

  • 优点
    • 高效访问:mmap使得文件的读写操作像访问内存一样高效,避免了频繁的系统调用和数据拷贝。
    • 文件共享:多个进程可以将同一个文件映射到各自的地址空间,实现文件共享,方便进程间通信和数据共享。
    • 零拷贝:与零拷贝技术结合,可以在网络传输中减少数据拷贝,提高传输性能。
  • 缺点
    • 内存消耗:虽然mmap避免了一次性将整个文件读入内存,但映射的文件会占用进程的虚拟内存空间,处理大文件时可能导致内存消耗过多。
    • 不适合小文件:对于小文件来说,mmap的开销可能超过传统的文件读写操作。
    • 不可控制的缓存:mmap的文件访问由操作系统管理,可能导致数据缓存的不可控,影响性能预测。

注意事项:
(1) 创建映射区的过程中,隐含着一次对映射文件的读操作,将文件内容读取到映射区。

(2) 当MAP_SHARED时,要求:映射区的权限应 <=文件打开的权限(出于对映射区的保护),如果不满足报非法参数(Invalid argument)错误。

当MAP_PRIVATE时候,mmap中的权限是对内存的限制,只需要文件有读权限即可,操作只在内存有效,不会写到物理磁盘,且不能在进程间共享。

(3) 映射区的释放与文件关闭无关,只要映射建立成功,文件可以立即关闭。(没映射成功前不能关闭)

(4) 用于映射的文件大小必须>0,当映射文件大小为0时,指定非0大小创建映射区,访问映射地址会报总线错误,指定0大小创建映射区,报非法参数错误(Invalid argument)

(5) 文件偏移量必须为0或者4K的整数倍(不是会报非法参数Invalid argument错误).

(操作系统的内存是一页一页分配的一页就是4k)

(6)映射大小可以大于文件大小,但只能访问文件page的内存地址,否则报总线错误(下图中剩余部分) ,超出映射的内存大小报段错误

三、实验

实验一:基础读写实验

读程序:

#if 1
 
 
#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
 
int main(){
    
    void *addr;
    int fd;
    fd =open("test",O_RDWR);
    if(fd<0){
        perror("open");
        return 0;
    }
    int len = lseek(fd,0,SEEK_END);    
    addr = mmap(NULL,2048, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if(addr == MAP_FAILED){
        perror("mmap");
        return 0;
    }
    close(fd);
//    memcpy((addr),"99999999999999",15);
    while(1){
        printf("read=%s\n",(char*)(addr));
        sleep(1);
    }
 
 
}
#endif

写程序:

#include <sys/mman.h>
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
 
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
 
 
int main(){
    
    void *addr;
    int fd;
    fd =open("test",O_RDWR);
    if(fd<0){
        perror("open");
        return 0;
    }
    int len = lseek(fd,0,SEEK_END);    
    addr = mmap(NULL,2048, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    if(addr == MAP_FAILED){
        perror("mmap");
        return 0;
    }
    close(fd);
	memcpy(addr,"aaaaaaaaaaaaaaa",15);
    int i=0;
    while(i<2048){
       memcpy((addr+i),"a",1);
       i++;
       sleep(1);
   }    
	//memcpy(addr,"abcdefg",7);
	
 
	//printf("read=%s\n",(char*)(addr));
 
 
 
}

会发现报了总线错误。对应注意中的第六条

给他加了22个空格

这是现象,是不是很奇怪。

        左面就是先写了15个a然后从第一个位置开始往后写,右面是一直读。这就是为什么前面都一样长因为它有初值了。i大于15时才会显现出来。验证一下

实验二:证明开始显示和最初赋值有关

把开始的初值改成空格

并且不写入字符串结束标志

        因为开始有初值所以变成这个形状了,我们还发现一个问题,没有字符串结束标志后开始没换行了,现在把test清空测一下。

实验三:开始打印的换行是哪来的

就变成这个样子了。

        发现当超过限制后就没换行了,这个addr的最后是有一个换行的,当把他覆盖掉后就没了。他最多可以多打印四个。

实验四:可打印长度和文件大小的关系

        事实证明这个长度最多就是和test的大小一致,可以突破限制多打印的数量是随机的有时候多4个有时候多一个,这个和内存中字符串结束标志在哪可能有关,毕竟是已经超出可控范围的东西。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1851117.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

计算机组成原理 —— 存储系统(主存储器基本组成)

计算机组成原理 —— 存储系统&#xff08;主存储器基本组成&#xff09; 0和1的硬件表示整合结构寻址按字寻址和按字节寻址按字寻址按字节寻址区别总结 字寻址到字节寻址转化 我们今天来看一下主存储器的基本组成&#xff1a; 0和1的硬件表示 我们知道一个主存储器是由存储体…

plt绘制网格图

代码 obj "accu" for (epoch,lr) in config:with open(data/epoch_{}_lr_{}_Adam.pkl.format(epoch,lr),rb) as f:data pickle.load(f) plt.plot(range(1,epoch1),data[obj],labelflr{lr})plt.title(obj"-epoch") plt.xlabel("epoch"…

Linux系统及常用命令介绍

一.介绍 Linux一套免费使用和自由传播的类Unix操作系统&#xff0c;是一个遵循POSIX的多用户、多任务、支持多线程和多CPU的操作系统。Linux系统的说明可以自行百度&#xff0c;知道这几点即可&#xff1a; 1.Linux中一切都是文件&#xff1b; 2.Linux是一款免费操作系统&…

云资源管理系统-项目部署

云资源管理系统-项目部署 大家好&#xff0c;我是秋意零。 今天分享个人项目同时也是个人毕设项目&#xff0c;云平台资源管理系统。该系统具备对OpenStack最基本资源的生命周期管理&#xff0c;如&#xff1a;云主机、云盘、镜像、网络。 该篇主要介绍&#xff0c;项目在Li…

STM32读取芯片内部温度

基于stm32f103cbt6这款芯片&#xff0c;原理部分请参考其他文章&#xff0c;此文章为快速上手得到结果&#xff0c;以结果为导向。 1.基础配置 打开stm32cubemx只需要勾选中 ADC1 Temperature Sensor Channel 2.代码分析 /** 函数名&#xff1a;float GetAdcAnlogValue(voi…

《计算机英语》 Unit 3 Software Engineering 软件工程

Section A Software Engineering Methodologies 软件工程方法论 Software development is an engineering process. 软件开发是一个工程过程。 The goal of researchers in software engineering is to find principles that guide the software development process and lea…

开启数字新纪元:全球首款开源AI女友,你的私人数字伴侣

在这个数字化飞速发展的时代,人工智能已经不再是科幻小说中的幻想,而是实实在在走进了我们的生活。今天,我们要介绍的,不仅仅是一项技术革新,更是一场关于陪伴的革命——全球首款开源AI女友,DUIX,已经横空出世! 🚀 革命性的开源平台 DUIX,由硅基智能精心打造,不…

GLM-4V模型学习

智谱AI引领技术前沿&#xff0c;推出了新一代预训练模型GLM-4系列&#xff0c;其中的GLM-4-9B作为开源版本&#xff0c;展现了其在人工智能领域的深厚实力。在语义理解、数学运算、逻辑推理、代码编写以及广泛知识领域的数据集测评中&#xff0c;GLM-4-9B及其人类偏好对齐的版本…

慎投!新增7本期刊被“On Hold“,14本影响因子下降!

本周投稿推荐 SSCI • 中科院2区&#xff0c;6.0-7.0&#xff08;录用友好&#xff09; EI • 各领域沾边均可&#xff08;2天录用&#xff09; CNKI • 7天录用-检索&#xff08;急录友好&#xff09; SCI&EI • 4区生物医学类&#xff0c;0.5-1.0&#xff08;录用…

大学生须知~~毕业行李太多,怎么拿回家

一年一度的暑假来临了&#xff0c;大学生们又该放假了&#xff0c;可是回家行李这么多&#xff0c;怎么邮寄才便宜呢&#xff1f;&#xff1f; 记得找惠发快递呀&#xff01;因为我们平台是跟快递总部合作的&#xff0c;不管你寄大件还是快递都很便宜&#xff0c;而且没有单量…

转--Hadoop集群部署案例

模块简介 本模块主要练习Hadoop集群部署。 模块知识 ● 使用Linux基础命令 ● Hadoop集群搭建部署知识 环境准备 三台CentOS7操作系统的虚拟机 可以是3个Docker容器&#xff0c;也可以是三个VMWare/VirtualBox的虚拟机。三台虚拟机的最低配置为1核1G 20G。如果是虚拟机中…

20分钟攻破DISCUZ论坛并盗取数据库(web安全白帽子)

20分钟攻破DISCUZ论坛并盗取数据库&#xff08;web安全白帽子&#xff09; 1 快速搭建discuz论坛1.1 攻击思路1.2 快速搭建实验环境1.2.1&#xff0c;漏洞概述1.2.2&#xff0c;在centos7虚拟机上搭建LAMP环境1.2.3&#xff0c;上传到discuz_X2_SC_UTF8.zip 到Linux系统/root下…

Android 添加自己的时钟小部件

小部件&#xff0c;也叫微件&#xff0c; 它的介绍参考官网 应用 widget 概览 https://developer.android.google.cn/develop/ui/views/appwidgets/overview?hlzh-cn 直接上图&#xff0c;原生系统上&#xff0c;时钟应用的小部件效果。 我也整一个。 1.创建小部件布局文…

C#使用轻量级深度学习模型进行车牌颜色识别和车牌号识别

看到这个文章时候请注意这个不涉及到车牌检测&#xff0c;这个仅仅是车牌颜色和车牌号识别&#xff0c;如果想涉及到车牌检测可以参考这个博客&#xff1a;[C#]winform部署yolov7CRNN实现车牌颜色识别车牌号检测识别_c# yolo 车牌识别-CSDN博客 【训练源码】 https://github.…

已解决java.rmi.activation.ActivationException异常的正确解决方法,亲测有效!!!

已解决java.rmi.activation.ActivationException异常的正确解决方法&#xff0c;亲测有效&#xff01;&#xff01;&#xff01; 问题分析 java.rmi.activation.ActivationException 是与Java RMI&#xff08;远程方法调用&#xff09;的激活机制相关的一种已检查异常。这个异…

【面试干货】Hashtable 与 HashMap 的区别

【面试干货】Hashtable 与 HashMap 的区别 1、线程安全性2、对null值的处理3、遍历方式4、遍历示例5、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 在Java中&#xff0c;Hashtable和HashMap都是基于哈希表实现的Map接口。然而&#…

代码随想录算法训练营第31天| 134. 加油站、135. 分发糖果、860.柠檬水找零、 406.根据身高重建队列

134. 加油站 题目链接&#xff1a;134. 加油站 文档讲解&#xff1a;代码随想录 状态&#xff1a;so easy 思路&#xff1a;每次遍历时&#xff0c;如果当前的油量差&#xff08;currTank&#xff09;小于0&#xff0c;说明从当前起点无法到达下一个加油站。此时&#xff0c;将…

Python --- 如何修改Jupyter Notebook保存文件的路径?

如何修改Jupyter Notebook在本地保存文件的默认路径&#xff1f; 一直以来都比较喜欢jupter notebook&#xff0c;自从用了以后就爱上了。平时用的时候&#xff0c;因为大多都是临时调用&#xff0c;每次在界面里直接new一个新的file就开干。 曾经也想过我创建的这些python文件…

代码随想录第31天|贪心算法

134. 加油站 参考 思路: 以每个油站相差作为判断, 比如: gas [5 8 2 8]cost [6 5 6 6] [-1 3 -4 2]错误 : 把相差最大点当作起点判断能否绕一圈 : 相加数组是否小于0局部最优: 当前累加rest[i]的和curSum一旦小于0&#xff0c;起始位置至少要是i1&#xff0c;因为从i…

初识 SpringMVC,运行配置第一个Spring MVC 程序

1. 初识 SpringMVC&#xff0c;运行配置第一个Spring MVC 程序 文章目录 1. 初识 SpringMVC&#xff0c;运行配置第一个Spring MVC 程序1.1 什么是 MVC 2. Spring MVC 概述2.1 Spring MVC 的作用&#xff1a; 3. 运行配置第一个 Spring MVC 程序3.1 第一步&#xff1a;创建Mave…