发信人: skyice()
整理人: skyice(2000-06-22 00:31:06), 站内信件
|
创建文件映射对象
一旦打开了文件,内存映射文件支持的第二步就涉及创建文件映射对象。
这是通过调用函数 CreateFileMapping() 来完成的,这个函数的第一个参
数是文件句柄。也许你以为如果偶然传递给它一个无效(-1)文件句柄,它
会失败,其实不然。正如我们不久将要讨论的,无效文件句柄作为第一个参
数时不创建共享文件访问,但将创建共享内存。CreateFileMapping() 函
数定义如下:
HANDLE WINAPI CreateFileMapping(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpsa,
DWORD dwProtect,
DWORD dwMaxSizeHigh,
DWORD dwMaxSizeLow,
LPCTSTR lpszMapName)
hFile 参数是从 OpenFile() 或 CrateFile() 调用返回的一个文件
句柄。lpsa 参数指向一个 SECURITY_ATTRIBUTES 结构,在 Windows NT
上,这个结构定义了文件映射对象的安全性属性。值 NULL 提供默认的安全
性。
dwProtect 参数是一个标志域,用于页保护标志,诸如 PAGE_READO-
NLY、PAGE_READWRITE 和 PAGE_WRITECOPY。这些标志必须和打开文件时
指定的访问标志相一致。
dwMaxSizeHigh 参数是最大文件尺寸的高 32 位。(由于预期要支持
大于 4GB 文件的文件系统, Win32 使用 64 位文件偏移量。)dwMaxSi-
zeLow 参数是最大文件尺寸的低 32 位。
lpszMapName 参数是一个可选字符串名,标识文件映射对象。可以提
供一个唯一命名文件映射对象的字符串,也可以提供 NULL 表示没有该对
象。以下是一个例子,调用这个函数创建一个无名的文件映射对象:
// Create file mapping object.
HANDLE hfm;
hfm = CreateFileMapping(hfile, // File handle
0, // Security Ptr
PAGE_READONLY, // Pg protection
0, // Size-Hi 32-bits
dwFileSize, // Size-Low 32-bits
0); // Mapping Name
当你创建文件映射对象时,如果你愿意,可以给它起一个唯一的名称(
在 lpszMapName 域中),例如“RICK_SHARED”。要确保这个名称是唯一
的,因为一个意外的名称和未知进程的冲突将会导致以意外的、不希望的方
式共享数据。
对于两个或多个进程共享一个文件,必须创建单一的文件映射对象供它
们共享。一旦调用 CreateFileMapping() 创建了一个文件映射对象,那么
就有三个不同函数启用了进程间共享,它们是: CreateFileMapping()、
OpenFileMapping() 和 DuplicateHandle()。
共享单一文件映射对象的方式之一是给这个文件映射对象起一个名称。
然后,当两个或多个进程用同一个名称调用 CreateFileMapping() 时,就
可以共享一个文件映射对象。第一个进程实际创建这个文件映射对象,而其
后的进程只是简单地关联到已存在的对象上。看起来似乎有点古怪,即使有
好几个不同进程调用这个函数,也只创建一个文件映射对象,而共享的本性
就是并不总能容易地判断哪个进程先开始。为了认定调用这个函数时没有创
建新的、唯一的文件映射对象,可调用 GetLastError(),并检查 ERROR_
ALREADY_EXISTS 返回值。
用于在进程间共享内存映射文件的第二个函数是 OpenFileMapping(),
它的参数之一是文件映射对象的名称。这个函数假设文件映射对象已经通过
调用 CreateFileMapping() 创建。如果名称指出的对象不存在,这个函数
返回一个NULL文件映射句柄。(记住,句柄值-1只用来指示文件打开错。)
连接到已存在的文件映射对象的第三个函数是 DuplicateHandle(),
它创建一个其他进程可以使用的 KERNEL 句柄。KERNEL 句柄是供单个进程
专用的,但是这个函数允许你从已存在的其他进程的句柄创建新句柄。注意,
这个函数只能用于映射某些类型的句柄(完整的列表见 Win32 文档)。一
般来说,这个函数不能复制用户界面对象句柄或 GDI 绘图对象句柄。然而,
它可以用来复制 KERNEL 对象,严格地说,在 Windows NT 上叫做可执行
对象,这些对象包括文件句柄、文件映射对象、进程、线程、信号量、互斥
和事件。
创建视图对象
一旦创建了文件对象和文件映射对象,访问内存映射文件的第三步就是
创建一个或多个数据文件的视图。创建视图时保留了地址空间,以允许访问
部分内存映射文件。为了访问这个范围的地址时,分配了内存页并从磁盘上
读取数据。可以对一个文件建立多个视图,以有选择地访问内存映射文件的
不同部分。例如,对文件开头建立视图以访问头标信息;对结尾创建视图,
这里可能存储有头标的副本;对中间区域创建视图,这里驻留着各种数据。
要创建内存映射文件的视图,调用 MapViewOfFile()。这个函数的定义如
下:
LPVOID WINAPI
MapViewOfFile(
HANDLE hFileMappingObject,
DWORD dwDesiredAccess,
DWORD dwFileOffsetHigh,
DWORD dwFileOffsetLow,
DWORD dwNumberofBytesToMap);
hFileMappingObject 参数是文件映射对象的句柄。dwDesiredAccess
参数是要对文件映射数据所做的访问。例如,它可以是 FILE_MAP_READ,表
示只读访问,也可以是 FILE_MAP_READ|FILE_MAP_WRITE,表示读写访问。
dwFileOffsetHigh 参数是要映射到内存的文件区域的开头在文件中的
偏移量的高 32 位。 dwFileOffsetLow 参数是要映射到内存的文件区域的
开头在文件中的偏移量的低 32 位。 dwNumberOfBytesToMap 参数是映射
的字节数。其大小将向上取整至最接近的页边界(在 Intel 芯片上是4K)。
如果这个参数值为 0,则映射整个文件。
下面这个例子显示的是如何调用这个函数来创建一个引用文件的前4096
字节的视图:
// Create view of file mapping object
LPVOID lpData;
lpData = MapViewOfFile(hFileMapping,
FILE_MAP_READ, // Page Protection
0, // File Offset-Hi 32-bits
0, // File Offset-Low 32-bits
4096); // Size of view
把共享访问内存映射文件的例程稍加变化,就可以在进程间共享页。下面
讨论了该方法所涉及的内容。
-- 独人独剑独马
浪迹天涯 ...
※ 来源:.月光软件站 http://www.moon-soft.com.[FROM: 202.99.93.224]
|
|