内存映射文件

03/30/2017

本文内容

内存映射文件包含虚拟内存中文件的内容。 借助文件和内存空间之间的这种映射,应用(包括多个进程)可以直接对内存执行读取和写入操作,从而修改文件。 可以使用托管代码访问内存映射文件,就像本机 Windows 函数访问内存映射文件(如管理内存映射文件中所述)一样。

内存映射文件分为两种类型:

持久化内存映射文件

持久化文件是与磁盘上的源文件相关联的内存映射文件。 当最后一个进程处理完文件时,数据保存到磁盘上的源文件中。 此类内存映射文件适用于处理非常大的源文件。

非持久化内存映射文件

非持久化文件是不与磁盘上的文件相关联的内存映射文件。 当最后一个进程处理完文件时,数据会丢失,且文件被垃圾回收器回收。 此类文件适合创建共享内存,以进行进程内通信 (IPC)。

进程、视图和管理内存

可以跨多个进程共享内存映射文件。 进程可以映射到相同的内存映射文件,只需使用文件创建进程分配的通用名称即可。

必须创建整个或部分内存映射文件的视图,才能使用内存映射文件。 还可以为内存映射文件的同一部分创建多个视图,从而创建并发内存。 若要让两个视图一直处于并发状态,必须通过同一个内存映射文件创建它们。

如果文件大于可用于内存映射的应用程序逻辑内存空间(在 32 位计算机中为 2 GB),可能也有必要使用多个视图。

视图分为以下两种类型:流访问视图和随机访问视图。 使用流访问视图,可以顺序访问文件;建议对非持久化文件和 IPC 使用这种类型。 随机访问视图是处理持久化文件的首选类型。

由于内存映射文件是通过操作系统的内存管理程序进行访问,因此文件会被自动分区到很多页面,并根据需要进行访问。 无需自行处理内存管理。

下图展示了多个进程如何同时对同一个内存映射文件有多个重叠视图。

下图显示了内存映射文件的多个重叠视图:

使用内存映射文件编程

下表列出了与使用内存映射文件对象及其成员相关的指南。

安全性

可以在创建内存映射文件时应用访问权限,具体操作是运行以下需要将 MemoryMappedFileAccess 枚举用作参数的方法:

若要指定打开现有内存映射文件所需的访问权限,可以运行需要将 MemoryMappedFileRights 用作参数的 OpenExisting 方法。

若要将新的或更改后的访问规则应用于内存映射文件,请使用 SetAccessControl 方法。 若要从现有文件检索访问或审核规则,请使用 GetAccessControl 方法。

示例

持久化内存映射文件

CreateFromFile 方法通过磁盘上的现有文件创建内存映射文件。

下面的示例为极大文件的一部分创建内存映射视图,并控制其中一部分。

using System;

using System.IO;

using System.IO.MemoryMappedFiles;

using System.Runtime.InteropServices;

class Program

{

static void Main(string[] args)

{

long offset = 0x10000000; // 256 megabytes

long length = 0x20000000; // 512 megabytes

// Create the memory-mapped file.

using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\ExtremelyLargeImage.data", FileMode.Open,"ImgA"))

{

// Create a random access view, from the 256th megabyte (the offset)

// to the 768th megabyte (the offset plus length).

using (var accessor = mmf.CreateViewAccessor(offset, length))

{

int colorSize = Marshal.SizeOf(typeof(MyColor));

MyColor color;

// Make changes to the view.

for (long i = 0; i < length; i += colorSize)

{

accessor.Read(i, out color);

color.Brighten(10);

accessor.Write(i, ref color);

}

}

}

}

}

public struct MyColor

{

public short Red;

public short Green;

public short Blue;

public short Alpha;

// Make the view brighter.

public void Brighten(short value)

{

Red = (short)Math.Min(short.MaxValue, (int)Red + value);

Green = (short)Math.Min(short.MaxValue, (int)Green + value);

Blue = (short)Math.Min(short.MaxValue, (int)Blue + value);

Alpha = (short)Math.Min(short.MaxValue, (int)Alpha + value);

}

}Imports System.IO

Imports System.IO.MemoryMappedFiles

Imports System.Runtime.InteropServices

Class Program

Sub Main()

Dim offset As Long = &H10000000 ' 256 megabytes

Dim length As Long = &H20000000 ' 512 megabytes

' Create the memory-mapped file.

Using mmf = MemoryMappedFile.CreateFromFile("c:\ExtremelyLargeImage.data", FileMode.Open, "ImgA")

' Create a random access view, from the 256th megabyte (the offset)

' to the 768th megabyte (the offset plus length).

Using accessor = mmf.CreateViewAccessor(offset, length)

Dim colorSize As Integer = Marshal.SizeOf(GetType(MyColor))

Dim color As MyColor

Dim i As Long = 0

' Make changes to the view.

Do While (i < length)

accessor.Read(i, color)

color.Brighten(10)

accessor.Write(i, color)

i += colorSize

Loop

End Using

End Using

End Sub

End Class

Public Structure MyColor

Public Red As Short

Public Green As Short

Public Blue As Short

Public Alpha As Short

' Make the view brighter.

Public Sub Brighten(ByVal value As Short)

Red = CType(Math.Min(Short.MaxValue, (CType(Red, Integer) + value)), Short)

Green = CType(Math.Min(Short.MaxValue, (CType(Green, Integer) + value)), Short)

Blue = CType(Math.Min(Short.MaxValue, (CType(Blue, Integer) + value)), Short)

Alpha = CType(Math.Min(Short.MaxValue, (CType(Alpha, Integer) + value)), Short)

End Sub

End Structure

若要查看翻译为非英语语言的代码注释,请在 此 GitHub 讨论问题中告诉我们。

下面的示例为另一个进程打开相同的内存映射文件。

using System;

using System.IO.MemoryMappedFiles;

using System.Runtime.InteropServices;

class Program

{

static void Main(string[] args)

{

// Assumes another process has created the memory-mapped file.

using (var mmf = MemoryMappedFile.OpenExisting("ImgA"))

{

using (var accessor = mmf.CreateViewAccessor(4000000, 2000000))

{

int colorSize = Marshal.SizeOf(typeof(MyColor));

MyColor color;

// Make changes to the view.

for (long i = 0; i < 1500000; i += colorSize)

{

accessor.Read(i, out color);

color.Brighten(20);

accessor.Write(i, ref color);

}

}

}

}

}

public struct MyColor

{

public short Red;

public short Green;

public short Blue;

public short Alpha;

// Make the view brigher.

public void Brighten(short value)

{

Red = (short)Math.Min(short.MaxValue, (int)Red + value);

Green = (short)Math.Min(short.MaxValue, (int)Green + value);

Blue = (short)Math.Min(short.MaxValue, (int)Blue + value);

Alpha = (short)Math.Min(short.MaxValue, (int)Alpha + value);

}

}Imports System.IO.MemoryMappedFiles

Imports System.Runtime.InteropServices

Class Program

Public Shared Sub Main(ByVal args As String())

' Assumes another process has created the memory-mapped file.

Using mmf = MemoryMappedFile.OpenExisting("ImgA")

Using accessor = mmf.CreateViewAccessor(4000000, 2000000)

Dim colorSize As Integer = Marshal.SizeOf(GetType(MyColor))

Dim color As MyColor

' Make changes to the view.

Dim i As Long = 0

While i < 1500000

accessor.Read(i, color)

color.Brighten(30)

accessor.Write(i, color)

i += colorSize

End While

End Using

End Using

End Sub

End Class

Public Structure MyColor

Public Red As Short

Public Green As Short

Public Blue As Short

Public Alpha As Short

' Make the view brigher.

Public Sub Brighten(ByVal value As Short)

Red = CShort(Math.Min(Short.MaxValue, CInt(Red) + value))

Green = CShort(Math.Min(Short.MaxValue, CInt(Green) + value))

Blue = CShort(Math.Min(Short.MaxValue, CInt(Blue) + value))

Alpha = CShort(Math.Min(Short.MaxValue, CInt(Alpha) + value))

End Sub

End Structure

非持久化内存映射文件

CreateNew 和 CreateOrOpen 方法创建未映射到磁盘上现有文件的内存映射文件。

下面的示例包含三个独立进程(控制台应用),以将布尔值写入内存映射文件。 各操作按下面的顺序发生:

Process A 创建内存映射文件,并向其中写入值。

Process B 打开内存映射文件,并向其中写入值。

Process C 打开内存映射文件,并向其中写入值。

Process A 读取并显示内存映射文件中的值。

在 Process A 处理完内存映射文件后,此文件立即被垃圾回收器回收。

若要运行此示例,请按照以下步骤操作:

编译应用并打开三个命令提示符窗口。

在第一个命令提示符窗口中,运行 Process A。

在第二个命令提示符窗口中,运行 Process B。

返回到 Process A,再按 Enter。

在第三个命令提示符窗口中,运行 Process C。

返回到 Process A,再按 Enter。

Process A 的输出如下所示:

Start Process B and press ENTER to continue.

Start Process C and press ENTER to continue.

Process A says: True

Process B says: False

Process C says: True

Process A

using System;

using System.IO;

using System.IO.MemoryMappedFiles;

using System.Threading;

class Program

{

// Process A:

static void Main(string[] args)

{

using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 10000))

{

bool mutexCreated;

Mutex mutex = new Mutex(true, "testmapmutex", out mutexCreated);

using (MemoryMappedViewStream stream = mmf.CreateViewStream())

{

BinaryWriter writer = new BinaryWriter(stream);

writer.Write(1);

}

mutex.ReleaseMutex();

Console.WriteLine("Start Process B and press ENTER to continue.");

Console.ReadLine();

Console.WriteLine("Start Process C and press ENTER to continue.");

Console.ReadLine();

mutex.WaitOne();

using (MemoryMappedViewStream stream = mmf.CreateViewStream())

{

BinaryReader reader = new BinaryReader(stream);

Console.WriteLine("Process A says: {0}", reader.ReadBoolean());

Console.WriteLine("Process B says: {0}", reader.ReadBoolean());

Console.WriteLine("Process C says: {0}", reader.ReadBoolean());

}

mutex.ReleaseMutex();

}

}

}Imports System.IO

Imports System.IO.MemoryMappedFiles

Imports System.Threading

Module Module1

' Process A:

Sub Main()

Using mmf As MemoryMappedFile = MemoryMappedFile.CreateNew("testmap", 10000)

Dim mutexCreated As Boolean

Dim mTex As Mutex = New Mutex(True, "testmapmutex", mutexCreated)

Using Stream As MemoryMappedViewStream = mmf.CreateViewStream()

Dim writer As BinaryWriter = New BinaryWriter(Stream)

writer.Write(1)

End Using

mTex.ReleaseMutex()

Console.WriteLine("Start Process B and press ENTER to continue.")

Console.ReadLine()

Console.WriteLine("Start Process C and press ENTER to continue.")

Console.ReadLine()

mTex.WaitOne()

Using Stream As MemoryMappedViewStream = mmf.CreateViewStream()

Dim reader As BinaryReader = New BinaryReader(Stream)

Console.WriteLine("Process A says: {0}", reader.ReadBoolean())

Console.WriteLine("Process B says: {0}", reader.ReadBoolean())

Console.WriteLine("Process C says: {0}", reader.ReadBoolean())

End Using

mTex.ReleaseMutex()

End Using

End Sub

End Module

Process B

using System;

using System.IO;

using System.IO.MemoryMappedFiles;

using System.Threading;

class Program

{

// Process B:

static void Main(string[] args)

{

try

{

using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))

{

Mutex mutex = Mutex.OpenExisting("testmapmutex");

mutex.WaitOne();

using (MemoryMappedViewStream stream = mmf.CreateViewStream(1, 0))

{

BinaryWriter writer = new BinaryWriter(stream);

writer.Write(0);

}

mutex.ReleaseMutex();

}

}

catch (FileNotFoundException)

{

Console.WriteLine("Memory-mapped file does not exist. Run Process A first.");

}

}

}Imports System.IO

Imports System.IO.MemoryMappedFiles

Imports System.Threading

Module Module1

' Process B:

Sub Main()

Try

Using mmf As MemoryMappedFile = MemoryMappedFile.OpenExisting("testmap")

Dim mTex As Mutex = Mutex.OpenExisting("testmapmutex")

mTex.WaitOne()

Using Stream As MemoryMappedViewStream = mmf.CreateViewStream(1, 0)

Dim writer As BinaryWriter = New BinaryWriter(Stream)

writer.Write(0)

End Using

mTex.ReleaseMutex()

End Using

Catch noFile As FileNotFoundException

Console.WriteLine("Memory-mapped file does not exist. Run Process A first." & vbCrLf & noFile.Message)

End Try

End Sub

End Module

Process C

using System;

using System.IO;

using System.IO.MemoryMappedFiles;

using System.Threading;

class Program

{

// Process C:

static void Main(string[] args)

{

try

{

using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap"))

{

Mutex mutex = Mutex.OpenExisting("testmapmutex");

mutex.WaitOne();

using (MemoryMappedViewStream stream = mmf.CreateViewStream(2, 0))

{

BinaryWriter writer = new BinaryWriter(stream);

writer.Write(1);

}

mutex.ReleaseMutex();

}

}

catch (FileNotFoundException)

{

Console.WriteLine("Memory-mapped file does not exist. Run Process A first, then B.");

}

}

}Imports System.IO

Imports System.IO.MemoryMappedFiles

Imports System.Threading

Module Module1

' Process C:

Sub Main()

Try

Using mmf As MemoryMappedFile = MemoryMappedFile.OpenExisting("testmap")

Dim mTex As Mutex = Mutex.OpenExisting("testmapmutex")

mTex.WaitOne()

Using Stream As MemoryMappedViewStream = mmf.CreateViewStream(2, 0)

Dim writer As BinaryWriter = New BinaryWriter(Stream)

writer.Write(1)

End Using

mTex.ReleaseMutex()

End Using

Catch noFile As FileNotFoundException

Console.WriteLine("Memory-mapped file does not exist. Run Process A first, then B." & vbCrLf & noFile.Message)

End Try

End Sub

End Module

请参阅

c语言 内存映射文件,内存映射文件相关推荐

  1. linux 文件IO与内存映射:内存映射

    前言 前面几篇我们学习了用户空间的IO缓冲区,以及IO缓冲区的分散聚合IO技术. 为了减少系统调用的次数,提升系统性能,操作系统开发者门提出了这么多的缓存技术. 但是到这里这些技术同样有不足的地方:不 ...

  2. java大文件读写操作,java nio 之MappedByteBuffer,高效文件/内存映射

    http://langgufu.iteye.com/blog/2107023 java处理大文件,一般用BufferedReader,BufferedInputStream这类带缓冲的Io类,不过如果 ...

  3. mmap映射大于4g的文件_iOS文件内存映射——MMAP

    前言 最近一段项目上总是出现一些因为文件没有及时保存而产生的问题,因此小编就在网上寻找到了这个文件存储方法mmap,这里为大家进行下简单的介绍. 简介 首先我们需要对iOS中各App的运行环境进行了解 ...

  4. java 内存映射文件 主要应用_VC++中使用内存映射文件处理大文件(3)

    -- // 创建文件内核对象,其句柄保存于hFile HANDLE hFile = CreateFile("Recv1.zip", GENERIC_WRITE | GENERIC_ ...

  5. system文件_大文件拷贝,试试NIO的内存映射

    最近项目里有个需求需要实现文件拷贝,在java中文件拷贝流的读写,很容易就想到IO中的InputStream和OutputStream之类的,但是上网查了一下文件拷贝也是有很多种方法的,除了IO,还有 ...

  6. 内存映射文件进行写文件和读文件有啥不同_Linux中的mmap映射 [二]

    来看下上文介绍的mmap()的函数原型是怎样的: #include <sys/mman.h> void *mmap(void *addr, size_t length, int prot, ...

  7. 文件内存映射mmap解决大文件快速读写问题和进程间共享内存

    mmap函数主要用途有三个: 1.将一个普通文件映射到内存中,通常在需要对文件进行频繁读写时使用,这样用内存读写取代I/O读写,以获得较高的性能: 2.将特殊文件进行匿名内存映射,可以为关联进程提供共 ...

  8. 【JavaNIO的深入研究4】内存映射文件I/O,大文件读写操作,Java nio之MappedByteBuffer,高效文件/内存映射...

    内存映射文件能让你创建和修改那些因为太大而无法放入内存的文件.有了内存映射文件,你就可以认为文件已经全部读进了内存,然后把它当成一个非常大的数组来访问.这种解决办法能大大简化修改文件的代码. file ...

  9. 学习笔记之ByteBuffer使用和实现以及文件内存映射

    转载自  学习笔记之ByteBuffer使用和实现以及文件内存映射 ByteBuffer和CharBuffer等其它Buffer的直接子类一样,顾名思义,就是存取字节的Buffer.很多数据最终在和底 ...

最新文章

  1. php1为true,php有一个预定义的常量true,值为整数1,这该如何理解?
  2. 将台式机组成云服务器_云桌面是什么?用了两年云桌面的真实感受
  3. springMVC笔记系列——RequestParam注解
  4. Cubieboard安装Debian在Nand中
  5. 【跃迁之路】【425天】程序员高效学习方法论探索系列(实验阶段182-2018.04.06)...
  6. 阿里云首席架构师解读开源和云端结合的三大优势
  7. Oracle字符到数值转换错误
  8. 为什么需要API网关?
  9. Separating Axis Theorem(SAT)
  10. 邮件客户端里的网络设置
  11. 一款不错的工具:aardio
  12. java 泛型参数具体类型获取、泛型返回具体类型获取
  13. 学计算机做纸质笔记,详细图文教你康奈尔大学推荐的超级笔记法,只要一张A4纸张,你也可以做学霸...
  14. 工程计算和数据科学中常用的9种测量距离
  15. 【SpringBoot教程】SpringBoot开发HTTP接口GET请求实战
  16. Java自学之路——构造器(Constructor)
  17. windows如何设置全角半角切换
  18. Abp Vnext新增模块
  19. 越是聪明人,越懂得下笨功夫
  20. amber分子动力学模拟干货总结

热门文章

  1. 学习微信小程序开发文档总结
  2. 从零开始搭建EasyDarwin环境——Linux系统开发环境Golang的搭建
  3. 全球及中国电子废弃物回收处理市场投资方向建议与发展策略研究报告2022-2028年
  4. android9.0系统耗电量大,升级EMUI9.0后太耗电?五招帮你摆平!
  5. 安川机器人编程指令含义
  6. Redis源代码分析(十一年)--- memtest内存测试
  7. 联想LJ2655DN激光打印机清零方法
  8. Git详解之七 自定义Git
  9. 用来测试的在线小视频url地址
  10. 小型双轮差速底盘三灰度循迹功能的实现