為什麼內存映射文件需要加鎖
㈠ 內存映射文件問題
在軟體的開發過程中,有時需要控制一些程序使他們不能同時運行,也就是多個程序間互斥運行(還包括禁止同一程序運行多個實例)。針對這一問題,我們在Visual C++6.0中利用內存映射文件實現了多個程序間的互斥運行。內存映射文件可以創建一個沒有和磁碟文件相聯系的內存對象,將文件的信息映射到一個進程的地址空間上,我們可以訪問該文件中的數據,就如同它位於內存中一樣。同時,在程序設計中可以給內存映射文件對象起一個名字,這個名字在整個系統中是唯一的,這個名字可以在多個進程之間共享,通過名字共享能實現進行信息交換,進而實現多個程序間的互斥運行。
在講述具體的編程方法之前,讓我們先介紹和內存映射文件操作有關的幾個重要的函
CreateFileMapping的函數為指定的文件創建一個文件映射對象,該函數的原形如下:
HANDLE CreateFileMapping(HANDLE hFile,//用於映射的文件句柄 LPSECURITY?ATTRIBUTES FileMappingAttributes,//內存映射文件的安全描述符 DWORD Flprotect,//文件映射對象的最大長度的高32位 DWORD dwMaximumSizelow,//最大長度的低32位 LPCTSTR IPNAME//指定這個內存映射文件的名字)
值得注意的是,參數如果是OXFFFFFFFF,將在操作系統虛擬內存頁面替換文件中創建文件映射對象,而不是使用磁碟文件,同時必須給出這個映射對象的大小。
NAO VUEWIFFILE函數將文件的視圖映射到一個進程地址空間上,返回LPVOID類型的內存指針。通過它,就可以直接訪問文件視圖中的信息。
LPVOID MAP VIEWLFFILE(HANDLE HFILEMAPPINGOBUCT,//映射文件對象句柄 DWORD DWDESIREDACCESS,//訪問模式 DWORD DWFILEOFFSETHIGH,//文件偏移地址的高32位 DWORD DWFILEOFFSETHIGH,//文件偏移地址的低32位 DWORD DWNUMBEROFBYTESTOMAP//映射視圖的大小)
在Visual c++6.0中我們用默認方式生成基於對話框的應用程序,在程序的初始化階段,在CwinApp生類的Initln_stance函數的開始處,添加以下代碼:
(//創建內存映射文件對象,mu_texRunning是其名字,所有需要互斥運行 //的程序都使用這個名字(這些代碼對於需要互斥運行的程序是通用的)HANDLE hMap=CreateFileMapping((HANDLE)0Xffffffffnull,PAGE_READWRLTE,0,128,"Mu_texRunning") if(hMap==NULL)//如果創建失敗 (AfxMessageBox("創建用於互斥運行的內存映文件對象失敗!」,MB?OK MB??ICLNSTOP);
return FALSE;//退出此程序)
//如果已經存在這個同名對象,說明已有需要互斥的其他程序運行了
else if(GetLastError( )==ER_ROR_ALREADY_EXISTS)
(LPVOID ipMen=MapViewOFFile(hMap,FILE_MAP_WRITE,0,0,0);
Cstring str=(char*)ipMem;//獲得已在運行的程序的描述信息
UnmapViewofFile(lpMem);//解除映射圖
CloseHandle(hMap);//關閉此對象
AfxMessageBox(str,MB_ok MB_ICONSTOP);顯示有關的描述信息
Return FALSE;//退出此程序)
Else//經過上面的檢查,說明這是第一個運行的互斥程序
(LPVOID ip_mem=MapViewofFile(hMap,FILE_MAP_WRITE,0,0,0);
//這里可寫入該程序運行的描述信息,上面的錯誤提示就是這信信息
strcpy((char*)lpMem,"xxx程序正在運行!」);
UnmapViewofFile(lpMem);//解除映射圖)
//下面可以繼續執行函數INITIN?STANCE原有的代碼了
AfxEnableControl_comtainer();
//當程序運行結束了,要記住調用CHANDIE(HMAP)關閉這個對象句柄,//這里可以在Initinstance函數最後returnFALSE之前調用
CloseHandle(hMap);//關閉內存映文件對象句柄 RETURN false;)以上的程序在Visual C++6.中已調試通過。其他非對話框類型的程序可以在各自的初始化和終止階段添加類似的代碼,只是如果內存映射文件對象的句柄hMap可能在不同函數中使用,那就要將其定義成CwinApp生類的成員變數或是全局變數了。
㈡ 對內存映射文件寫入,程序關閉後,文件並沒有更新其內容
映射部分是否是與專用段落或是未被鎖定。請核實
㈢ 內存映射是怎麼回事
內存映射文件是由一個文件到一塊內存的映射,使進程虛擬地址空間的某個區域與磁碟上某個文件的部分或全部內容的建立映射。
建立映射後,通過該區域可以直接對被映射的磁碟文件進行訪問.而不必執行文件I/O操作也無需對文件內容進行緩沖處理。
就好像整個被映射的文件都載入到了內存一樣,因此內存文件映射非常適合於用來管理大文件。
內存映射文件對程序的提速,只在處理大文件或非常頻繁的文件讀寫操作時效果才明顯。
通過內存映射,相當於將磁碟上的文件所在空間建立成一塊虛擬內存,程序訪問時可按內存的方式進行,省去了普通io方式的一些環節,其實真正要讀寫操作時,會進行換頁,將這些個「虛擬內存」讀到物理內存中。
總之,內存映射文件是應用虛擬內存的技術來達到加速處理的
㈣ 內存映射文件的使用
為什麼要內存映射?
ReadFile本來就不是一次把文件全部讀到內存。
㈤ 內存映射文件的內存文件
內存映射文件與虛擬內存有些類似,通過內存映射文件可以保留一個地址空間的區域,同時將物理存儲器提交給此區域,只是內存文件映射的物理存儲器來自一個已經存在於磁碟上的文件,而非系統的頁文件,而且在對該文件進行操作之前必須首先對文件進行映射,就如同將整個文件從磁碟載入到內存。由此可以看出,使用內存映射文件處理存儲於磁碟上的文件時,將不必再對文件執行I/O操作,這意味著在對文件進行處理時將不必再為文件申請並分配緩存,所有的文件緩存操作均由系統直接管理,由於取消了將文件數據載入到內存、數據從內存到文件的回寫以及釋放內存塊等步驟,使得內存映射文件在處理大數據量的文件時能起到相當重要的作用。另外,實際工程中的系統往往需要在多個進程之間共享數據,如果數據量小,處理方法是靈活多變的,如果共享數據容量巨大,那麼就需要藉助於內存映射文件來進行。實際上,內存映射文件正是解決本地多個進程間數據共享的最有效方法。
內存映射文件並不是簡單的文件I/O操作,實際用到了Windows的核心編程技術--內存管理。所以,如果想對內存映射文件有更深刻的認識,必須對Windows操作系統的內存管理機制有清楚的認識,下面給出使用內存映射文件的一般方法:
首先要通過CreateFile()函數來創建或打開一個文件內核對象,這個對象標識了磁碟上將要用作內存映射文件的文件。在用CreateFile()將文件映像在物理存儲器的位置通告給操作系統後,只指定了映像文件的路徑,映像的長度還沒有指定。為了指定文件映射對象需要多大的物理存儲空間還需要通過CreateFileMapping()函數來創建一個文件映射內核對象以告訴系統文件的尺寸以及訪問文件的方式。在創建了文件映射對象後,還必須為文件數據保留一個地址空間區域,並把文件數據作為映射到該區域的物理存儲器進行提交。由MapViewOfFile()函數負責通過系統的管理而將文件映射對象的全部或部分映射到進程地址空間。此時,對內存映射文件的使用和處理同通常載入到內存中的文件數據的處理方式基本一樣,在完成了對內存映射文件的使用時,還要通過一系列的操作完成對其的清除和使用過資源的釋放。這部分相對比較簡單,可以通過UnmapViewOfFile()完成從進程的地址空間撤消文件數據的映像、通過CloseHandle()關閉前面創建的文件映射對象和文件對象。
㈥ 內存映射文件的原理
講點基礎的你了解了再去看那些資料就好懂多了。
1。內存映射文件簡單概述
內存文件映射也是Windows的一種內存管理方法,提供了一個統一的內存管理特徵,使應用程序可以通過內存指針對磁碟上的文件進行訪問,其過程就如同對載入了文件的內存的訪問。通過文件映射這種使磁碟文件的全部或部分內容與進程虛擬地址空間的某個區域建立映射關聯的能力,可以直接對被映射的文件進行訪問,而不必執行文件I/O操作也無需對文件內容進行緩沖處理。內存文件映射的這種特性是非常適合於用來管理大尺寸文件的。
2。使用內存映射文件的一般流程
而在某些特殊行業,經常要面對十幾GB乃至幾十GB容量的巨型文件,而一個32位進程所擁有的虛擬地址空間只有232 = 4GB,顯然不能一次將文件映像全部映射進來。對於這種情況只能依次將大文件的各個部分映射到進程中的一個較小的地址空間。這需要對上面的一般流程進行適當的更改:
1)映射文件開頭的映像。
2)對該映像進行訪問。
3)取消此映像
4)映射一個從文件中的一個更深的位移開始的新映像。
5)重復步驟2,直到訪問完全部的文件數據。
㈦ 為什麼要內存映射
內存映射(mmap)是一種內存映射文件的方法,即將一個文件或者其他對象映射到進程的地址空間,實現文件磁碟地址和應用程序進程虛擬地址空間中一段虛擬地址的一一映射關系。實現這樣的映射關系後,進程就可以採用指針的方式讀寫操作這一段內存,而系統會自動回寫藏頁面到對應的文件磁碟上。應用程序處理映射部分如同訪問主存。(1)線程啟動映射過程,並在虛擬地址空間中為映射創建虛擬映射區域。
先在用戶空間調用庫函數mmap,並在進程當前進程的虛擬地址空間中,尋找一段空閑的滿足要求的連續虛擬地址作為內存虛擬映射區域,對此區域初始化並插入進程的虛擬地址區域鏈表或樹中。
(2)系統在內核空間調用內核函數mmap,實現文件物理地址和進程虛擬地址之間的一一映射關系。
(3)進程發起堆這片映射空間的訪問
進程讀寫操作訪問虛擬地址,查詢頁表,發現這一段地址並不在內存的物理頁面上,因為雖然建立了映射關系,但是還沒有將文件從磁碟移到內存中。由此發生缺頁中斷,內核請求從磁碟調入頁面。調頁過程先在交換緩存空間(swap cache)中查找,若沒有則通過nopage函數把缺失頁從磁碟調入內存。之後進程會對其做讀寫操作,若寫操作改變了頁面內容,一段時間後系統會自動回寫臟頁面到磁碟中。(修改過的臟頁面不會立即更新到文件中,可以調用msync來強制同步,寫入文件)
㈧ 如何對mmap區域的數據進行加鎖
如果內存映射文件是將文件全部讀取到內存中,那麼「內存映射文件」和你直接從文件讀取數據,全部裝入內存就沒有區別了,內存映射文件也就沒有存在的意義了。 內存映射文件的原理是通過數據訪問局部性這個原理來提高性能的。什麼叫數據訪問局部性呢?我們從統計學意義上分析,如果你讀取文件中某個地方的數據,那麼你接下來讀取的數據在之前讀取地址附近的概率,要比讀取很遠的地方的數據的概率要高。 那麼,如果操作系統得到請求,你要獲取某個數據,它在讀取這個數據的時候,順帶手將這一塊的數據都讀取到內存中。也許接下來很不幸,你讀取的數據不在操作系統預取的范圍內,但是這是少數情況。多數情況是,你接下來再讀的數據,內存中已經有了,此時操作系統無需再訪問磁碟,直接從內存中返回。 雖然這比一次性全部讀進內存,100%的數據都能訪問到要稍微遜色一些,但是我們用很經濟的代價(可能只要原數據10%的內存)得到了近乎完美的性能(和完全讀到內存相比性能可能相差10%)。 是不是這樣一來性能就提高了?內存映射文件的含義就是,操作系統透明處理了很多載入、更新、回寫緩存的操作,使得開發者看上去像是讀取文件,但是結果是更快實現了IO的存取。同時又避免數據過大不能一次性讀取到內存的問題。
㈨ 什麼是內存映射文件 高手進來
將文件內容(可部分可整個映射到內存地址上),操作文件時就只操作內存地址就行了,其它的操作系統幫你做。