用內(nèi)存映射文件處理大文件應(yīng)用示例
下面結(jié)合一個(gè)具體的實(shí)例來進(jìn)一步講述內(nèi)存映射文件的使用方法。該實(shí)例從端口接收數(shù)據(jù),并實(shí)時(shí)將其存放于磁盤,由于數(shù)據(jù)量大(幾十GB),在此選用內(nèi)存映射文件進(jìn)行處理。下面給出的是位于工作線程MainProc中的部分主要代碼,該線程自程序運(yùn)行時(shí)啟動(dòng),當(dāng)端口有數(shù)據(jù)到達(dá)時(shí)將會(huì)發(fā)出事件hEvent[0],WaitForMultipleObjects()函數(shù)等待到該事件發(fā)生后將接收到的數(shù)據(jù)保存到磁盤,如果終止接收將發(fā)出事件hEvent[1],事件處理過程將負(fù)責(zé)完成資源的釋放和文件的關(guān)閉等工作。下面給出此線程處理函數(shù)的具體實(shí)現(xiàn)過程:
……
// 創(chuàng)建文件內(nèi)核對(duì)象,其句柄保存于hFile
HANDLE hFile = CreateFile("Recv1.zip",
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
// 創(chuàng)建文件映射內(nèi)核對(duì)象,句柄保存于hFileMapping
HANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE,
0, 0x4000000, NULL);
// 釋放文件內(nèi)核對(duì)象
CloseHandle(hFile);
// 設(shè)定大小、偏移量等參數(shù)
__int64 qwFileSize = 0x4000000;
__int64 qwFileOffset = 0;
__int64 T = 600 * sinf.dwAllocationGranularity;
DWORD dwBytesInBlock = 1000 * sinf.dwAllocationGranularity;
// 將文件數(shù)據(jù)映射到進(jìn)程的地址空間
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)
{
// 接收數(shù)據(jù)事件觸發(fā)
case 0:
// 從端口接收數(shù)據(jù)并保存到內(nèi)存映射文件
nReadLen=syio_Read(port[1], pbFile + qwFileOffset, QueueLen);
qwFileOffset += nReadLen;
// 當(dāng)數(shù)據(jù)寫滿60%時(shí),為防數(shù)據(jù)溢出,需要在其后開辟一新的映射視圖
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);
}
下面結(jié)合一個(gè)具體的實(shí)例來進(jìn)一步講述內(nèi)存映射文件的使用方法。該實(shí)例從端口接收數(shù)據(jù),并實(shí)時(shí)將其存放于磁盤,由于數(shù)據(jù)量大(幾十GB),在此選用內(nèi)存映射文件進(jìn)行處理。下面給出的是位于工作線程MainProc中的部分主要代碼,該線程自程序運(yùn)行時(shí)啟動(dòng),當(dāng)端口有數(shù)據(jù)到達(dá)時(shí)將會(huì)發(fā)出事件hEvent[0],WaitForMultipleObjects()函數(shù)等待到該事件發(fā)生后將接收到的數(shù)據(jù)保存到磁盤,如果終止接收將發(fā)出事件hEvent[1],事件處理過程將負(fù)責(zé)完成資源的釋放和文件的關(guān)閉等工作。下面給出此線程處理函數(shù)的具體實(shí)現(xiàn)過程:
……
// 創(chuàng)建文件內(nèi)核對(duì)象,其句柄保存于hFile
HANDLE hFile = CreateFile("Recv1.zip",
GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ,
NULL,
CREATE_ALWAYS,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL);
// 創(chuàng)建文件映射內(nèi)核對(duì)象,句柄保存于hFileMapping
HANDLE hFileMapping = CreateFileMapping(hFile,NULL,PAGE_READWRITE,
0, 0x4000000, NULL);
// 釋放文件內(nèi)核對(duì)象
CloseHandle(hFile);
// 設(shè)定大小、偏移量等參數(shù)
__int64 qwFileSize = 0x4000000;
__int64 qwFileOffset = 0;
__int64 T = 600 * sinf.dwAllocationGranularity;
DWORD dwBytesInBlock = 1000 * sinf.dwAllocationGranularity;
// 將文件數(shù)據(jù)映射到進(jìn)程的地址空間
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)
{
// 接收數(shù)據(jù)事件觸發(fā)
case 0:
// 從端口接收數(shù)據(jù)并保存到內(nèi)存映射文件
nReadLen=syio_Read(port[1], pbFile + qwFileOffset, QueueLen);
qwFileOffset += nReadLen;
// 當(dāng)數(shù)據(jù)寫滿60%時(shí),為防數(shù)據(jù)溢出,需要在其后開辟一新的映射視圖
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);
}

