一文了解Linux中的内存映射

目录

一、概念

工作原理:

特点:

适用场景:

二、详解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个有时候多一个,这个和内存中字符串结束标志在哪可能有关,毕竟是已经超出可控范围的东西。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

three.js基础环境搭建

three.js three.js介绍安装threejs文件资源目录介绍本地静态服务器vscode配置live-server插件nodejs配置本地静态服务器项目的开发环境引入threejs 基础知识右手坐标系程序结构 three.js介绍 three.js官网 Three.js是一款基于WebGL的JavaScript 3D库&#xff0c;它使得开发者能…

Spring统一功能

文章目录 一、什么是统一功能二、拦截器2.1 什么是拦截器2.2 拦截器的使用2.3 案例&#xff1a;不拦截前端的请求2.4 拦截器是如何实现的 ---- >分析DispatcherServlet源码分析 三、适配器模式四、统一数据返回格式五、统一异常六、案例&#xff1a;在图书管理系统使用统一功…

Linux系统启动流程

init程序类型&#xff1a; ①、SysV&#xff1a;init&#xff0c;centos 5之前&#xff0c;配置文件/etc/init.d/ ②、Upstart: init&#xff0c;centos 6&#xff0c;配置文件/etc/init.d/ /etc/init/ ③、Systemd:Systemd&#xff0c;centos 7&#xff0c;配置文件/usr/li…

鸿蒙开发系统基础能力:【@ohos.systemTime (设置系统时间)】

设置系统时间 本模块用来设置、获取当前系统时间&#xff0c;设置、获取当前系统日期和设置、获取当前系统时区。 说明&#xff1a; 本模块首批接口从API version 7开始支持。后续版本的新增接口&#xff0c;采用上角标单独标记接口的起始版本。 导入模块 import systemTime …

第三十三篇——互联网广告:为什么Google搜索的广告效果好?

目录 一、背景介绍二、思路&方案三、过程1.思维导图2.文章中经典的句子理解3.学习之后对于投资市场的理解4.通过这篇文章结合我知道的东西我能想到什么&#xff1f; 四、总结五、升华 一、背景介绍 对于信息的利用&#xff0c;再广告这个维度中去洞察&#xff0c;你又能发…

在低版本Excel中创建次级下拉列表

在低版本中indirect函数不支持选区&#xff0c;创建次级下拉列表得依靠“名称管理”给选区命名。 (笔记模板由python脚本于2024年06月26日 06:24:22创建&#xff0c;本篇笔记适合常用Excel处理数据的coder翻阅) 【学习的细节是欢悦的历程】 Python 官网&#xff1a;https://www…

3.任务的创建与删除

1.什么是任务&#xff1f; 任务可以理解为进程/线程&#xff0c;创建一个任务&#xff0c;就会在内存开辟一个空间。 任务通常都含有while(1)死循环 2.任务创建与删除相关的函数 3.CUBEMAX相关配置 编辑一个led1闪烁的任务

JAVA开发的一套医院绩效考核系统源码:KPI关键绩效指标的清晰归纳

KPI是关键绩效指标&#xff08;Key Performance Indicators&#xff09;的缩写&#xff0c;它是一种用于衡量员工或组织绩效的量化指标。这些指标通常与组织的目标和战略相关&#xff0c;并帮助管理层评估员工和组织的实际表现。KPI还可以为员工提供清晰的方向&#xff0c;使他…

怎么把不同的文件做成二维码?多种文件类型在线生码的制作方法

扫码来展示文件是现在很多场景下会使用的一种内容展示方法&#xff0c;这种方式能够简化其他人获取文件的流程&#xff0c;从而提升文件传播的效率&#xff0c;用户可以存储二维码&#xff0c;随时扫码查看文件内容。文件生成二维码支持多种类型的文件使用&#xff0c;比如ppt、…

PS教程29

图层蒙版 以案例来解释蒙版的作用 将这两张图片原框背景切换将图二的背景选中使用套索工具选中区域切换图一CtrlA全选CtrlC复制编辑-选择性粘贴-贴入即可贴入如果位置不对用移动工具进行调整 这就是图层蒙版 图层蒙版本质作用&#xff1a;是临时通道&#xff0c;支持黑白灰三种…

什么是凸/非凸数据?

简单来说&#xff0c;数据集D中任意两点的连线上的点&#xff0c;也会在数据集D内&#xff0c;那么数据集D就是一个凸集。 如下图&#xff0c;左边非凸&#xff0c;右边为凸

【华为OD机试|01】最远足迹(Java/C/Py/JS)

目录 一、题目介绍 1.1 题目描述 1.2 备注&#xff1a; 1.3 输入描述 1.4 输出描述 1.5 用例 二、Java代码实现 2.1 实现思路 2.2 详细代码 2.3 代码讲解&#xff1a; 三、C语言实现 3.1实现步骤 3.2 实现代码 3.3 代码详解 四、Python实现 4.1 实现步骤 4.2 …

Linux开发讲课16--- 【内存管理】页表映射基础知识2

ARM32页表和Linux页表那些奇葩的地方 ARM32硬件页表中PGD页目录项PGD是从20位开始的&#xff0c;但是为何头文件定义是从21位开始&#xff1f; 历史原因&#xff1a;Linux最初是基于x86的体系结构设计的&#xff0c;因此Linux内核很多的头文件的定义都是基于x86的&#xff0c…

离线安装docker-v26.1.4,compose-v2.27.0

目录 ​编辑 1.我给大家准备好了提取即可 2.安装docker和compose 3.解压 4.切换目录 5.执行脚本 6.卸载docker和compose 7.执行命令 “如果您在解决类似问题时也遇到了困难&#xff0c;希望我的经验分享对您有所帮助。如果您有任何疑问或者想分享您的经历&#xff0c;…

Java 8 新特性:Lambda表达式让你的代码焕然一新——掌握它,让编程变得轻松又高效!

前言 Java 8 是 Java 发展史上的一次重要里程碑。作为企业级开发语言&#xff0c;它在性能和功能上做了巨大的提升。这其中&#xff0c;Lambda表达式是一个关键的新特性&#xff0c;它为 Java 语言带来了函数式编程的概念。本篇文章将深入探讨Lambda表达式&#xff0c;并结合热…

[油猴脚本] Image To Ascii 快速转换审计网站图片中敏感信息插件

项目地址:https://github.com/MartinxMax/ImageToAscii 导入 将ImagetoAscii.user.js导入油猴 进行按照 访问网站分析图片 当鼠标靠近图片时会出现分析按钮 通过审查图片信息,我们可以快速发现这张图片存在PHP代码。 当然在渗透测试中,你可以快速查看上传的图片木马中PHP代码…

vuejs3用gsap实现动画

效果 gsap官网地址&#xff1a; https://gsap.com/ 安装gsap npm i gsap 创建Gsap.vue文件 <script setup> import {reactive, watch} from "vue"; import gsap from "gsap"; const props defineProps({value:{type:Number,default:0} }) cons…

多线程思维导图

多线程 线程是一个程序内部的一条执行流程 多线程的好处————消息通信&#xff0c;网页浏览等等 多线程是指从软硬件上实现多条执行流程的技术 并发和并行同时执行 多线程的创建 Java.Long包下的Thread类 定义一个子类…

RT-Thread使用HAL库实现双线程控制LED交替闪烁

如何创建工程我的其他文中你面有可以进去查看 1创建线程&#xff08;以动态方式实现&#xff09; 1-2创建函数入口 1-2启动函数 main.c文件源码 /** Copyright (c) 2006-2024, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date …

自动驾驶技术综述:附自动驾驶公司一览表

前言 自动驾驶技术是一项复杂的系统工程&#xff0c;涵盖了众多技术领域。本文将从硬件和软件两个方面&#xff0c;详细介绍自动驾驶汽车涉及的关键技术&#xff0c;希望能为您提供有益的参考。 一、硬件 自动驾驶汽车的实现离不开各种硬件的支持。以下是一张自动驾驶研究所…