VC++中使用内存映射文件处理大文件(2)

2026-02-06
用内存映射文件处理大文件应用示例

  下面结合一个具体的实例来进一步讲述内存映射文件的使用方法。该实例从端口接收数据,并实时将其存放于磁盘,由于数据量大(几十GB),在此选用内存映射文件进行处理。下面给出的是位于工作线程MainProc中的部分主要代码,该线程自程序运行时启动,当端口有数据到达时将会发出事件hEvent[0],WaitForMultipleObjects()函数等待到该事件发生后将接收到的数据保存到磁盘,如果终止接收将发出事件hEvent[1],事件处理过程将负责完成资源的释放和文件的关闭等工作。下面给出此线程处理函数的具体实现过程:

  ……

  // 创建文件内核对象,其句柄保存于hFile

  HANDLE hFile = CreateFile("Recv1.zip",

  GENERIC_WRITE | GENERIC_READ,

  FILE_SHARE_READ,

  NULL,

  CREATE_ALWAYS,

  FILE_FLAG_SEQUENTIAL_SCAN,

  NULL);

  // 创建文件映射内核对象,句柄保存于hFileMapping

  HANDLE 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);

  }