在Windows系统中,CreateFileMapping函数是用来创建文件映射的API函数。文件映射是一种与文件相关的内存映射方式,可以让进程共享同一份物理内存。使用CreateFileMapping函数可以方便地将文件映射到内存中,在多个进程间共享文件数据。本文将介绍如何使用CreateFileMapping函数在Windows中创建文件映射。
一、CreateFileMapping函数简介
CreateFileMapping函数是Windows系统中的一个API函数,声明在Windows.h头文件中。该函数可以将文件映射到内存中,来实现多个进程间能够共享文件数据。以下是CreateFileMapping函数的原型:
HANDLE CreateFileMapping(
HANDLE hFile,
LPSECURITY_ATTRIBUTES lpAttributes,
DWORD flProtect,
DWORD dwMaximumSizeHigh,
DWORD dwMaximumSizeLow,
LPCTSTR lpName
);
CreateFileMapping函数的参数解释如下:
1. hFile:表示待映射的文件句柄。当该参数值为INVALID_HANDLE_VALUE时,则会创建一个新的文件映射对象。
2. lpAttributes:指向SECURITY_ATTRIBUTES结构的指针,用来设置文件映射对象的安全描述符。如果该参数值为NULL,则文件映射对象默认有一个NULL描述符。
3. flProtect:指定内存页的保护级别。可以是以下几种值之一:
- PAGE_READONLY:只读保护
- PAGE_READWRITE:可读可写保护
- PAGE_WRITECOPY:写拷贝保护
- PAGE_EXECUTE:可执行保护
- PAGE_EXECUTE_READ:可执行可读保护
- PAGE_EXECUTE_READWRITE:可执行可读可写保护
- PAGE_EXECUTE_WRITECOPY:可执行写拷贝保护
4. dwMaximumSizeHigh和dwMaximumSizeLow:指定文件映射的最大大小。以DWORD为单位。若要创建可用空间,此参数不能为0.当数据超出当前大小时,系统会自动增加文件大小。如果文件大小为零且文件名非空,则将创建1页空间。
5. lpName:指定文件映射对象的名称,如果要在多个进程间共享文件映射对象,则必须指定文件映射对象的名称。如果要让系统为映射对象指定自定义名称,则可以将该参数设置为空值。
二、使用CreateFileMapping函数创建文件映射
1.使用已有文件创建文件映射对象
当我们需要将已有文件映射到内存中时,可以调用CreateFile函数来打开该文件,并将文件句柄传给CreateFileMapping函数来创建文件映射对象。
以下是使用CreateFileMapping函数创建文件映射对象的示例代码:
HANDLE hFile = CreateFile(_T("D:\\test.txt"), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); //打开一个文件
HANDLE hFileMapping = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); //创建文件映射对象
2.创建新的文件映射对象
如果需要创建新的文件映射对象,可以将hFile参数设置为INVALID_HANDLE_VALUE,这样就会创建一个新文件映射对象。
以下是创建新文件映射对象的示例代码:
HANDLE hFileMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, nSize, lpName); //创建一个新的文件映射对象
三、使用文件映射实现进程间通信
文件映射不仅可以将文件映射到内存中,还可以让多个进程间共享同一份物理内存。使用该方式可以有效地实现进程间通信(IPC)。在多进程编程中,文件映射通常用来实现下面的两种情况:
1.不同进程之间共享数据
多个进程同时需要访问同一个数据,这时就需要将该数据映射到文件中,并将文件映射到内存中。这样每个进程都可以通过文件映射对象访问同一份物理内存,来实现进程间的数据共享。
以下是共享内存的示例代码:
//创建文件映射对象
HANDLE hMapping = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, dwSize, _T("myMapping"));
if (hMapping == NULL){
return -1;
}
//获取映射到进程地址空间的指针
LPVOID pData = MapViewOfFile(hMapping, FILE_MAP_WRITE, 0, 0, 0);
//向共享内存写数据
strcpy_s((char*)pData, 100, "My name is Alina");
//控制释放资源
UnmapViewOfFile(pData);
CloseHandle(hMapping);
//在另一个进程中打开文件映射对象,并将其映射到虚拟地址空间
HANDLE hMapping = OpenFileMapping(FILE_MAP_READ, FALSE, _T("myMapping"));
LPVOID pData = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
printf((char*)pData); //输出打印共享内存数据
UnmapViewOfFile(pData);
CloseHandle(hMapping);
2.互斥共享资源访问
在多进程编程中,经常需要统一管理进程之间的资源访问,以防止不同进程之间的资源争用,产生资源冲突。使用文件映射可以非常方便地实现同步互斥。
以下是同步互斥的示例代码:
HANDLE hMutex = CreateMutex(NULL, FALSE, _T("myMutex"));
//加锁
WaitForSingleObject(hMutex, INFINITE);
//处理共享资源
//释放锁
ReleaseMutex(hMutex);
//在另一个进程中打开Mutex对象进行排他性控制
HANDLE hMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, _T("myMutex"));
//等待锁
WaitForSingleObject(hMutex, INFINITE);
//处理共享资源
//释放锁
ReleaseMutex(hMutex);
四、总结
使用CreateFileMapping函数可以非常方便地将文件映射到内存中,在多个进程间共享文件数据和内存资源。文件映射在进程间通信中的应用也非常广泛,可以用来实现共享数据和同步互斥。在使用文件映射时,需要注意文件保护级别、文件大小以及文件映射对象的命名方式。同时,在资源使用完成后,也需要释放相应的资源避免资源泄露的问题。