首页 > 系统相关 >内存映射文件

内存映射文件

时间:2024-11-21 09:31:52浏览次数:1  
标签:文件 读取 映射 System 访问 内存

内存映射文件

内存映射文件简介

内存映射文件(Memory-Mapped File)是一种将文件或其他对象映射到进程地址空间的机制,使得应用程序可以像访问内存一样访问文件内容。以下是内存映射文件的主要特点和工作原理:

主要特点

  1. 直接内存访问
    • 应用程序可以通过指针直接访问文件内容,而不需要通过传统的读写操作。这提高了文件访问的效率。
  2. 共享内存
    • 内存映射文件可以被多个进程共享,使得它们可以同时访问同一个文件。这在进程间通信(IPC)中非常有用。
  3. 延迟加载
    • 文件的内容并不是立即加载到内存中,而是在实际访问时才加载。这可以节省内存资源。
  4. 自动同步
    • 对内存映射区域的修改会自动反映到文件中,反之亦然。这意味着对内存的更改会直接影响到文件内容。

工作原理

  1. 创建内存映射文件

    • 操作系统提供的 API(如 Windows 的 CreateFileMappingMapViewOfFile)用于创建内存映射文件。
  2. 映射文件到内存

    • 通过将文件的某个部分映射到进程的虚拟地址空间,进程可以使用指针来访问文件内容。
  3. 访问和修改

    • 应用程序可以像访问普通数组一样访问映射的内存区域。对该区域的写入操作会直接修改文件内容。
  4. 解除映射

    • 当不再需要访问文件时,可以使用 API 解除映射,并释放相关资源。

优点

  1. **高性能**:由于数据直接在内存中访问,避免了频繁的磁盘I/O操作,因此读写速度非常快。
  2. **简单易用**:使用内存映射文件可以像操作普通内存一样操作文件内容,简化了代码逻辑。
  3. **节省内存**:只有实际访问的数据才会被加载到内存中,未访问的部分不会占用内存。
  4. **共享内存**:多个进程可以同时映射同一文件的不同部分,实现进程间的共享内存通信。

缺点

  1. **内存限制**:虽然内存映射文件可以映射大文件,但实际使用的物理内存仍然受限于系统的可用内存。
  2. **复杂性**:相对于传统的文件读写操作,内存映射文件的使用可能稍微复杂一些,需要理解虚拟内存和页面管理的概念。
  3. **数据一致性**:在多进程或多线程环境中,需要额外的同步机制来保证数据的一致性。

应用场景

  • 大文件处理:在处理大文件时,内存映射文件可以避免将整个文件加载到内存中。
  • 数据库:许多数据库系统使用内存映射文件来提高数据访问速度。
  • 进程间通信:通过共享内存映射文件,多个进程可以高效地交换数据。

示例

读取内存映射文件

using System;
using System.IO;
using System.IO.MemoryMappedFiles;

class Program
{
    static void Main()
    {
        string filePath = "path/to/your/file.txt";
        long fileSize = new FileInfo(filePath).Length;

        // 创建内存映射文件
        using (MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(filePath, FileMode.Open))
        {
            // 创建视图访问器
            using (MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(0, fileSize))
            {
                // 读取文件内容
                byte[] buffer = new byte[fileSize];
                accessor.ReadArray(0, buffer, 0, buffer.Length);

                // 将字节数组转换为字符串
                string content = System.Text.Encoding.UTF8.GetString(buffer);
                Console.WriteLine(content);
            }
        }
    }
}

写入内存映射文件

using System;
using System.IO;
using System.IO.MemoryMappedFiles;

class Program
{
    static void Main()
    {
        string filePath = "path/to/your/file.txt";
        string content = "Hello, Memory-Mapped Files!";

        // 创建内存映射文件
        using (MemoryMappedFile mmf = MemoryMappedFile.CreateFromFile(filePath, FileMode.Create, maximumSize: (long)content.Length))
        {
            // 创建视图访问器
            using (MemoryMappedViewAccessor accessor = mmf.CreateViewAccessor(0, content.Length))
            {
                // 将字符串转换为字节数组
                byte[] buffer = System.Text.Encoding.UTF8.GetBytes(content);

                // 写入数据
                accessor.WriteArray(0, buffer, 0, buffer.Length);
            }
        }
    }
}

这段代码演示了如何创建和使用内存映射文件来存储和读取数据。

读取测试

这里我们分别使用IO的方式和 MMF方式来读取一个1G多的模型文件。IO方式耗时2000ms,MMF方式560ms

测试代码

[Button("TestReadByMemoryMappedFile")]
    void TestReadByMemoryMappedFile()
    {
        using (CustomTimer timer = new CustomTimer("ReadByMemoryMappedFile"))
        {
            ReadByMemoryMappedFile();
        }

        using (CustomTimer timer = new CustomTimer("ReadByIO"))
        {
            ReadByIO();
        }
    }

    private void ReadByIO()
    {
        string filePath = "E:\\A.ply";

        // 确保文件存在
        if (!System.IO.File.Exists(filePath))
        {
            Debug.Log("文件不存在: " + filePath);
            return;
        }

        // 读取文件内容
        byte[] buffer = System.IO.File.ReadAllBytes(filePath);

        // 将字节数组转换为字符串并输出
        string fileContent = System.Text.Encoding.UTF8.GetString(buffer);
        Debug.Log(fileContent.Length);
    }


    void ReadByMemoryMappedFile()
    {
        string filePath = "E:\\A.ply";

        // 确保文件存在
        if (!System.IO.File.Exists(filePath))
        {
            Debug.Log("文件不存在: " + filePath);
            return;
        }

        // 获取文件大小
        long fileSize = new System.IO.FileInfo(filePath).Length;

        // 创建内存映射文件
        using var mmf = System.IO.MemoryMappedFiles.MemoryMappedFile.CreateFromFile(filePath, System.IO.FileMode.Open, "PlyMap", fileSize);
        // 创建视图流
        using var stream = mmf.CreateViewStream();
        // 读取文件内容
        byte[] buffer = new byte[fileSize];
        stream.Read(buffer, 0, buffer.Length);

        // 将字节数组转换为字符串并输出
        string fileContent = System.Text.Encoding.UTF8.GetString(buffer);
        Debug.Log(fileContent.Length);
    }

测试结果

内存映射文件读取文件

内存映射文件与传统IO方式的区别

1. 访问方式

  • 传统读取
    • 你需要通过文件操作函数(如 Open, Read, Write, Close)逐步读取文件。
    • 每次读取时,操作系统会从磁盘将数据加载到内存,过程较为繁琐。
  • 内存映射文件
    • 文件的内容被直接映射到进程的地址空间,你可以像访问普通数组一样访问文件内容。
    • 你只需简单地使用指针或索引来读取和修改数据。

2. 性能

  • 传统读取
    • 每次读取都涉及系统调用,开销较大,尤其是处理大文件时会频繁进行磁盘 I/O 操作,可能导致性能瓶颈。
  • 内存映射文件
    • 通过内存直接访问,减少了磁盘 I/O 的次数,通常能提供更好的性能,特别是在处理大文件或频繁读写时。

3. 内存管理

  • 传统读取
    • 你需要手动管理内存,读取的数据可能需要存储在一个数组或缓冲区中,使用完后需要释放。
  • 内存映射文件
    • 操作系统自动管理内存映射区域,内存不足时会自动将不常用的数据换出,保持高效的内存使用。

4. 共享和进程间通信

  • 传统读取
    • 如果多个进程需要访问同一文件,通常需要使用文件锁或其他机制来进行协调,复杂度较高。
  • 内存映射文件
    • 可以轻松实现多个进程共享同一个内存映射文件,进程间可以直接访问同一块内存区域,简化了进程间通信。

5. 延迟加载

  • 传统读取
    • 通常需要一次性读取整个文件或分块读取,可能浪费内存。
  • 内存映射文件
    • 只有在实际访问时,相关数据才会被加载到内存中,避免了不必要的内存占用。

读书

将内存映射文件和传统 I/O 比作读一本书,可以通过以下几个方面来理解它们之间的区别:

1. 获取方式

  • 内存映射文件
    • 就像把整本书的内容直接放在桌面上,你可以随时打开、查看任何一页,而不需要去书架上拿书。
    • 这种方式允许你直接访问内存中的数据,速度快。
  • 传统 I/O
    • 需要每次去书架上取书,查阅时逐页翻阅。
    • 每次读取内容都需要进行系统调用,速度较慢。

2. 访问方式

  • 内存映射文件
    • 你可以随机访问书中的任意一页,随时跳转到任何章节,效率高。
    • 内存中的数据可以被多个进程共享,方便快速访问。
  • 传统 I/O
    • 需要按顺序逐页查阅,不能快速跳转,效率低。
    • 每次读取都需要从磁盘加载数据,可能会造成延迟。

3. 性能

  • 内存映射文件
    • 由于数据已经在内存中,访问速度快,减少了磁盘 I/O 操作。
    • 适合处理大文件和需要频繁访问的场景。
  • 传统 I/O
    • 每次读取都涉及到磁盘操作,性能较低,尤其是在处理大文件时。
    • 适合小文件或简单的读取操作。

4. 资源管理

  • 内存映射文件
    • 操作系统管理内存映射,自动处理数据的加载和卸载。
    • 更高效地利用内存,减少了内存和磁盘之间的复制。
  • 传统 I/O
    • 程序员需要手动管理文件的打开、读取和关闭,容易出错。
    • 可能导致资源浪费,例如未及时关闭文件。

总结

内存映射文件

内存映射文件百科

内存映射文件视频

Microsoft MMP

标签:文件,读取,映射,System,访问,内存
From: https://www.cnblogs.com/Firepad-magic/p/18559917

相关文章

  • Linux基础——ISO修复kernel-4.19.0-grub问题:/boot文件损坏
    1、挂载bc8镜像#Trobleshooting进入2、进入修复模式3、进入救援模式4、切换用户根目录/mnt/sysimagechroot/mnt/sysroot/5、挂载ios镜像数据包mkdir-p/mnt/tempmount/dev/sr0/mnt/temp可以尝试以下两种挂载镜像方式iso9660文件系统mount-oiso9660/d......
  • 数据流转无忧:企业文件传输管控的智能化解决方案!
    受管文件传输管控适用于各个行业,特别是那些需要处理大量敏感数据和重要文件的行业,如集成电路半导体、金融、高科技、高新制造、医疗医药等。在这些行业中,确保文件的安全性和合规性对于企业的运营和声誉至关重要。一、受管文件传输管控的考量因素1、更高的安全性要求分发和访问......
  • 反射内存卡 TH-PXIE-211 单模 PXIE接口 256M 传输距离 10km
    特点1.高速数据传输:‌反射内存卡能够实现极高的数据传输速度,‌这是其最显著的特点之一。‌数据传输速度可达到微秒级或百纳秒级,‌大大提升了数据处理的实时性。‌这种高速传输能力使得反射内存卡非常适用于需要实时数据共享和处理的场合。‌2.低延迟:‌反射内存卡通过纯硬件方......
  • FTP的替代者:如何安全可控地实现文件外发管理?
    文件外发管理是指对企业或组织内部电子文档进行外部传递的管控过程。由于电子文档具有易拷贝、易扩散、易传播的特性,如果带有核心资产或组织机密的信息文档在业务交流中发生泄露,将会给组织带来政治、商业等方面的重大损失。一、文件外发管理的必要性1.保护敏感信息:文件外发管理......
  • 一文看懂做大模型备案的关键点【评估测试题+备案源文件】
    文章目录(一)适用主体(二)语料安全(三)模型安全(四)安全措施要求(五)词库要求(六)安全评估要求(七)附录大模型备案材料源文件2024年3月1日,我国通过了《生成式人工智能服务安全基本要求》(以下简称《AIGC安全要求》),这是目前我国第一部有关AIGC服务安全性方面的技术性指导文件,对语料安全......
  • 小工具-markdown文件导入博客园cnblogs
    开源一个批量导出csdn博客,导入博客园cnblogs工具,供大家备份博客、迁移博客使用,windows客户端工具,操作简便易用。这篇文章介绍如何批量导入博客园网站。软件界面,选择【博客园导入】获取博客园登录cookie获取博客园导入xsrf-token,需要先手动导入一篇markdown文章,获取tok......
  • 基于Java+Springboot+Jpa+Mysql实现的在线网盘文件分享系统功能设计与实现四
    一、前言介绍:免费学习:猿来入此1.1项目摘要在线网盘文件分享系统的课题背景主要源于现代社会对数字化信息存储和共享需求的日益增长。随着互联网的普及和技术的快速发展,人们越来越依赖电子设备来存储和传输各种类型的数据文件。然而,传统的本地存储方式存在诸多不便,如空间有限、......
  • 文件上传接口文档
    一、文件上传1、基本信息:请求路径:/upload请求方式:POST接口描述:该接口用于用户上传其本地的头像或者商品图片(单文件)2、请求参数:请求参数格式:multipart/form-data参数名称说明类型是否必须备注file表单中文件请求参数名file是3、请求样例:无4、响应......
  • 基于Java+Springboot+Jpa+Mysql实现的在线网盘文件分享系统功能设计与实现三
    一、前言介绍:免费学习:猿来入此1.1项目摘要在线网盘文件分享系统的课题背景主要源于现代社会对数字化信息存储和共享需求的日益增长。随着互联网的普及和技术的快速发展,人们越来越依赖电子设备来存储和传输各种类型的数据文件。然而,传统的本地存储方式存在诸多不便,如空间有限、......
  • WEB攻防-PHP应用&文件包含&LFI&RFI&伪协议编码算法&无文件利用&黑白盒
    什么是文件包含1、原理程序开发人员通常会把可重复使用的函数写到单个文件中,在使用某些函数时,直接调用此文件,而无须再次编写,这种调用文件的过程一般被称为文件包含。在包含文件的过程中,如果文件能进行控制(如进行替换和修改),则存储文件包含漏洞白盒发现:在php代码中如果存......