【轉載】Windows下記憶體對應檔的工作原理及使用方法

來源:互聯網
上載者:User

原文地址:http://hi.baidu.com/handsomedtl/blog/item/e4d449359a47a146241f1445.html

一、引言
  WIN32 API為我們提供了一種進行檔案操作的高效途徑,即記憶體對應檔。記憶體對應檔允許我們在WIN32進程的虛擬位址空間中保留一段記憶體地區,把目標檔案映射到這段虛擬記憶體之中。我們可以用存取記憶體資料的方式直接操作檔案中的資料,就好像這些資料放在記憶體中一樣。而實際上,我們並沒有、也不需要調用API函數來讀寫檔案,更不需要自己提供任何緩衝演算法,作業系統將會為我們完成這些工作。使用記憶體對應檔能給程式開發工作提供極大的方便,程式的運行效率也非常高。
  記憶體對應檔在Windows NT和Windows95中的實現機制略有不同,下面主要介紹Windows95下記憶體對應檔的工作原理及使用方法。
  二、Windows95如何管理WIN32進程的記憶體空間
  記憶體對應檔的實現與Windows95的記憶體管理有密切的關係,因此先討論一下Windows95在運行WIN32進程時的記憶體管理與劃分。
  在Windows3.x下,所有Windows應用程式共用單一的地址空間,任何進程都能夠對這一空間中屬於其他進程的記憶體進行讀寫操作,甚至可以存取作業系統本身的重要資料。在這種環境中,編寫不當的應用程式或者帶有惡意的應用程式,就可能破壞其他程式的資料或代碼,使得系統運行不正常,嚴重時甚至會導致系統崩潰。
  在實現了WIN32的作業系統Windows NT和Windows95中,每個WIN32進程擁有自己的地址空間,一個WIN32進程不能存取另一個進程地址空間的私人資料,兩個進程可以用具有相同值的指標定址,但所讀寫的只是它們各自的資料,這樣就大大減少了進程之間的相互幹擾,增強了系統的健壯性;另一方面,每個WIN32進程擁有4GB的地址空間,但並不代表它真正擁有4GB的實際實體記憶體,而只是作業系統利用CPU的記憶體分頁功能提供的虛擬位址空間。在一般情況下,絕大多數虛擬位址並沒有實體記憶體與之對應,在真正可以使用這些地址空間之前,還要由作業系統提供實際的實體記憶體。為虛擬位址提供實際實體記憶體的過程叫做“提交”(Commit)。在不同情況下,系統提交的實體記憶體的類型是不同的,可能是RAM,也可能是硬碟類比的虛擬記憶體。
  Windows95對WIN32進程地址空間的劃分如下:
  地址空間底部的4MB由Windows95用來維護與DOS和16位Windows的相容性。理想情況下,WIN32進程應該不能訪問這段記憶體,但由於實現上的困難,Windows95隻能保護低端從0x00000000到0x00000FFF的4KB地區,這4KB區間用來捕獲NULL指標。從0x80000000到0xBFFFFFFF的1GB空間由所有的WIN32進程共用,記憶體對應檔就使用這段地址空間。高端的1GB空間由Windows95自己使用,不像Windows NT那樣,這段空間也沒有受到保護,任何進程都可能破壞其中的資料。
  三、記憶體對應檔的工作原理
  記憶體對應檔分三種情況,第一種是可執行檔的記憶體映射,主要由Windows95自身使用;第二種是資料檔案的記憶體映射;最後一種是藉助於頁面分頁檔的記憶體映射。應用程式可以使用後面兩種記憶體對應檔。
  1、可執行檔的記憶體映射
  Windows95在執行一個WIN32應用程式時使用記憶體對應檔,它為將要執行的EXE檔案保留足夠大的地址空間。一般情況下,這段空間是從WIN32進程的載入地址0x00400000開始,系統給這段空間提交的實體儲存體就是硬碟上的EXE檔案本身。做好各項準備工作後,系統開始執行這個程式。剛開始,程式的代碼並不在RAM中,執行程式入口的第一條指令時會產生一個頁面異常,系統捕獲到這個異常後,分配一塊RAM,將其映射到0x00400000處,並把實際代碼讀入其中,然後繼續執行。以後在執行到不在RAM中的代碼時,同樣會產生頁面異常,從而系統有機會讀入這些代碼。系統以類似的方式處理WIN32DLL,只是DLL被映射到的地址空間是由所有WIN32進程共用的。
  當使用者運行同一個應用程式的第二個執行個體時,系統知道程式已經有一個執行個體了,EXE檔案的代碼和資料已經被讀到RAM中,系統只需要把這段RAM再映射到新進程的地址空間就行了,這就實現了共用RAM中的代碼和資料。事實上,這種共用只是針對唯讀資料,一旦出現進程改寫自身代碼和資料,作業系統會把被修改資料所在頁面拷貝一份,分配給執行寫操作的進程,從而避免了多個執行個體之間的相互幹擾。
  當然,作業系統執行一個WIN32應用程式的實際過程非常複雜,上面所描述的只是工作原理。我們可以用Softicefor Windows95來驗證作業系統是以對應檔的方式來執行一個應用程式的:使用Wldr第一次調入一個應用程式如Notepad時,Softice被啟用。它所列出的程式的入口代碼處全是Invalid(無效),這表明將要執行的代碼所在頁面並不在RAM之中。按下F8,逐步執行一條指令,螢幕上立刻列出了真正的程式指令,這是因為指令執行時首先產生了一個頁面異常,作業系統在處理頁面異常時,將代碼讀入RAM之中。Softice再次被啟用時,就能看見剛讀入的指令了。進一步檢查還可以發現,系統每次唯讀一個頁面(4KB)到RAM中,以便盡量節約記憶體。我們再用Wldr調入Notepad的第二個執行個體,這一次Softice被啟用後列出的入口代碼不再是Invalid,而是真正的程式指令。由於Softice是系統級的調試器,用它修改記憶體中的應用程式時,作業系統並不做頁面拷貝。我們將Notepad的入口代碼做一點改動,然後再用Wldr調入第三個執行個體。這次可以發現,列出的入口代碼是剛剛修改過的,而實際的EXE檔案並無任何變化,這表明,作業系統把同一塊RAM中的程式碼映射到多個進程的地址空間中,從而實現了共用RAM中的程式碼。
  2、資料檔案的記憶體映射
  資料檔案記憶體映射的工作原理與可執行檔的記憶體映射原理是一樣的。首先把資料檔案的一部分映射到虛擬位址空間(映射到的地區是在0x80000000-0xBFFFFFFF內),但不提交RAM,存取這段記憶體的指令同樣會產生頁面異常。作業系統捕獲到這個異常後,分配一頁RAM,並把它映射到當前進程發生異常的地址處,然後系統把檔案中相應的資料讀到這個頁面中,繼續執行剛才產生異常的指令。這就是應用程式自己不需要調用檔案I/O函數的原因。
  3、基於頁面分頁檔的記憶體映射
  記憶體對應檔的第三種情況是基於頁面分頁檔的。一個WIN32進程可以利用記憶體對應檔在WIN32進程共用的地址空間中保留一塊地區,這塊地區與系統的頁面分頁檔相聯絡。我們可以用它來儲存臨時資料,但更常見的用法是,利用它與其他WIN32進程進行通訊。事實上,WIN32實現多處理序間通訊的各種方法都是通過記憶體對應檔來實現的,例如PostMessage()函數或SendMessage()函數,在內部都使用了記憶體對應檔。
  四、使用記憶體對應檔的方法
  1、利用記憶體對應檔進行檔案I/O操作,進行檔案I/O操作需要下面幾個步驟:
  步驟一:調用CreateFile()函數,以適當的方式建立或開啟一個檔案核心對象;
  步驟二:把CreateFile()函數返回的檔案控制代碼作為參數,傳給CreateFileMapping()函數,由CreateFileMapping()函數建立一個檔案對應核心對象的適當屬性;
  步驟三:建立了檔案對應核心對象後,調用MapViewOfFile()函數,告訴系統把檔案的哪一部分映射到進程的地址空間中,以何種方式映射;
  步驟四:利用MapViewOfFile()函數返回的指標來使用檔案資料;
  步驟五:操作完畢後,調用UnmapViewOfFile()函數,告訴系統撤銷對檔案對應核心對象的映射;
  步驟六:使用CloseHandle()函數關閉檔案對應核心對象;
  步驟七:使用CloseHandle()函數關閉檔案核心對象;
  各個API函數的詳細說明請參考Windows95SDK或一些編程工具的線上說明。
  2、利用記憶體對應檔實現WIN32進程間的通訊
  在Windows95下,一個進程開啟的檔案對應物件的映射區對所有的WIN32進程都是可視的,並且映射區的地址對所有WIN32進程都是一樣的。一個進程可以開啟一個檔案,建立檔案對應核心對象,用MapViewOfFile()函數開啟檔案視圖,然後將檔案對應的地址傳給另一個進程,第二個進程就可以讀出檔案中的資料。這種方法需要進行各進程間的同步,實現起來較困難。並且在Windows NT中,一個映射區在不同的WIN32進程空間中對應的地址不同,因此為了與Windows NT相容,盡量不要使用這種方法。
  第二種方法是兩個進程使用同一檔案對應核心對象,開啟各自的視圖,或者父進程把自己建立的檔案對應核心對象繼承給子進程使用。這種方法比較安全有效。
  第三種方法是建立基於頁面分頁檔的記憶體映射對象。在調用CreateFileMapping()函數時,傳遞檔案控制代碼為0xFFFFFFFF,系統就從頁面分頁檔中提交實體儲存體,然後進程之間按照第二種方法進行通訊。這種方法不用事先準備一個特殊的檔案,非常方便。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.