内存映射文件使用方法

合集下载

内存映射原理

内存映射原理

内存映射原理
内存映射是一种将磁盘文件映射到内存的操作。

在内存中建立一个虚拟地址空间,该空间与磁盘文件相对应,使得我们可以像访问内存一样访问磁盘文件的内容。

内存映射的原理是通过将磁盘文件的内容映射到内存的一段连续地址空间中。

在内存中指定一个缓冲区,当对这个缓冲区进行读写操作时,实际上是在对磁盘文件进行读写操作。

读取该内存区域的数据时,由于数据已经在内存中,所以读取速度非常快。

内存映射的过程主要包括以下几个步骤:
1. 打开文件:使用文件操作相关的API函数打开需要映射到内存的文件。

2. 创建映射区域:使用内存映射相关的API函数,创建一个映射区域。

将文件的某个区域映射到内存。

3. 访问映射区域:获得映射到内存中的虚拟地址,可以直接对其进行读写操作,就像操作内存一样。

4. 保存修改:如果对映射区域进行了修改,需要使用相关的API函数将修改的内容保存回磁盘文件。

通过内存映射,可以实现大文件的快速读写,提高文件的访问速度。

此外,多个进程可以通过映射同一个文件,实现共享内
存的功能,简化进程间通信的实现。

但需要注意的是,对于大文件的内存映射可能会消耗大量的系统内存,需要进行适当的调优和管理。

内存映射文件

内存映射文件

内存映射文件:内存映射文件有三种,第一种是可执行文件的映射,第二种是数据文件的映射,第三种是借助页面交换文件的内存映射.应用程序本身可以使用后两种内存映射.1.可执行文件映射:Windows在执行一个Win32应用程序时使用的是内存映射文件技术.系统先在进程地址空间的0x00400000以上保留一个足够大的虚拟地址空间(0x00400000以下是由系统管理的),然后把应用程序所在的磁盘空间作为虚拟内存提交到这个保留的地址空间中去(我的理解也就是说,虚拟内存是由物理内存和磁盘上的页面文件组成的,现在应用程序所在的磁盘空间就成了虚拟地址的页面文件).做好这些准备后,系统开始执行这个应用程序,由于这个应用程序的代码不在内存中(在页面文件中),所以在执行第一条指令的时候会产生一个页面错误(页面错误也就是说,系统所访问的数据不在内存中),系统分配一块内存把它映射到0x00400000处,把实际的代码或数据读入其中(系统分配一块内存区域,把它要访问的在页面文件中的数据读入到这块内存中,需在注意是系统读入代码或数据是一页一页读入的),然后可以继续执行了.当以后要访问的数据不在内存中时,就可以通过前面的机制访问数据.对于Win32DLL的映射也是同样,不过DLL文件应该是被Win32进程共享的(我想应该被映射到x80000000以后,因为0x80000000-0xBFFFFFFF是被共享的空间).当系统在另一个进程中执行这个应用程序时,系统知道这个程序已经有了一个实例,程序的代码和数据已被读到内存中,所以系统只需把这块内存在映射到新进程的地址空间即可,这样不就实现了在多个进程间共享数据了吗!然而这种共享数据只是针对只读数据,如果进程改写了其中的代码和数据,操作系统就会把修改的数据所在的页面复制一份到改写的进程中(我的理解也就是说共享的数据没有改变,进程改写的数据只是共享数据的一份拷贝,其它进程在需要共享数据时还是共享没有改写的数据),这样就可以避免多个进程之间的相互干扰.2.数据文件的内存映射:数据文件的内存映射原理与可执行文件内存映射原理一样.先把数据文件的一部分映射到虚拟地址空间的0x80000000 - 0xBFFFFFFF,但没有提交实际内存(也就是说作为页面文件),当有指令要存取这段内存时同样会产生页面错误异常.操作系统捕获到这个异常后,分配一页内存,映射内存到发生异常的位置,然后把要访问的数据读入到这块内存,继续执行刚才产生异常的指令(这里我理解的意思是把刚才产生异常的指令在执行一次,这次由于数据已经映射到内存中,指令就可以顺利执行过去),由上面的分析可知,应用程序访问虚拟地址空间时由操作系统管理数据在读入等内容,应用程序本身不需要调用文件的I/O函数(这点我觉得很重要,也就是为什么使用内存映射文件技术对内存的访问就象是对磁盘上的文件访问一样).3.基于页面交换文件的内存映射:内存映射的第三种情况是基于页面交换文件的.一个Win32进程利用内存映射文件可以在进程共享的地址空间保留一块区域(0x8000000 - 0xBFFFFFFF),这块区域与系统的页面交换文件相联系.我们可以用这块区域来存储临时数据,但更常见的做法是利用这块区域与其他进程通信(因为0x80000000以上是系统空间,进程切换只是私有地址空间,系统空间是所有进程共同使用的),这样多进程间就可以实现通信了.事实上Win32多进程间通信都是使用的内存映射文件技术,如PostMessage(),SentMessage()函数,在内部都使用内存映射文件技术.使用内存映射文件的方法:1.利用内存映射文件进行文件I/O操作:CreateFile()-->CreateFileMapping()-->MapViewOfFile()......2.利用内存映射文件实现Win32进程间通信:我只介绍两种常用的方法:第一种方法:两个进程使用同一个文件映射核心对象,打开各自的视图,或者父进程把自己创建的文件映射核心对象继承给子进程使用.这种方法比较安全有效.第二种方法:基于页面交换文件的内存映射对象.在调用CreateFileMapping()函数时,传递的文件句柄为0xFFFFFFFF,系统就从页面交换文件中提交物理内存,然后进程之间按照第一种方法进程通信.这种方法不用事先准备一个特殊的文件(也就是说不用事先调用CreateFile()返回一个文件的句柄),非常方便.。

内存映射文件(专门读写大文件)

内存映射文件(专门读写大文件)

内存映射⽂件(专门读写⼤⽂件)引⾔ ⽂件操作是应⽤程序最为基本的功能之⼀,Win32 API和MFC均提供有⽀持⽂件处理的函数和类,常⽤的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。

⼀般来说,以上这些函数可以满⾜⼤多数场合的要求,但是对于某些特殊应⽤领域所需要的动辄⼏⼗GB、⼏百GB、乃⾄⼏TB的海量存储,再以通常的⽂件处理⽅法进⾏处理显然是⾏不通的。

⽬前,对于上述这种⼤⽂件的操作⼀般是以内存映射⽂件的⽅式来加以处理的,本⽂下⾯将针对这种Windows核⼼编程技术展开讨论。

内存映射⽂件概述 内存⽂件映射也是Windows的⼀种内存管理⽅法,提供了⼀个统⼀的内存管理特征,使应⽤程序可以通过内存指针对磁盘上的⽂件进⾏访问,其过程就如同对加载了⽂件的内存的访问。

通过⽂件映射这种使磁盘⽂件的全部或部分内容与进程虚拟地址空间的某个区域建⽴映射关联的能⼒,可以直接对被映射的⽂件进⾏访问,⽽不必执⾏⽂件I/O操作也⽆需对⽂件内容进⾏缓冲处理。

内存⽂件映射的这种特性是⾮常适合于⽤来管理⼤尺⼨⽂件的。

在使⽤内存映射⽂件进⾏I/O处理时,系统对数据的传输按页⾯来进⾏。

⾄于内部的所有内存页⾯则是由虚拟内存管理器来负责管理,由其来决定内存页⾯何时被分页到磁盘,哪些页⾯应该被释放以便为其它进程提供空闲空间,以及每个进程可以拥有超出实际分配物理内存之外的多少个页⾯空间等等。

由于虚拟内存管理器是以⼀种统⼀的⽅式来处理所有磁盘I/O的(以页⾯为单位对内存数据进⾏读写),因此这种优化使其有能⼒以⾜够快的速度来处理内存操作。

使⽤内存映射⽂件时所进⾏的任何实际I/O交互都是在内存中进⾏并以标准的内存地址形式来访问。

磁盘的周期性分页也是由操作系统在后台隐蔽实现的,对应⽤程序⽽⾔是完全透明的。

内存映射⽂件的这种特性在进⾏⼤⽂件的磁盘事务操作时将获得很⾼的效益。

快速读取内存文件-内存映射文件的方法

快速读取内存文件-内存映射文件的方法

快速读取内存⽂件-内存映射⽂件的⽅法
1、前⾔
Windows提供了3种进⾏内存管理的⽅法:
• 虚拟内存,最适合⽤来管理⼤型对象或结构数组。

• 内存映射⽂件,最适合⽤来管理⼤型数据流(通常来⾃⽂件)以及在单个计算机上运⾏的多个进程之间共享数据。

• 内存堆栈,最适合⽤来管理⼤量的⼩对象。

内存映射⽂件可以⽤于3个不同的⽬的
• 系统使⽤内存映射⽂件,以便加载和执⾏. exe和DLL⽂件。

这可以⼤⼤节省页⽂件空间和应⽤程序启动运⾏所需的时间。

• 可以使⽤内存映射⽂件来访问磁盘上的数据⽂件。

这使你可以不必对⽂件执⾏I/O操作,并且可以不必对⽂件内容进⾏缓存。

• 可以使⽤内存映射⽂件,使同⼀台计算机上运⾏的多个进程能够相互之间共享数据。

Windows确实提供了其他⼀些⽅法,以便在进程之间进⾏数据通信,但是这些⽅法都是使⽤内存映射⽂件来实现的,这使得内存映射⽂件成为单个计算机上的多个进程互相进⾏通信的最有效的⽅法。

参考博客:。

C++中使用内存映射文件处理大文件

C++中使用内存映射文件处理大文件

C++中使⽤内存映射⽂件处理⼤⽂件引⾔ ⽂件操作是应⽤程序最为基本的功能之⼀,Win32 API和MFC均提供有⽀持⽂件处理的函数和类,常⽤的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。

⼀般来说,以上这些函数可以满⾜⼤多数场合的要求,但是对于某些特殊应⽤领域所需要的动辄⼏⼗GB、⼏百GB、乃⾄⼏TB的海量存储,再以通常的⽂件处理⽅法进⾏处理显然是⾏不通的。

⽬前,对于上述这种⼤⽂件的操作⼀般是以内存映射⽂件的⽅式来加以处理的,本⽂下⾯将针对这种Windows核⼼编程技术展开讨论。

内存映射⽂件 内存映射⽂件与虚拟内存有些类似,通过内存映射⽂件可以保留⼀个地址空间的区域,同时将物理存储器提交给此区域,只是内存⽂件映射的物理存储器来⾃⼀个已经存在于磁盘上的⽂件,⽽⾮系统的页⽂件,⽽且在对该⽂件进⾏操作之前必须⾸先对⽂件进⾏映射,就如同将整个⽂件从磁盘加载到内存。

由此可以看出,使⽤内存映射⽂件处理存储于磁盘上的⽂件时,将不必再对⽂件执⾏I/O操作,这意味着在对⽂件进⾏处理时将不必再为⽂件申请并分配缓存,所有的⽂件缓存操作均由系统直接管理,由于取消了将⽂件数据加载到内存、数据从内存到⽂件的回写以及释放内存块等步骤,使得内存映射⽂件在处理⼤数据量的⽂件时能起到相当重要的作⽤。

另外,实际⼯程中的系统往往需要在多个进程之间共享数据,如果数据量⼩,处理⽅法是灵活多变的,如果共享数据容量巨⼤,那么就需要借助于内存映射⽂件来进⾏。

实际上,内存映射⽂件正是解决本地多个进程间数据共享的最有效⽅法。

内存映射⽂件并不是简单的⽂件I/O操作,实际⽤到了Windows的核⼼编程技术--内存管理。

所以,如果想对内存映射⽂件有更深刻的认识,必须对Windows操作系统的内存管理机制有清楚的认识,内存管理的相关知识⾮常复杂,超出了本⽂的讨论范畴,在此就不再赘述,感兴趣的读者可以参阅其他相关书籍。

文件映射 原理

文件映射 原理

文件映射原理
文件映射是一种计算机存储技术,其原理是将文件系统中的文件与内存中的地址空间进行对应。

通过文件映射,可以使文件在内存中的访问方式与访问普通内存相同,从而简化对文件的读写操作。

具体来说,文件映射通过以下步骤实现:
1. 打开文件:首先,需要使用文件系统提供的接口打开待映射的文件。

这个步骤通常包括指定文件名、路径等信息来定位文件。

2. 创建映射:接下来,需要调用操作系统提供的函数,将文件映射到内存中。

在Windows系统中,可使用CreateFileMapping函数来创建文件映射对象;而在Linux系统中,可以使用mmap函数完成映射。

3. 映射文件到内存:一旦创建了文件映射对象,就可以将其映射到进程的虚拟地址空间中。

文件映射可以将整个文件或者指定的部分映射到内存中,形成映射区域。

4. 内存操作:一旦映射成功,可以将内存中的映射区域当作普通的内存进行读写操作。

对映射区域的读写实际上是对文件的读写操作,映射区域的更新会直接影响到文件的内容。

5. 解除映射:当不再需要使用文件映射时,可以调用相应的函数解除映射。

在Windows系统中,使用CloseHandle函数来关
闭文件映射对象;在Linux系统中,可以使用munmap函数来解除映射。

文件映射的实现原理是利用操作系统的虚拟内存机制。

通过将文件映射到内存中的虚拟地址空间,使得对文件的读写操作可以通过内存地址来完成,而不需要使用文件系统相关的函数。

文件映射的好处是可以提高对文件的读写效率,因为内存访问要比文件访问速度更快。

此外,多个进程可以共享同一个文件的映射,实现数据的共享和通信。

【IT专家】使用.so(共享对象)中的内存映射文件

【IT专家】使用.so(共享对象)中的内存映射文件

本文由我司收集整编,推荐下载,如有疑问,请与我司联系使用.so(共享对象)中的内存映射文件使用.so(共享对象)中的内存映射文件[英]Using memory-mapped files from within a .so (shared object) I am getting a segfault when accessing shared memory(memory mapped file, using a fixed address of 0x60000000 ) from within a share object (.so).当从共享对象(.so)中访问共享内存(内存映射文件,使用固定地址0x60000000)时,我得到一个段错误。

We have many applications accessing this shared memory without difficulty. My app is different in that I create a small .so with it and the .so is the one calling mmap and accessing the shared memory.我们有很多应用程序毫无困难地访问此共享内存。

我的应用程序不同之处在于我用它创建一个小的.so 而.so 是调用mmap 并访问共享内存的.so。

The mmap() returns just fine. My requested address is returned back properly. But assoon as I try to access the memory from within this .so, it seg faults.mmap()返回正常。

我要求的地址已正确退回。

但是一旦我尝试从这个.so 中访问内存,就会出现故障。

I can’t figure out what is unique about a .so that would prevent it from accessing sharedmemory this way.我无法弄清楚.so 的独特之处在于它会阻止它以这种方式访问共享内存。

SD卡映射方法

SD卡映射方法

1.进入磁盘管理程序中
同时按住Win + X键,弹出超级菜单。

在弹出的界面选择“磁盘管理”
或同时按住Win + R ,输入“diskmgmt.msc”进入磁盘管理程序中
2.创建SD卡驱动器号和路径
鼠标右击(或长按)SD卡,点击选择“更改驱动器号和路径”
在弹出的对话框中选择“添加”
注:此路径可以是在C盘库文件夹下,也可以在其他的驱动器下
找到您想添加的磁盘目录下,添加一个新的文件夹
以图示所例,我们在新的驱动器D盘中建立了一个“SD”文件夹
添加完成之后,请您点击“确定” 即可。

进入您映射的盘符下,您就可以在您设置的目录下找到您映射的SD卡文件夹。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

内存映射文件要点:MapViewOfFile函数中映射文件的偏移地址必须为系统分配粒度的整数倍,但一次映射的文件长度则不受此限制。

摘要:本文给出了一种方便实用的解决大文件的读取、存储等处理的方法,并结合相关程序代码对具体的实现过程进行了介绍。

引言文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。

一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB、几百GB、乃至几TB的海量存储,再以通常的文件处理方法进行处理显然是行不通的。

目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Windows核心编程技术展开讨论。

内存映射文件内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域,只是内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而非系统的页文件,而且在对该文件进行操作之前必须首先对文件进行映射,就如同将整个文件从磁盘加载到内存。

由此可以看出,使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作,这意味着在对文件进行处理时将不必再为文件申请并分配缓存,所有的文件缓存操作均由系统直接管理,由于取消了将文件数据加载到内存、数据从内存到文件的回写以及释放内存块等步骤,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。

另外,实际工程中的系统往往需要在多个进程之间共享数据,如果数据量小,处理方法是灵活多变的,如果共享数据容量巨大,那么就需要借助于内存映射文件来进行。

实际上,内存映射文件正是解决本地多个进程间数据共享的最有效方法。

内存映射文件并不是简单的文件I/O操作,实际用到了Windows的核心编程技术--内存管理。

所以,如果想对内存映射文件有更深刻的认识,必须对Windows操作系统的内存管理机制有清楚的认识,内存管理的相关知识非常复杂,超出了本文的讨论范畴,在此就不再赘述,感兴趣的读者可以参阅其他相关书籍。

下面给出使用内存映射文件的一般方法:首先要通过CreateFile()函数来创建或打开一个文件内核对象,这个对象标识了磁盘上将要用作内存映射文件的文件。

在用CreateFile()将文件映像在物理存储器的位置通告给操作系统后,只指定了映像文件的路径,映像的长度还没有指定。

为了指定文件映射对象需要多大的物理存储空间还需要通过CreateFileMapping()函数来创建一个文件映射内核对象以告诉系统文件的尺寸以及访问文件的方式。

在创建了文件映射对象后,还必须为文件数据保留一个地址空间区域,并把文件数据作为映射到该区域的物理存储器进行提交。

由MapViewOfFile()函数负责通过系统的管理而将文件映射对象的全部或部分映射到进程地址空间。

此时,对内存映射文件的使用和处理同通常加载到内存中的文件数据的处理方式基本一样,在完成了对内存映射文件的使用时,还要通过一系列的操作完成对其的清除和使用过资源的释放。

这部分相对比较简单,可以通过UnmapViewOfFile()完成从进程的地址空间撤消文件数据的映像、通过CloseHandle()关闭前面创建的文件映射对象和文件对象。

内存映射文件相关函数在使用内存映射文件时,所使用的API函数主要就是前面提到过的那几个函数,下面分别对其进行介绍:函数CreateFile()即使是在普通的文件操作时也经常用来创建、打开文件,在处理内存映射文件时,该函数来创建/打开一个文件内核对象,并将其句柄返回,在调用该函数时需要根据是否需要数据读写和文件的共享方式来设置参数dwDesiredAccess和dwShareMode,错误的参数设置将会导致相应操作时的失败。

CreateFileMapping()函数创建一个文件映射内核对象,通过参数hFile指定待映射到进程地址空间的文件句柄(该句柄由CreateFile()函数的返回值获取)。

由于内存映射文件的物理存储器实际是存储于磁盘上的一个文件,而不是从系统的页文件中分配的内存,所以系统不会主动为其保留地址空间区域,也不会自动将文件的存储空间映射到该区域,为了让系统能够确定对页面采取何种保护属性,需要通过参数flProtect来设定,保护属性PAGE_READONLY、PAGE_READWRITE和PAGE_WRITECOPY分别表示文件映射对象被映射后,可以读取、读写文件数据。

在使用PAGE_READONLY时,必须确保CreateFile()采用的是GENERIC_READ参数;PAGE_READWRITE则要求CreateFile()采用的是GENERIC_READ|GENERIC_WRITE参数;至于属性PAGE_WRITECOPY则只需要确保CreateFile()采用了GENERIC_READ和GENERIC_WRITE其中之一即可。

DWORD型的参数dwMaximumSizeHigh和dwMaximumSizeLow也是相当重要的,指定了文件的最大字节数,由于这两个参数共64位,因此所支持的最大文件长度为16EB,几乎可以满足任何大数据量文件处理场合的要求。

MapViewOfFile()函数负责把文件数据映射到进程的地址空间,参数hFileMappingObject为CreateFileMapping()返回的文件映像对象句柄。

参数dwDesiredAccess则再次指定了对文件数据的访问方式,而且同样要与CreateFileMapping()函数所设置的保护属性相匹配。

虽然这里一再对保护属性进行重复设置看似多余,但却可以使应用程序能更多的对数据的保护属性实行有效控制。

MapViewOfFile()函数允许全部或部分映射文件,在映射时,需要指定数据文件的偏移地址以及待映射的长度。

其中,文件的偏移地址由DWORD型的参数dwFileOffsetHigh和dwFileOffsetLow组成的64位值来指定,而且必须是操作系统的分配粒度的整数倍,对于Windows操作系统,分配粒度固定为64KB。

当然,也可以通过如下代码来动态获取当前操作系统的分配粒度:参数dwNumberOfBytesToMap指定了数据文件的映射长度,这里需要特别指出的是,对于Windows 9x操作系统,如果MapViewOfFile()无法找到足够大的区域来存放整个文件映射对象,将返回空值(NULL);但是在Windows 2000下,MapViewOfFile()只需要为必要的视图找到足够大的一个区域即可,而无须考虑整个文件映射对象的大小。

在完成对映射到进程地址空间区域的文件处理后,需要通过函数UnmapViewOfFile()完成对文件数据映像的释放,该函数原型声明如下:唯一的参数lpBaseAddress指定了返回区域的基地址,必须将其设定为MapViewOfFile()的返回值。

在使用了函数MapViewOfFile()之后,必须要有对应的UnmapViewOfFile()调用,否则在进程终止之前,保留的区域将无法释放。

除此之外,前面还曾由CreateFile()和CreateFileMapping()函数创建过文件内核对象和文件映射内核对象,在进程终止之前有必要通过CloseHandle()将其释放,否则将会出现资源泄漏的问题。

除了前面这些必须的API函数之外,在使用内存映射文件时还要根据情况来选用其他一些辅助函数。

例如,在使用内存映射文件时,为了提高速度,系统将文件的数据页面进行高速缓存,而且在处理文件映射视图时不立即更新文件的磁盘映像。

为解决这个问题可以考虑使用FlushViewOfFile()函数,该函数强制系统将修改过的数据部分或全部重新写入磁盘映像,从而可以确保所有的数据更新能及时保存到磁盘。

使用内存映射文件处理大文件应用示例下面结合一个具体的实例来进一步讲述内存映射文件的使用方法。

该实例从端口接收数据,并实时将其存放于磁盘,由于数据量大(几十GB),在此选用内存映射文件进行处理。

下面给出的是位于工作线程MainProc中的部分主要代码,该线程自程序运行时启动,当端口有数据到达时将会发出事件hEvent[0],WaitForMultipleObjects()函数等待到该事件发生后将接收到的数据保存到磁盘,如果终止接收将发出事件hEvent[1],事件处理过程将负责完成资源的释放和文件的关闭等工作。

下面给出此线程处理函数的具体实现过程:……// 创建文件内核对象,其句柄保存于hFileHANDLE hFile = CreateFile("Recv1.zip",GENERIC_WRITE | GENERIC_READ,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_FLAG_SEQUENTIAL_SCAN,NULL);// 创建文件映射内核对象,句柄保存于hFileMappingHANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE,0, 0x4000000, NULL);// 释放文件内核对象CloseHandle(hFile);// 设定大小、偏移量等参数__int64 qwFileSize = 0x4000000;__int64 qwFileOffset = 0;__int64 T = 600 * sinf.dwAllocationGranularity;DWORD dwBytesInBlock = 1000 * sinf.dwAllocationGranularity;// 将文件数据映射到进程的地址空间PBYTE pbFile = (PBYTE)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,(DWORD)(qwFileOffset>>32), (DWORD)(qwFileOffset&0xFFFFFFFF), dwBytesInBlock); while(bLoop){// 捕获事件hEvent[0]和事件hEvent[1]DWORD ret = WaitForMultipleObjects(2, hEvent, FALSE, INFINITE);ret -= WAIT_OBJECT_0;switch (ret){// 接收数据事件触发case 0:// 从端口接收数据并保存到内存映射文件nReadLen=syio_Read(port[1], pbFile + qwFileOffset, QueueLen);qwFileOffset += nReadLen;// 当数据写满60%时,为防数据溢出,需要在其后开辟一新的映射视图if (qwFileOffset > T){T = qwFileOffset + 600 * sinf.dwAllocationGranularity;UnmapViewOfFile(pbFile);pbFile = (PBYTE)MapViewOfFile(hFileMapping,FILE_MAP_ALL_ACCESS,(DWORD)(qwFileOffset>>32), (DWORD)(qwFileOffset&0xFFFFFFFF), dwBytesInBlock); }break;// 终止事件触发case 1:bLoop = FALSE;// 从进程的地址空间撤消文件数据映像UnmapViewOfFile(pbFile);// 关闭文件映射对象CloseHandle(hFileMapping);break;}}…在终止事件触发处理过程中如果只简单的执行UnmapViewOfFile()和CloseHandle()函数将无法正确标识文件的实际大小,即如果开辟的内存映射文件为30GB,而接收的数据只有14GB,那么上述程序执行完后,保存的文件长度仍是30GB。

相关文档
最新文档