居然這就是C++記憶體對映檔案?!
記憶體對映檔案大家都時不時聽過,但它到底是個什麼?趕緊來看看吧
記憶體對映檔案到底是幹嘛的呢?讓我們先來思考下面幾個問題:
如果您想讀的內容大於系統分配的記憶體塊怎麼辦?如果您想搜尋的字串剛好超過記憶體塊的邊界又該如何處理?對於第一個問題,您也許會說,只要不斷地讀就不解決了嗎。至於第二個問題,您又會說在記憶體塊的邊界處做一些特別的處理,譬如放上一些標誌位就可以了。原理上確實是行得通,但是這隨問題複雜程度加深而顯得非常難以處理。其中的第二個問題是有名的邊界判斷問題,程式中許許多多的錯誤都是由此引起。想一想,如果我們能夠分配一個能夠容納整個檔案的大記憶體塊該多好啊,這樣這兩個問題不都迎刃而解了嗎?是的,WIN32的記憶體對映檔案確實允許我們分配一個裝得下現實中可能存在的足夠大的檔案的記憶體。
#include
#include
#include
#include
using namespace std;
int main()
{
/開始
//獲得檔案控制程式碼
HANDLE hFile=CreateFile(
"c:\test.dat", //檔名
GENERIC_READ|GENERIC_WRITE, //對檔案進行讀寫操作
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING, //開啟已存在檔案
FILE_ATTRIBUTE_NORMAL,
0);
//返回值size_high,size_low分別表示檔案大小的高32位/低32位
DWORD size_low,size_high;
size_low= GetFileSize(hFile,&size_high);
//建立檔案的記憶體對映檔案。
HANDLE hMapFile=CreateFileMapping(
hFile,
NULL,
PAGE_READWRITE, //對對映檔案進行讀寫
size_high,
size_low, //這兩個引數共64位,所以支援的最大檔案長度為16EB
NULL);
if(hMapFile==INVALID_HANDLE_VALUE)
{
AfxMessageBox("Can't create file mapping.Error%d:n", GetLastError());
CloseHandle(hFile);
return 0;
}
//把檔案資料對映到程式的地址空間
void* pvFile=MapViewOfFile(
hMapFile,
FILE_MAP_READ|FILE_MAP_WRITE,
0,
0,
0);
unsigned char *p=(unsigned char*)pvFile;
//至此,就獲得了外部檔案test.dat在記憶體地址空間的對映,
//下面就可以用指標p"折磨"這個檔案了
CString s;
p[size_low-1]='!';
p[size_low-2]='X'; //修改該檔案的最後兩個位元組(檔案大小
#include
#include
#include
#include
using namespace std;
int main()
{
//開始
//獲得檔案控制程式碼
HANDLE hFile=CreateFile(
"c:\test.dat", //檔名
GENERIC_READ|GENERIC_WRITE, //對檔案進行讀寫操作
FILE_SHARE_READ|FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING, //開啟已存在檔案
FILE_ATTRIBUTE_NORMAL,
0);
//返回值size_high,size_low分別表示檔案大小的高32位/低32位
DWORD size_low,size_high;
size_low= GetFileSize(hFile,&size_high);
//建立檔案的記憶體對映檔案。
HANDLE hMapFile=CreateFileMapping(
hFile,
NULL,
PAGE_READWRITE, //對對映檔案進行讀寫
size_high,
size_low, //這兩個引數共64位,所以支援的最大檔案長度為16EB
NULL);
if(hMapFile==INVALID_HANDLE_VALUE)
{
AfxMessageBox("Can't create file mapping.Error%d:n", GetLastError());
CloseHandle(hFile);
return 0;
}
//把檔案資料對映到程式的地址空間
void* pvFile=MapViewOfFile(
hMapFile,
FILE_MAP_READ|FILE_MAP_WRITE,
0,
0,
0);
unsigned char *p=(unsigned char*)pvFile;
//至此,就獲得了外部檔案test.dat在記憶體地址空間的對映,
//下面就可以用指標p"折磨"這個檔案了
CString s;
p[size_low-1]='!';
p[size_low-2]='X'; //修改該檔案的最後兩個位元組(檔案大小
往小了說,只要你把這幾個API函式搞定了,一般的記憶體對映問題就可以解決了。。
利用記憶體對映檔案您可以認為作業系統已經為您把檔案全部裝入了記憶體,然後您只要移動檔案指標進行讀寫即可了。這樣您甚至不需要呼叫那些分配、釋放記憶體塊和檔案輸入/輸出的API函式,另外您可以把這用作不同的程式之間共享資料的一種辦法。運用記憶體對映檔案實際上沒有涉及實際的檔案操作,它更象為每個程式保留一個看得見的記憶體空間。
至於把記憶體對映檔案當成程式間共享資料的辦法來用,則要加倍小心,因為您不得不處理資料的同步問題,否則您的應用程式也許很可能得到過時或錯誤的資料甚至崩潰。本課中我們將主要講述記憶體對映檔案,將不涉及程式間的同步。WIN32中的記憶體對映檔案應用非常廣泛,譬如:即使是系統的核心模組—PE格式檔案裝載器也用到了記憶體對映檔案,因為PE格式的檔案並不是一次性載入到記憶體中來的,譬如他它在首次載入時只載入必需載入的部分,而其他部分在用到時再載入,這正好可以利用到記憶體對映檔案的長處。實際中的大多數檔案存取都和PE載入器類似,所以您在處理該類問題時也應該充分利用記憶體對映檔案。
以下介紹如何使用CreateFileMapping,MapViewOfFile建立記憶體對映檔案,如何向記憶體對映檔案中寫入資料,讀取資料。
#include
#include
#include
#include
#define BAD_POS 0xFFFFFFFF // returned by SetFilePointer and GetFileSize
#define SUCCESS 0
using namespace std;
typedef DWORD mmf_share_mode;
typedef DWORD mmf_access_mode;
typedef DWORD mmf_flags;
int main(){
cout
記憶體對映檔案本身還是有一些侷限性的,譬如一旦您生成了一個記憶體對映檔案,那麼您在那個會話期間是不能夠改變它的大小的。所以記憶體對映檔案對於只讀檔案和不會影響其大小的檔案操作是非常有用的。當然這並不意味著對於會引起改變其大小的檔案操作就一定不能用記憶體影射檔案的方法,您可以事先估計操作後的檔案的可能大小,然後生成這麼大小一塊的記憶體對映檔案,然後檔案的長度就可以增長到這麼一個大小。
#include
#include
#include
#include
#define BAD_POS 0xFFFFFFFF // returned by SetFilePointer and GetFileSize
#define SUCCESS 0
using namespace std;
typedef DWORD mmf_share_mode;
typedef DWORD mmf_access_mode;
typedef DWORD mmf_flags;
int main(){
cout
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/4479/viewspace-2802896/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 使用記憶體對映檔案(mmap)記憶體
- 二進位制檔案記憶體對映記憶體
- Python mmap的使用-檔案記憶體對映Python記憶體
- windows核心程式設計--記憶體對映檔案Windows程式設計記憶體
- Java記憶體對映,上G大檔案輕鬆處理Java記憶體
- 溫故之.NET程式間通訊——記憶體對映檔案記憶體
- C#記憶體對映大檔案並使用Marshal解析結構體資訊C#記憶體結構體
- linux記憶體管理(八)- 反向對映RMAPLinux記憶體
- 從記憶體對映mmap說開去記憶體
- 這。。這。。C++標頭檔案居然可以這麼打!!!! 長見識了!!!C++
- C++ struct結構體記憶體對齊C++Struct結構體記憶體
- C/C++記憶體對齊原則C++記憶體
- C/C++記憶體對齊詳解C++記憶體
- linux檔案存在記憶體裡Linux記憶體
- 載入Mapper對映檔案APP
- Mybatis對映檔案簡介MyBatis
- 共享記憶體對映(linux程式與執行緒學習筆記)記憶體Linux執行緒筆記
- Ubuntu 新增虛擬記憶體檔案Ubuntu記憶體
- C++記憶體管理C++記憶體
- Mybatis【配置檔案】就是這麼簡單MyBatis
- 作業系統-記憶體、檔案管理作業系統記憶體
- C++記憶體掃描C++記憶體
- C++記憶體管理剖析C++記憶體
- nginx容器卷對映檔案不生效Nginx
- 記憶體對齊記憶體
- Mybatis 學習筆記(一)——配置檔案SqlMapConfig.xml和對映檔案Mapper.xmlMyBatis筆記SQLXMLAPP
- C++記憶體管理:簡易記憶體池的實現C++記憶體
- 記憶體檔案系統的再學習記憶體
- dump檔案解析之探索.Net的記憶體記憶體
- 【Redis】 redis解析rdb檔案,記憶體排序等Redis記憶體排序
- 從核心世界透視 mmap 記憶體對映的本質(原理篇)記憶體
- C++動態記憶體分配C++記憶體
- C++手寫記憶體池C++記憶體
- Hibernate配置檔案中對映元素詳解
- MyBaits | 對映檔案之引數處理AI
- GO 記憶體對齊Go記憶體
- 理解記憶體對齊記憶體
- PHP超低記憶體遍歷目錄檔案和讀取超大檔案PHP記憶體