VC利用内存映射文件处理大文件
内存映射原理
内存映射原理
内存映射是一种将磁盘文件映射到内存的操作。
在内存中建立一个虚拟地址空间,该空间与磁盘文件相对应,使得我们可以像访问内存一样访问磁盘文件的内容。
内存映射的原理是通过将磁盘文件的内容映射到内存的一段连续地址空间中。
在内存中指定一个缓冲区,当对这个缓冲区进行读写操作时,实际上是在对磁盘文件进行读写操作。
读取该内存区域的数据时,由于数据已经在内存中,所以读取速度非常快。
内存映射的过程主要包括以下几个步骤:
1. 打开文件:使用文件操作相关的API函数打开需要映射到内存的文件。
2. 创建映射区域:使用内存映射相关的API函数,创建一个映射区域。
将文件的某个区域映射到内存。
3. 访问映射区域:获得映射到内存中的虚拟地址,可以直接对其进行读写操作,就像操作内存一样。
4. 保存修改:如果对映射区域进行了修改,需要使用相关的API函数将修改的内容保存回磁盘文件。
通过内存映射,可以实现大文件的快速读写,提高文件的访问速度。
此外,多个进程可以通过映射同一个文件,实现共享内
存的功能,简化进程间通信的实现。
但需要注意的是,对于大文件的内存映射可能会消耗大量的系统内存,需要进行适当的调优和管理。
内存映射文件的作用功能介绍
内存映射文件的作用功能介绍内存映射文件的主要用途:1.操作大文件 2.进程间大量数据共享,下面分别介绍如下:VC++中使用内存映射文件处理大文件引言文件操作是应用程序最为基本的功能之一,Win32 API和MFC均提供有支持文件处理的函数和类,常用的有Win32 API的CreateFile()、WriteFile()、ReadFile()和MFC提供的CFile类等。
一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的动辄几十GB、几百GB、乃至几TB的海量存储,再以通常的文件处理方法进行处理显然是行不通的。
目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将针对这种Windows核心编程技术展开讨论。
内存映射文件内存映射文件与虚拟内存有些类似,通过内存映射文件可以保留一个地址空间的区域,同时将物理存储器提交给此区域,只是内存文件映射的物理存储器来自一个已经存在于磁盘上的文件,而非系统的页文件,而且在对该文件进行操作之前必须首先对文件进行映射,就如同将整个文件从磁盘加载到内存。
由此可以看出,使用内存映射文件处理存储于磁盘上的文件时,将不必再对文件执行I/O操作,这意味着在对文件进行处理时将不必再为文件申请并分配缓存,所有的文件缓存操作均由系统直接管理,由于取消了将文件数据加载到内存、数据从内存到文件的回写以及释放内存块等步骤,使得内存映射文件在处理大数据量的文件时能起到相当重要的作用。
另外,实际工程中的系统往往需要在多个进程之间共享数据,如果数据量小,处理方法是灵活多变的,如果共享数据容量巨大,那么就需要借助于内存映射文件来进行。
实际上,内存映射文件正是解决本地多个进程间数据共享的最有效方法。
内存映射文件并不是简单的文件I/O操作,实际用到了Windows的核心编程技术--内存管理。
所以,如果想对内存映射文件有更深刻的认识,必须对Windows操作系统的内存管理机制有清楚的认识,内存管理的相关知识非常复杂,超出了本文的讨论范畴,在此就不再赘述,感兴趣的读者可以参阅其他相关书籍。
VC++ 中WM_COPYDATA 怎么样应用来实现两个进程间的数据传输
HWND hWnd = FindWindow(NULL,"MyApp");
if(hWnd!=NULL)
{
COPYDATASTRUCT cpd; /*给COPYDATASTRUCT结构赋值*/
cpd.dwData = 0;
cpd.cbData = strlen("字符串");
{
AfxMessageBox((LPCSTR)(pCopyDataStruct->lpData));/*利用对话框表示收到消息*/
return CWnd::OnCopyData(pWnd, pCopyDataStruct);
}
进程通信还有其他一些手段,相对来说比较麻烦,但局限性要比WM_COPYDATA小。当然你也可以两端都注册一个消息来通信。
afx_msg BOOL OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct);
ON_WM_COPYDATA()/*消息映射*/
BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
进程间通信的方法有多种,其中,对于少量数据可以用WM_COPYDATA方便的实现通信(如果对于大量数据的话,由于SendMessage是阻塞的,只有接收方响应了消息,SendMessage才能返回,否则则一直阻塞,所以,对于大量数据来说,用SendMessage就容易造成窗口假死) 。
ห้องสมุดไป่ตู้
本例子分别用WM_COPYDATA 实现了两种数据类型的发送,一种为Cstring,另外一种为自定义的结构体Student:
VC6.0在32位机中对大数据量文件操作的扩展
POSI TI ON po s l
几种 不 同 情 况 的 处 理 方 法 。
境为 3 2 位 Wi n d o ws 系统 。
( 1 ) 首 先 我 们 把 需 要 操 作 的 数 据 文 件 时 文件F i l e l C o p y 。
并 且 还 要 针 对 一 些 数 据 结 构 不 能 操 作 大 型 格 式 的 大 数 据 量 文 件 的操 作 , 分 别 阐述 了 内存空间, 系 统 无 法 分配 内存 , 从 而导 致
m —f i 1 e.O P e n (f i 1 e N a m e,
中没 有考 虑 到大 数据 量 的 可能 性 , 对数 据块 i f ( mmf . Ma p F i l e ( t e mp Na me , TRU E, 大 小 的描 述 都 是 采 用 的整 型i n t 型或 长 整 型 F I L E ~ S HA R E — RE A D) )
信 息技 术
VC6. 0在 3 2位机 中对 大数 据量 文件 操作 的扩 展
褚 晓 冬 ( 中海 油 田服务股 份有 限公 司油 田技术研 究 院 河北 燕郊
0 6 5 2 0 1 )
摘 要 : 目前 , 随 着计算 机在 各个 产 业部 门的逐 渐普 及 、 计算机 运算 能 力的逐 步提 高 以及各 种新 型需 求的诞 生 , 对文 件存 储 以及访 问 的需求也 随之 升高 , 人 们已经不 能满足 于基 于兆叛 的数据文 件的 访问 , 更大 的数 据文 件的访 问和 支持 能 力对开 发人 员提 出 了更 高的要 求, 但是 , 受计算 机硬 件 条件 , 系统软 件 的版 本 以及软 件 开发 版本 的 约束 , 我 们并 不 能大 刀 阔斧的 对软 件进 行彻 底修 改 , 否则会 对软 件的兼容 性遗 成非 常 严重 的危 害 , 因此 我们 需要针 对不 同情 况来 分剐对 各种 大型数据进 行遍 历 , 从 而保 证软件 在不 同配置 的计算机 上
基于VC++的海量图像分割
B P文件结构 的内容这里不再赘述。 M
下 面将 给 出 成 员 变 量 定 义 , 四个 重 要 的外 部 接 口 函数 和 四
个 内存 成员 函数的详细代码和 注释 ,限于篇幅 ,其他 函数和代
码 不再 叙述 ,可 以参 看 源 程 序 。 t 成 员变 量定 义 . c s S lDb p biC be t l s pi i: u l O jc a C t c
{
p o e t d rt ce :
、
分 析
利用 内存映射文件实现海量文件 ,其机理 实际上 是应用 了
一
种 自定义 的内存 映射机制 ,将硬 盘上 的数 据地址通 过某 种特
定 的映 射 方 式 映 射 到 某 个 虚 拟 的 内存 地 址 ,整 个 硬 盘 数 据 地 址 都 可 以 通 过 这 种 映 射 方 式 映 射 到 某 个 虚 拟 内存 地 址 区域 ,这 样
BIM AP I E ADER% m _ Bi a FlHe d r T F L HE p t p i m e a e;
/ 原始图像文件 头 /
BIM AP NF T I OHE ADE m _ Bt a lf He d r R p i pn o a e ; m
贝到指定 的内存 中进行处理 ,这个过程必然需要将数据从硬盘
处理海量 图像程序设计 中,一个 常用 的方法是使用 内存 映
射文件 ,但笔者在开发过程 中发现 ,内存 映射文件应用不 当,
有 可 能 引 起 内存 耗 尽 现 象 ,所 以撰 写 此 文 ,详 细 叙 述 了现 象 的 原 委 和 解 决 办 法 ,并 设 计 了一 个 可 用 于 海 量 图像 分 割 的类 ,给 出 了 一 个海 量 图像 分 割 的实 例 。
VC6.0在32位机中对大数据量文件操作的扩展
VC6.0在32位机中对大数据量文件操作的扩展摘要:目前,随着计算机在各个产业部门的逐渐普及、计算机运算能力的逐步提高以及各种新型需求的诞生,对文件存储以及访问的需求也随之升高,人们已经不能满足于基于兆级的数据文件的访问,更大的数据文件的访问和支持能力对开发人员提出了更高的要求,但是,受计算机硬件条件、系统软件的版本以及软件开发版本的约束,我们并不能大刀阔斧的对软件进行彻底修改,否则会对软件的兼容性造成非常严重的危害,因此我们需要针对不同情况来分别对各种大型数据进行遍历,从而保证软件在不同配置的计算机上能够顺利运行。
关键词:新型需求彻底修改遍历引言:在石油及矿产勘探领域,经常使用不同方式对地层进行探测,随着探测手段日益增强,衍生出的数据量也越来越大,从早期的几十兆到现在的几个G的级别,不仅对计算机的要求日益提高,同时对软件开发人员也提出了更高的要求:开发人员要花费大量精力来优化内存以及CPU的使用,并且还要针对一些数据结构不能操作大型数据进行扩展。
本文针对某油田测井数据格式的大数据量文件的操作,分别阐述了几种不同情况的处理方法。
本程序是基于VC6.0开发的,其运行环境为32位Windows系统。
1 修改数据描述格式:首先,我们需要面对的是数据格式不能满足需求的问题,对所有标识文件数据块大小的字段进行类型的修改,原有的代码中没有考虑到大数据量的可能性,对数据块大小的描述都是采用的整型int型或长整型long格式,由于采用的是有符号整型,所以其只能标识-2147483648~2147483648的文件块大小,这对于一般的线性数据块大小是足够的,但是对于大范围的波列数据以及矩阵类型数据的描述就捉襟见肘了。
本程序采用了一种叫做ULONGLONG的据格式,该格式为无符号64位数据格式,理论上可以达到0~18446744073709551616的存储长度,这样的话对于任意可能存在的数据长度,该格式都是足够描述的。
windows 读取超大文件到内存的方法
windows 读取超大文件到内存的方法以Windows读取超大文件到内存的方法在日常的计算机使用过程中,我们经常会遇到需要读取超大文件的情况。
然而,由于超大文件的体积过大,直接将其读取到内存中可能会导致内存溢出或系统崩溃的问题。
本文将介绍一种在Windows系统下读取超大文件到内存的方法,以避免出现这些问题。
一、使用流式读取在处理超大文件时,我们可以使用流式读取的方式,逐行读取文件内容,而不是一次性将整个文件读入内存。
这种方式可以大大减少内存的占用,提高程序的运行效率。
在Windows系统下,我们可以使用Python编程语言来实现流式读取超大文件的操作。
首先,我们需要安装Python的相关环境。
然后,使用以下代码来实现文件的流式读取:```pythonwith open('file.txt', 'r') as file:for line in file:# 处理每一行的代码```这段代码中,我们使用`open()`函数打开文件,并以只读模式(`'r'`)读取文件内容。
然后,通过`for`循环逐行读取文件内容,并在每一行进行相应的处理。
通过这种方式,我们可以将超大文件的内容逐行读取到内存中,而不会占用过多的内存空间。
二、使用缓冲区除了流式读取,我们还可以使用缓冲区的方式来读取超大文件。
缓冲区是一种临时存储区域,可以将部分文件内容读入内存,然后逐步处理。
这样可以减少对内存的占用,提高读取文件的效率。
在Windows系统下,我们可以使用C#编程语言来实现使用缓冲区读取超大文件的操作。
首先,我们需要在代码中引入`System.IO`命名空间。
然后,使用以下代码来实现文件的缓冲区读取:```csharpusing (var fileStream = new FileStream("file.txt", FileMode.Open)){using (var streamReader = new StreamReader(fileStream, Encoding.UTF8, true, 1024)){while (!streamReader.EndOfStream){var line = streamReader.ReadLine();// 处理每一行的代码}}}```这段代码中,我们使用`FileStream`和`StreamReader`类来实现文件的缓冲区读取。
内存映射文件与共享内存的区别
内存映射文件与共享内存的区别
内存映射文件和共享内存都是用来实现进程间通信的技术,但它们之间存在着
一些重要的区别。
首先,内存映射文件是将一个文件映射到进程的地址空间中,使得整个文件可以像内存一样被访问,而共享内存则是将一段物理内存映射到多个进程的地址空间中,以实现进程间数据的共享。
其次,内存映射文件是一种将文件内容映射到内存的技术,通过将文件映射到
内存中,可以避免频繁的磁盘IO操作,提高访问文件内容的速度。
而共享内存则
是一段物理内存空间,在不同进程中访问共享内存可以实现进程间的数据共享,比如可以通过共享内存传递数据或共享某些资源。
另外,内存映射文件是一种通过对文件进行映射来实现内存访问的技术,对文
件的修改会实时反映到文件中,但内存映射文件不支持对文件进行完全随机的访问和修改。
而共享内存是一种直接访问物理内存的方式,对共享内存的操作会直接影响到进程间的通信。
此外,内存映射文件更适用于对文件进行读写操作,特别是适合大文件的处理,而共享内存更适用于简单的数据共享,比如进程之间传递一些共享的数据结构或缓冲区。
综上所述,内存映射文件和共享内存都是实现进程间通信的方式,但它们在实
现机制、适用场景和操作方式上存在一些区别。
开发者可以根据具体的需求选择合适的技术来实现进程间通信,提高程序的性能和效率。
内存映射文件原理
内存映射文件原理内存映射文件原理1. 概述•内存映射文件是一种将文件内容映射到内存地址空间的技术。
•它可以让我们像访问内存一样访问文件,提供了快速读写文件的方法。
2. 原理介绍1.内存映射文件通过建立虚拟内存与磁盘文件之间的映射关系实现。
2.当我们将一个文件映射到内存中时,操作系统会为该文件分配一块虚拟内存空间。
3.虚拟内存空间被划分为多个固定大小的页,而文件也被划分为相同大小的页。
4.当访问虚拟内存空间中的某个页时,操作系统会将对应的磁盘页加载到内存中。
5.文件中的数据和内存中的数据是共享的,对内存中的数据的修改会直接写回到文件中。
3. 优点•快速读写:内存映射文件利用了操作系统的虚拟内存机制,可以直接访问文件数据,避免了频繁的磁盘读写操作,提高了读写性能。
•方便操作:将文件映射到内存后,我们可以像操作内存一样访问文件,使用指针访问数据更加方便和高效。
•共享数据:多个进程可以将同一个文件映射到各自的内存空间中,实现共享数据的目的,方便进程间的通信。
4. 使用步骤1.打开文件:使用指定的文件路径打开需要映射的文件。
2.获取文件大小:通过系统调用或API函数获取文件的大小。
3.创建映射对象:使用系统调用或API函数创建一个映射对象,指定文件句柄、大小等信息。
4.映射到内存:将映射对象映射到内存中,得到一个指向映射区域的指针。
5.访问数据:可以通过指针对映射区域中的数据进行读写操作。
6.取消映射:使用系统调用或API函数取消内存与文件的映射关系。
7.关闭文件:使用系统调用或API函数关闭文件。
5. 使用场景•大文件处理:内存映射文件可以有效地处理大文件,减少了磁盘读写的次数,提高了处理效率。
•数据共享:多个进程可以通过内存映射文件实现数据的共享,方便了进程间的通信和数据交换。
•高性能数据库:许多高性能数据库系统使用内存映射文件来提高数据的读写速度和响应时间。
6. 注意事项•内存映射文件使用较多的内存资源,需注意管理内存的使用情况,避免内存泄漏等问题。
大文件读取解决方案
大文件读取解决方案1.分块读取:将文件分割为多个块进行读取。
可以设置一个固定的块大小,逐步读取每个块的数据。
这种方法适用于文件无序的情况,但需要借助文件指针进行定位。
2.缓存读取:使用缓冲区来存储部分文件内容,通过循环读取小块数据并累计存储在缓冲区中。
随着缓冲区的数据被处理完,再读取下一块数据。
这种方法可以减少内存的占用,提高读取效率。
3. 内存映射文件:通过将文件映射到内存中,可以像访问内存一样访问文件内容。
可以使用mmap函数(在Linux环境下)或CreateFileMapping函数(在Windows环境下)将文件映射到内存中,并使用指针进行操作和读取。
4.多线程读取:将文件分割为多个部分,每个线程负责读取一个部分的数据。
可以有效利用多核处理器的并行能力,提高读取速度。
需要注意进行线程同步和数据合并。
5.压缩文件读取:如果文件内容可以压缩,可以先将文件进行压缩处理,然后在读取时进行解压缩操作。
这样可以减小文件大小,提高读取效率。
6.使用流处理:使用流来逐行读取文件内容,而不是一次性读取整个文件。
这种方法可以减少内存的占用,并且适用于处理大文件中的一行或一部分内容。
7.使用数据库:将文件内容导入数据库,然后通过数据库的查询语句进行读取操作。
数据库可以有效地管理大量数据,并提供高效的查询功能。
8. 使用专业的大文件读取工具:一些专门为大文件读取设计的工具,例如Hadoop、Spark等,可以处理大规模的数据集,并提供高性能的文件读取能力。
在选择解决方案时,需要考虑文件的具体情况和应用需求。
不同的解决方案适用于不同的场景,可以根据实际情况选择最合适的方法。
同时,也可以结合多种方法进行优化和改进,以提高大文件读取的效率和可靠性。
C语言技术的高级使用方法
C语言技术的高级使用方法C语言作为一门广泛应用于软件开发和系统编程的编程语言,其高级使用方法在提高代码效率和性能方面起着重要作用。
本文将探讨几种C语言技术的高级使用方法,包括指针操作、内存管理以及多线程编程。
一、指针操作指针是C语言中一种强大的工具,可以直接访问和操作内存中的数据。
高级使用方法包括指针的指针、指针的算术运算以及函数指针等。
1. 指针的指针指针的指针是指指针变量的地址存储在另一个指针变量中。
通过使用指针的指针,可以实现多级间接访问,提高代码的灵活性和效率。
例如,可以使用指针的指针来实现动态数组的分配和释放。
通过在堆上分配一块内存,并将其地址存储在指针的指针中,可以实现动态数组的大小调整。
2. 指针的算术运算指针的算术运算允许对指针进行加减运算,以及比较大小。
这在处理数组和字符串时非常有用。
例如,可以使用指针的算术运算来实现字符串的逆序输出。
通过将指针指向字符串的末尾,然后逐步向前移动指针,可以实现字符串的逆序输出。
3. 函数指针函数指针是指向函数的指针变量。
通过使用函数指针,可以实现回调函数和动态函数调用等高级功能。
例如,可以使用函数指针来实现回调函数,即将一个函数作为参数传递给另一个函数。
这在事件处理和异步编程中非常有用。
二、内存管理C语言中的内存管理是一项关键任务,直接影响程序的性能和稳定性。
高级使用方法包括动态内存分配、内存池和内存映射文件等。
1. 动态内存分配动态内存分配允许在程序运行时分配和释放内存。
通过使用动态内存分配函数(如malloc和free),可以根据需要动态调整内存的大小。
例如,可以使用动态内存分配来实现链表数据结构。
通过在每个节点中使用指针来指向下一个节点,可以实现动态增删节点的功能。
2. 内存池内存池是一种预先分配一定数量内存块的技术。
通过使用内存池,可以减少动态内存分配和释放的次数,提高程序的效率。
例如,可以使用内存池来管理大量的小对象。
通过将内存分为固定大小的块,并将这些块链接在一起,可以实现高效的内存分配和释放。
大文件读取解决方案
大文件读取解决方案在处理大文件读取的过程中,主要涉及到以下几个方面的问题:文件大小、内存限制、IO性能以及文件格式等。
针对这些问题,可以采取以下解决方案:1.分块读取:将大文件切割为多个小块进行读取和处理。
通过逐块读取文件可以一定程度上减少内存的使用量。
可以使用文件指针定位到需要读取的位置,然后读取指定大小的数据块。
2. 使用缓冲区:在读取大文件时,可以利用缓冲区来减少IO次数,从而提高IO性能。
可以使用缓冲流(BufferedReader、BufferedInputStream等)进行读取,设定合理的缓冲区大小,以提高读取效率。
3.多线程读取:在多核CPU上可以使用多线程并行读取文件,提高读取速度。
将文件切割成多个块,并使用多个线程同时读取和处理。
可以利用线程池来管理线程的创建和销毁,控制并发数,避免资源浪费和线程频繁切换的开销。
4. 内存映射文件:通过使用内存映射文件,将大文件映射到内存中,可以直接在内存中进行读取操作,避免频繁的IO操作。
内存映射文件可以使用NIO中的FileChannel类的map(方法来实现。
5.使用外部存储:如果内存不能完全加载大文件,可以考虑使用外部存储进行读取和处理,如数据库等。
可以将大文件拆分为小文件,存储在数据库中,再进行读取和处理,减少内存的压力。
6.改变文件格式:如果可能的话,可以考虑改变文件的格式,减小文件的大小。
例如,可以使用压缩算法对文件进行压缩,减小文件的体积,然后再解压缩进行读取和处理。
7. 使用专用的文件处理工具:可以使用专门的大文件处理工具,如Hadoop、Spark等,这些工具提供了分布式处理的能力,可以将大文件划分为多个块,分发到不同的节点上进行处理,大大加快处理速度。
8.增加硬件资源:如果处理大文件的性能问题持续存在,可以考虑增加硬件资源,如更大的内存、更快的磁盘等,以提升读取和处理性能。
总结起来,大文件读取需要综合考虑文件大小、内存限制、IO性能和文件格式等因素,可以采取分块读取、使用缓冲区、多线程读取、内存映射文件等方式来解决问题。
大量数据处理时的高效率VC++编程方法
任 何 物理 存储 器 ,那 么访 问该 范 围 中的 内存地 址 的任 何企 图都将
Wn o s提 供 了一 种有 效 的 内存 管理 的 方法 :虚 拟 内存 ,它 idw 最适 合 用来 管 理大 型对 象 或结 构数 组 。它可 以让 应 用程 序拥 有 连 续 可用 的 内存地 址 ,而 实 际上 , 它通 常是 被 分 隔成 多个 物 理 内存 碎 片,还 有 部分 暂 时存 储 在外 部磁 盘 存储 器 上 ,仅在 需 要 时进 行 数据 交 换 ,这样 大 大加 快 程序 的运 行 性 能 。一般 而 言 ,计算 机 的 R 越 多 ,程 序 运行 得越 快 。如 果计 算 机 的速度 由于缺 少 R M而 M A A 降低 ,则可 以 尝试增 加虚 拟 内存 来 进行 补偿 。 通 过调 用 W n os的 A I函数 Vr u l lo,可 以在进 程 的 id w P ita A lc 地 址空 间 中保 留一 个 区域 ,分 配 一定 大 小 的虚拟 内存 ,其 函数 形
的难 度 。
后 一 个参 数是 fw r t c,用 于 指 明应 该赋 予该 地址 空 间区 域 的 dP oe t
保 护 属性 。与 该 区域 相 关联 的保 护 属性 对 映射 到 该 区域 的 已提 交 内存 没有 影 响 。无论 赋 予 区域 的保 护属 性 是什 么 ,如 果没 有提 交
等 解 决办 法 。
关键词 :v + 程 ; 大数据 量 处理 ;虚 拟 内存使 用 ;双缓 冲绘 图 ;大型文 件存 取 c+ 编
中图分类号:U 1. 42 6
文献标茯码 :A
文章鳊号:10 — 5 9( 00 8 04 - 2 07 9 9 2 1 )0— 18 0
c语言读取大文件
CreateFileMapping的MSDN翻译和使用心得测试创建和打开文件映射的时候老是得到"句柄无效"的错误, 仔细看了MSDN以后才发觉是函数认识不透, 这里把相关的解释翻译出来HANDLE CreateFileMapping(HANDLE hFile, //物理文件句柄LPSECURITY_ATTRIBUTES lpAttributes, //安全设置DWORD flProtect, //保护设置DWORD dwMaximumSizeHigh, //高位文件大小DWORD dwMaximumSizeLow, //低位文件大小LPCTSTR lpName //共享内存名称);1) 物理文件句柄任何可以获得的物理文件句柄, 如果你需要创建一个物理文件无关的内存映射也无妨,将它设置成为0xFFFFFFFF(INVALID_HANDLE_VALUE)就可以了.如果需要和物理文件关联, 要确保你的物理文件创建的时候的访问模式和"保护设置"匹配, 比如: 物理文件只读, 内存映射需要读写就会发生错误. 推荐你的物理文件使用独占方式创建.如果使用INVALID_HANDLE_VALUE, 也需要设置需要申请的内存空间的大小, 无论物理文件句柄参数是否有效, 这样CreateFileMapping 就可以创建一个和物理文件大小无关的内存空间给你, 甚至超过实际文件大小, 如果你的物理文件有效, 而大小参数为0, 则返回给你的是一个和物理文件大小一样的内存空间地址范围. 返回给你的文件映射地址空间是可以通过复制, 集成或者命名得到, 初始内容为0.2) 保护设置就是安全设置, 不过一般设置NULL就可以了, 使用默认的安全配置. 在win2k下如果需要进行限制, 这是针对那些将内存文件映射共享给整个网络上面的应用进程使用是, 可以考虑进行限制.3) 高位文件大小弟兄们, 我想目前我们的机器都是32位的东东, 不可能得到超过32位进程所能寻址的私有32位地址空间, 一般还是设置0吧, 我没有也不想尝试将它设置超过0的情况.4) 低位文件大小这个还是可以进行设置的, 不过为了让其他共享用户知道你申请的文件映射的相关信息, 我使用的时候是在获得的地址空间头部添加一个结构化描述信息, 记录内存映射的大小, 名称等, 这样实际申请的空间就比输入的增加了一个头信息结构大小了, 我认为这样类似BSTR的方式应该是比较合理的.5) 共享内存名称这个就是我今天测试的时候碰壁的祸根, 因为为了对于内存进行互斥访问, 我设置了一个互斥句柄, 而名称我选择和命名共享内存同名, 之下就是因为他们使用共同的namespace导致了错误, 呵呵.7) 调用CreateFileMapping的时候GetLastError的对应错误ERROR_FILE_INVALID 如果企图创建一个零长度的文件映射, 应有此报ERROR_INVALID_HANDLE 如果发现你的命名内存空间和现有的内存映射, 互斥量, 信号量, 临界区同名就麻烦了ERROR_ALREADY_EXISTS 表示内存空间命名已经存在8) 相关服务或者平台的命名保留Terminal Services:命名可以包含"Global\" 或者"Local\" 前缀在全局或者会话名空间初级文件映射. 其他部分可以包含任何除了(\)以外的字符, 可以参考Kernel Object Name Spaces.Windows 2000 or later:如果Terminal Services 没有运行"Global\" 和"Local\" 前缀的特殊含义就被忽略了CreateFileMapping 函数(转载)内存映射API函数CreateFileMapping创建一个有名的共享内存:HANDLE CreateFileMapping(HANDLE hFile, // 映射文件的句柄,//设为0xFFFFFFFF以创建一个进程间共享的对象LPSECURITY_ATTRIBUTES lpFileMappingAttributes, // 安全属性DWORD flProtect, // 保护方式DWORD dwMaximumSizeHigh, //对象的大小DWORD dwMaximumSizeLow,LPCTSTR lpName // 必须为映射文件命名);与虚拟内存类似,保护方式可以是PAGE_READONLY或是PAGE_READWRITE。
内存映射文件的工作原理及使用方法
内存映射文件的工作原理及使用方法内存映射文件(Memory-mapped files)是一种将文件映射到内存的机制,它允许应用程序直接访问磁盘上的文件,而无需进行显式的读写操作。
在内存映射文件中,操作系统将文件的一些区域映射到了进程的虚拟内存空间,从而让应用程序可以像访问内存一样访问文件的内容。
内存映射文件的工作原理及使用方法如下:工作原理:1. 打开文件:应用程序首先使用标准的文件操作函数(如open()打开需要映射的文件。
在打开文件时,操作系统会为该文件维护一个文件描述符(File Descriptor)以及其他相关信息。
2. 创建映射:应用程序使用操作系统提供的内存映射函数(如mmap()将文件的一些区域映射到进程的虚拟内存空间中。
该区域通常以页为单位进行映射,即一个或多个连续的页被映射为一段连续的虚拟内存区域。
3.访问文件:一旦映射创建成功,应用程序就可以像访问内存一样访问文件的内容。
读文件时,应用程序直接读取虚拟内存中的数据,操作系统会自动将数据从磁盘读取到内存中;写文件时,应用程序直接修改虚拟内存中的数据,操作系统也会自动将数据写回磁盘。
4.同步数据:内存映射文件中的数据是与磁盘文件保持同步的。
当应用程序对映射区域进行修改时,操作系统会将数据缓存到内存中,并在适当的时机进行写回磁盘,以保证文件的一致性。
使用方法:1. 准备文件:首先需要准备一个需要映射的文件。
可以通过标准的文件操作函数(如open(、write()创建或修改文件。
2. 打开映射:使用内存映射函数(如mmap()将文件的一些区域映射到虚拟内存中。
需要指定映射的起始位置、映射的长度、映射的权限等参数。
3.访问文件:通过访问虚拟内存中的映射区域,可以读写文件的内容。
可以使用指针操作、数组操作或其他方式来访问映射区域中的数据。
4. 同步数据:在需要时,可以使用内存同步函数(如msync()将内存中修改的数据写回磁盘,以保证文件的一致性。
内存映射文件使用方法
内存映射文件使用方法随着计算机技术的不断发展,内存映射文件成为了一种重要的文件处理方式。
内存映射文件可以将文件直接映射到内存中,提供了一种高效、方便的文件操作方式。
本文将介绍内存映射文件的使用方法,匡助读者更好地理解和应用这一技术。
一、什么是内存映射文件内存映射文件是一种将文件映射到内存的技术。
通过内存映射文件,我们可以像操作内存一样操作文件,而不需要频繁地进行磁盘读写操作。
内存映射文件可以提高文件的读写效率,并且简化了文件操作的代码。
二、内存映射文件的创建在使用内存映射文件之前,我们需要创建一个内存映射文件对象。
下面是一个简单的内存映射文件的创建示例:```pythonimport mmapfile = open('example.txt', 'r+b')mmap_obj = mmap.mmap(file.fileno(), 0)```在上述示例中,我们首先打开了一个文件,并以读写模式打开。
然后,通过`mmap.mmap`函数创建了一个内存映射文件对象`mmap_obj`。
这样,我们就可以通过`mmap_obj`来操作文件了。
三、内存映射文件的读写操作内存映射文件对象提供了一系列方法来进行读写操作。
下面是一些常用的方法:1. `read(size)`:从内存映射文件中读取指定大小的数据,并返回一个字节对象。
2. `write(data)`:将指定的数据写入到内存映射文件中。
3. `seek(offset[, whence])`:将文件指针挪移到指定的位置。
`offset`表示偏移量,`whence`表示偏移的起始位置,默认为0。
4. `size()`:返回内存映射文件的大小。
通过这些方法,我们可以方便地对内存映射文件进行读写操作。
例如,我们可以使用`read`方法读取文件的内容,并使用`write`方法将数据写入到文件中。
四、内存映射文件的应用场景内存映射文件在实际开辟中有着广泛的应用场景。
内存映射的方式
内存映射的方式内存映射是一种将文件或其他设备映射到程序的内存空间的方式,使得程序可以直接读取或写入内存中的数据,而无需通过繁琐的文件读写操作。
常见的内存映射方式有以下几种:1.文件映射:文件映射是将一个文件的内容映射到内存中,使得程序可以直接访问文件的内容。
文件映射可以分为读映射和写映射两种方式。
读映射意味着程序可以直接从内存中读取文件的内容,而无需通过文件读取操作;写映射则允许程序直接将数据写入到内存中,而无需通过文件写入操作。
文件映射可以提高文件的读写性能,减少了文件操作的开销。
2.共享内存映射:共享内存映射是一种特殊的内存映射方式,它允许多个进程之间共享同一段内存空间。
这种方式可以通过建立映射关系,使得多个进程可以直接读写映射到内存中的数据,实现数据共享和通信。
共享内存映射可以提高进程间通信的效率,避免了复制数据的开销。
3.设备映射:设备映射是将设备的寄存器或者是设备对应的内存空间映射到程序的内存空间中,使得程序可以直接操作设备。
这种方式可以提高对设备的访问效率,并且简化了对设备的操作流程。
提高读写性能:因为内存映射可以减少文件读写操作的次数,直接在内存中进行读写操作,因此可以提高读写性能,特别是对于大文件的读写。
简化操作流程:通过内存映射,程序可以直接访问内存中的数据,而无需通过繁琐的文件读写操作或者设备操作,减少了操作的复杂性和开销。
实现数据共享和通信:共享内存映射可以实现不同进程之间的数据共享和通信,提高了进程间通信的效率。
内存限制:程序的内存空间是有限的,如果映射的文件或设备太大,可能会导致内存不足的问题。
并发访问:如果多个进程或线程同时访问同一段内存映射空间,可能会发生竞争条件和数据一致性问题,需要进行相应的同步和互斥处理。
安全性:内存映射方式对于系统的安全性也有一定的影响,需要特别注意对映射区域的保护和权限控制,防止恶意访问和篡改。
总的来说,内存映射是一种高效简便的数据访问方式,可以提高读写性能,简化操作流程,并实现数据共享和通信。
操作系统中的内存映射与文件映射技术
操作系统中的内存映射与文件映射技术内存映射和文件映射是操作系统中常用的技术之一。
它们允许操作系统将磁盘上的文件直接映射到内存,使得对文件的访问操作可以像对内存一样快速和方便。
本文将分别介绍内存映射和文件映射的原理、应用场景以及它们的优缺点。
一、内存映射1.内存映射的原理内存映射是操作系统中一种将磁盘上的文件映射到进程地址空间的技术。
具体而言,操作系统会为文件在虚拟内存地址空间中分配一段连续的地址,并将文件内容从磁盘读取到这段内存中。
这样,对该文件的访问操作就可以直接在内存中进行,而不需要再通过文件读写系统调用。
2.内存映射的应用场景内存映射在操作系统中有着广泛的应用场景。
其中最常见的应用场景包括:-文件访问:将文件映射到内存中可以避免频繁的磁盘读写操作,从而提高文件访问速度。
这在处理大型文件或需要频繁访问的文件时特别有用。
-共享内存:多个进程可以将同一个文件映射到各自的地址空间中,从而实现共享内存的目的。
这在并发编程和进程间通信中常用,可以提高进程间的数据交换效率。
-动态链接库加载:操作系统可以将动态链接库文件映射到进程地址空间中,实现动态库的加载和使用。
这可以提高程序的可扩展性和灵活性。
3.内存映射的优缺点内存映射技术有着以下优点:-提高访问速度:内存映射将磁盘上的文件映射到内存中,避免了频繁的磁盘读写操作,从而提高了访问速度。
-简化编程:内存映射使得对文件的访问可以像访问内存一样简单,不需要使用繁琐的文件读写系统调用。
-共享数据:多个进程可以通过映射同一文件实现共享内存,从而在进程间交换数据,并实现进程间的通信。
然而,内存映射技术也有以下缺点:-浪费内存:内存映射会为文件在进程地址空间中分配一段内存,如果映射了大型文件,会导致内存的浪费。
-安全性问题:如果多个进程都可以访问同一个文件的映射内存,那么需要注意对共享内存的保护,避免数据损坏或非法访问。
-文件大小限制:由于内存有限,操作系统对单个文件的映射大小通常存在限制,不能超过操作系统的地址空间大小。
文件映射
内存映射文件是利用虚拟内存把文件映射到进程的地址空间中去,在此之后进程操作文件,就像操作进程空间里的地址一样了,比如使用memcpy等内存操作的函数。
这种方法能够很好的应用在需要频繁处理一个文件或者是一个大文件的场合,这种方式处理IO效率比普通IO效率要高。
优势:1)速度快2)可以在源文件中修改文件内容,或者在文件的任意位置添加字符到文件中,就好像操作字符数组一样,不必执行I/O操作,并且不必对文件内存进行缓存。
原理为:把数据文件的一部分映射到虚拟地址空间,但没有提交实际内存(也就是说作为页面文件),当有指令要存取这段内存时同样会产生页面错误异常.操作系统捕获到这个异常后,分配一页内存,映射内存到发生异常的位置,然后把要访问的数据读入到这块内存,继续执行刚才产生异常的指令(这里我理解的意思是把刚才产生异常的指令在执行一次,这次由于数据已经映射到内存中,指令就可以顺利执行过去),由上面的分析可知,应用程序访问虚拟地址空间时由操作系统管理数据在读入等内容,应用程序本身不需要调用文件的I/O函数(这点我觉得很重要,也就是为什么使用内存映射文件技术对内存的访问就象是对磁盘上的文件访问一样).使用方法:1)创建或打开一个文件内核对象,用这个内核对象标识磁盘上需要映射的文件(CreateFile)2) 创建一个文件映射内核对象,告诉系统需要映射的对象需要多少物理存储器(可以大于或小于文件大小)及访问权限(CreateFileMapping),但创建一个文件映射对象时,系统并不为它保留地址空间区域,也不将文件的存储器映射到这个区域,函数的主要作用是保证文件映射对象能够获取足够的物理存储器。
3)让系统将文件对象的全部或者部分映射到进程的地址空间(MapViewOfFile)。
有两件事必须要处理:首先,必须告诉系统数据文件中的哪个字节将作为视图中的第一个字节来映射。
其次,必须告诉系统,文件中有多少个字节需要映射到地址空间。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { TRACE("创建文件对象失败,错误代码:%d\r\n", GetLastError()); return; } // 创建文件映射对象 HANDLE hFileMap = CreateFileMapping(hFile, NULL, PAGE_READWRITE, 0, 0, NULL); if (hFileMap == NULL) { TRACE("创建文件映射对象失败,错误代码:%d\r\n", GetLastError()); return; } // 得到系统分配粒度 SYSTEM_INFO SysInfo; GetSystemInfo(&SysInfo); DWORD dwGran = SysInfo.dwAllocationGranularity; // 得到文件尺寸 DWORD dwFileSizeHigh; __int64 qwFileSize = GetFileSize(hFile, &dwFileSizeHigh); qwFileSize |= (((__int64)dwFileSizeHigh) << 32); // 关闭文件对象 CloseHandle(hFile); // 偏移地址 __int64 qwFileOffset = 0; // 块大小 DWORD dwBlockBytes = dwGran; while (qwFileSize > 0) { // 映射视图 if (qwFileSize < dwGran) dwBlockBytes = (DWORD)qwFileSize; LPBYTE lpbMapAddress = (LPBYTE)MapViewOfFile(hFileMap,FILE_MAP_ALL_ACCESS, (DWORD)(qwFileOffset >> 32), (DWORD)(qwFileOffset & 0xFFFFFFFF), dwBlockBytes); if (lpbMapAddress == NULL) { TRACE("映射文件映射失败,错误代码:%d\r\n", GetLastError()); return; } // 对映射的视图进行访问 for(DWORD i = 0; i < dwBlockBytes; i++) {
静态、动态数据,一旦对它们的操作被提交,这些页面也将被备份至系统的页面文件,这与可执 行文件被用来备份执行代码页面的过程是很类似的。 图 1 展示了代码页面和数据页面在磁盘存储 器上的备份过程: 图 1 进程的代码页、数据页在磁盘存储器上的备份 显然,如果可以采取同一种方式来处理代码和数据页面,无疑将会提高程序的执行效率,而 内存映射文件的使用恰恰可以满足此需求。
下面分别对这些关键函数进行说明: 1)CreateFile():CreateFile()函数是一个用途非常广泛的函数,在这里的用法并没 有什么特殊的地方,但有几点需要注意:一是访问模式参数 dwDesiredAccess。该参数设置了对 文件内核对象的访问类型,其允许设置的权限可以为读权限 GENERIC_READ、写权限 GENERIC_WRITE、读写权限 GENERIC_READ | GENERIC_WRITE 和设备查询权限 0。在使用映射文件 时,只能打开那些具有可读访问权限的文件,即只能应用 GENERIC_READ 和 GENERIC_READ | GENERIC_WRITE 这两种组合;另一点需要注意的是共享模式参数 dwShareMode。该参数定义了对 文件内核对象的共享方式,其可能的设置为 FILE_SHARE_READ、FILE_SHARE_WRITE 和 0,并可对 其组合使用。其中,设置为 0 时不允许共享对象; FILE_SHARE_READ 和 FILE_SHARE_WRITE 分别 为在要求只读、只写访问的情况下才允许对象的共享。 由于通过内存映射文件可以在多个进程间共享数据,因此在进行这种应用时应当考虑 dwShareMode 参数设置对运行结果的影响。 2)CreateFileMapping():该函数的作用是创建一个文件映射内核对象,以告知系统文件 映射对象需要多大的物理存储器。 创建内存映射文件对象对系统资源几乎没有什么影响, 也不会 影响进程的虚拟地址空间。 除了需要用来表示该对象的内部资源之外通常并不用为其分配虚拟内 存, 但是如果内存映射文件对象是作共享内存之用的话, 就要在创建对象时由系统为内存映射文 件的使用在系统页文件中保留足够的空间。 函数第一个参数 hFile 为标识要映射到进程的地址空间的文件的句柄。 虽然由于内存映射文
BYTE temp = *(lpbMapAddress + i); } // 撤消文件映像 UnmapViewOfFile(lpbMapAddress); // 修正参数 qwFileOffset += dwBlockBytes; qwFileSize -= dwBlockBytes; } // 关闭文件映射对象句柄 CloseHandle(hFileMap); AfxMessageBox("成功完成对文件的访问"); } 在本例中,首先通过 GetFileSize()得到被处理文件长度(64 位)的高 32 位和低 32 位值。 然后在映射过程中设定每次映射的块大小为 1000 倍的分配粒度,如果文件长度小于 1000 倍的 分配粒度时则将块大小设置为文件的实际长度。在处理过程中由映射、访问、撤消映射构成了一 个循环处理。其中,每处理完一个文件块后都通过关闭文件映射对象来对每个文件块进行整理。 CreateFileMapping()、MapViewOfFile()等函数是专门用来进行内存文件映射处理用的。
VC 利用内存映射文件处理大文件(转载)
摘要: 本文通过内存映射文件的使用来对大尺寸文件进行访问操作, 同时也对内存映射文件的相 关概念和一般编程过程作了较为详细的介绍。 关键词:内存映射文件;大文件处理;分配粒度 引言 文件操作是应用程序最为基本的功能之一,Win32 API 和 MFC 均提供有支持文件处理的函数 和类,常用的有 Win32 API 的 CreateFile()、WriteFile()、ReadFile()和 MFC 提供的 CFile 类 等。一般来说,以上这些函数可以满足大多数场合的要求,但是对于某些特殊应用领域所需要的 动辄几十 GB、几百 GB、乃至几 TB 的海量存储,再以通常的文件处理方法进行处理显然是行不通 的。目前,对于上述这种大文件的操作一般是以内存映射文件的方式来加以处理的,本文下面将 针对这种 Windows 核心编程技术展开讨论。 内存映射文件概述 内存文件映射也是 Windows 的一种内存管理方法, 提供了一个统一的内存管理特征, 使应用 程序可以通过内存指针对磁盘上的文件进行访问, 其过程就如同对加载了文件的内存的访问。 通 过文件映射这种使磁盘文件的全部或部分内容与进程虚拟地址空间的某个区域建立映射关联的 能力, 可以直接对被映射的文件进行访问, 而不必执行文件 I/O 操作也无需对文件内容进行缓冲 处理。内存文件映射的这种特性是非常适合于用来管理大尺寸文件的。 在使用内存映射文件进行 I/O 处理时, 系统对数据的传输按页面来进行。 至于内部的所有内 存页面则是由虚拟内存管理器来负责管理, 由其来决定内存页面何时被分页到磁盘, 哪些页面应 该被释放以便为其它进程提供空闲空间, 以及每个进程可以拥有超出实际分配物理内存之外的多 少个页面空间等等。 由于虚拟内存管理器是以一种统一的方式来处理所有磁盘 I/O 的 (以页面为 单位对内存数据进行读写),因此这种优化使其有能力以足够快的速度来处理内存操作。 使用内存映射文件时所进行的任何实际 I/O 交互都是在内存中进行并以标准的内存地址形 式来访问。 磁盘的周期性分页也是由操作系统在后台隐蔽实现的, 对应用程序而言是完全透明的。 内存映射文件的这种特性在进行大文件的磁盘事务操作时将获得很高的效益。 需要说明的是,在系统的正常的分页操作过程中,内存映射文件并非一成不变的,它将被定 期更新。如果系统要使用的页面目前正被某个内存映射文件所占用,系统将释放此页面,如果页 面数据尚未保存,系统将在释放页面之前自动完成页面数据到磁盘的写入。 对于使用页虚拟存储管理的 Windows 操作系统, 内存映射文件是其内部已有的内存管理组件 的一个扩充。 由可执行代码页面和数据页面组成的应用程序可根据需要由操作系统来将这些页面 换进或换出内存。 如果内存中的某个页面不再需要, 操作系统将撤消此页面原拥用者对它的控制 权,并释放该页面以供其它进程使用。只有在该页面再次成为需求页面时,才会从磁盘上的可执 行文件重新读入内存。同样地,当一个进程初始化启动时,内存的页面将用来存储该应用程序的
件的物理存储器是来自于磁盘上的文件, 而非系统的页文件, 使创建内存映射文件就像保留一个 地址空间区域并将物理存储器提交给该区域一样。第二个参数为指向文件映射内核对象的 SECURITY_ATTRIBUTES 结构的指针,由此来决定子进程能否继承得到返回的句柄。通常为其传递 NULL 值,以默认的安全属性来禁止返回句柄的被继承。 接下来的参数用于文件被映射后设定文件映像的保护属性。其可能的取值为 PAGE_READONLY、 PAGE_READWRITE 和 PAGE_WRITECOPY。虽然在创建文件映射对象时,系统并不 为其保留地址空间区域,也不将文件的存储器映射到该区域。但是,在系统将存储器映射到进程 的地址空间中去时,系统必须确切知道应赋予物理存储器页面的保护属性。在设置保护属性时, 必须与用 CreateFile()函数打开文件时所指定的访问标识相匹配,否则将导致 CreateFileMapping()的执行失败。因此这里设置 PAGE_READWRITE 属性。除了上述三个页面 保护属性外,还有 4 个区(Section)保护属性也可以一起组合使用: