轉(zhuǎn)自:http://www.zxbc.cn/html/20080524/51094.html

          與虛擬內(nèi)存一樣,內(nèi)存映射文件可以用來保留一個地址空間的區(qū)域,一旦該文件被映射,就可以訪問它,就像整個文件已經(jīng)加載內(nèi)存一樣。

          ??內(nèi)存映射文件可以用于3個不同的目的:

          ???1. 系統(tǒng)使用內(nèi)存映射文件,以便加載和執(zhí)行exe 和dll文件,這可以大大節(jié)省頁文件空間和應(yīng)用程序啟動運行所需的時間。
          ???2.可以使用內(nèi)存映射文件來訪問磁盤上的數(shù)據(jù)文件,這使你可以不必對文件執(zhí)行I/O操作,并且可以不必對文件內(nèi)容進行緩存。
          ???3.可以使用內(nèi)存映射文件,使同一臺計算機上運行的多個進程能夠相互之間共享數(shù)據(jù),Windows確實提供了其他一些方法,以便在進程之間進行數(shù)據(jù)通信,但是這些方法都是使用內(nèi)存映射文件來實現(xiàn)的,這使得內(nèi)存映射文件成為單個計算機上多個進程互相進行同行的最有效的方法。

          一.內(nèi)存映射文件的函數(shù)包括

          CreateFileMapping , OpenFileMapping, MapViewOfFile, UnmapViewOfFile FlushViewOfFile

          用法如下:

          1 HANDLE CreateFileMapping(

          ? HANDLE????????????????? hFile,????????????? // 一個文件句柄

          ? LPSECURITY_ATTRIBUTE? lpAttributes,???????? // 定義內(nèi)存映射文件對象是否可以被承

          ? DWORD?????????????????? flProtect,?????????? // 該內(nèi)存映射文件的保護類型

          ? DWORD?????????????????? dwMaximumSizeHigh,// 內(nèi)存映射文件的長度

          ? DWORD?????????????????? dwMaximumSizeLow, //

          ? LPCTSTR????????????????? lpName???????????? // 內(nèi)存映射文件的名字

          )

          hFile?????? 指定要映射的文件的句柄,如果這是一個已經(jīng)打開的文件的句柄( CreateFile 函數(shù)的返回值),那么將建立這個文件的內(nèi)存映射文件,如果這個參數(shù)為 -1 ,則建立共享內(nèi)存。

          lpAttribute? 安全屬性,一般設(shè)為 NULL

          flProtect??? 指定映射文件的保護類型,它的取值可以是 PAGE_READONLY (內(nèi)存頁面只讀) PAGE_READWRITE (內(nèi)存頁面可讀寫)。

          dwMaximumSizeHigh dwMaximumSizeLow 參數(shù)組合指定了一個 64 位的內(nèi)存映射文件的長度。一種簡單的方法是將這兩個參數(shù)全部設(shè)置為 0 ,那么內(nèi)存映射文件的大小將與磁盤文件大小一致。

          2 HANDLE OpenFileMapping(

          ????? DWORD?????????????? dwDesiredAccess,??? // 指定保護類型

          ????? BOOL????????????????? bIsInheritHandle,???? // 返回的句柄是否可以被繼承

          ????? LPCSTR??????????????? lpName???????????? // 創(chuàng)建對象時使用的名字

          ????

          如果創(chuàng)建的是共享內(nèi)存,其他進程不能再使用 CreateFileMapping 函數(shù)去創(chuàng)建同名的內(nèi)存映射文件對象,而要使用 OpenFileMapping 函數(shù)打開已創(chuàng)建好的對象。

          dwDesiredAcess?? 指定保護類型有 FILE_MAP_WRITE FILE_MAP_READ

          3 LPVOID? MapViewOfFile(

          ????? HANDLE? hFileMappingObject,??? // 前兩個函數(shù)返回的內(nèi)存映射文件的句柄

          ????? DWORD? dwDesiredAcess,???? ?// 保護類型 FILE_MAP_READ ,FILE_MAP_WRITE

          ????? DWORD? dwFileOffsetHight,???? // 從文件的那個地址開始映射

          ????? DWORD? dwFileOffsetLow,

          ????? SIZE_T?? dwNumberOfBytesToMap // 要映射的字節(jié)數(shù),為 0 則映射整個文件

          4 BOOL? UnmapViewOfFile( LPCVOID? lpBaseAddress )

          當(dāng)不再使用內(nèi)存映射文件時,可以通過 UmmapViewOfFile 函數(shù)撤銷映射并使用 CloseHandle 函數(shù)關(guān)閉內(nèi)存映射文件的句柄。

          5 BOOL? FlushViewOfFile(

          ?????? LPCVOID?? lpBaseAddress,? // 開始的地址

          ?????? SIZE_T???? dwNumberOfBytesToFlush // 數(shù)據(jù)塊的大小

          ?

          ? 如果修改了映射視圖中的內(nèi)存,系統(tǒng)會在試圖撤銷映射或文件映射對象被刪除時自動將數(shù)據(jù)寫到磁盤上,但程序也可以根據(jù)需要將視圖中的數(shù)據(jù)立即寫到磁盤上。

          二.使用步驟

          1.? 使用 CreateFileMapping 創(chuàng)建一個內(nèi)存映射文件內(nèi)核對象,告訴操作系統(tǒng)內(nèi)存映射文件需要的物理內(nèi)存大小,這個步驟決定了內(nèi)存映射文件的用途――究竟是為磁盤上的文件建立內(nèi)存映射還是為多個進程共享數(shù)據(jù)建立共享內(nèi)存。或者使用 OpenFileMapping 打開映射文件內(nèi)核對象。

          2.? 映射文件映射對象的全部或一部分到進程的地址空間,可以認(rèn)為該操作是為文件中的內(nèi)容分配線型地址空間,并將線型地址和文件內(nèi)容對應(yīng)起來,完成該操作的函數(shù)是 MapViewOfFile

          ?

          三.使用內(nèi)存映射文件讀文件的具體過程可以這樣:

          (1)??????? 調(diào)用 CreateFile 函數(shù)打開想要映射的文件,得到文件句柄 hFile

          (2)??????? 調(diào)用 CreateFileMapping 函數(shù),并傳入文件句柄 hFile ,為該文件創(chuàng)建一個內(nèi)存映射內(nèi)核對象,得到內(nèi)存映射文件的句柄 hMap

          (3)??????? 調(diào)用 MapViewOfFile 函數(shù)映射整個文件或一部分到進程的虛擬地址空間。該函數(shù)返回文件映射到內(nèi)存后的起始地址。使用指向這個地址的指針就可以讀取文件的內(nèi)容了。

          (4)??????? 調(diào)用 UnmapViewOfFile 函數(shù)來解除文件映射。

          (5)??????? 調(diào)用 CloseHandle 函數(shù)關(guān)閉文件對象,必須傳入內(nèi)存映射文件句柄 hMap

          (6)??????? 調(diào)用 CloseHandle 函數(shù)關(guān)閉文件對象,必須傳入文件句柄 hFile

          ?

          四.進程間共享內(nèi)存:

          共享內(nèi)存主要是通過映射機制實現(xiàn)的。 Windows 下進程的地址空間是相互隔離的,但在物理上卻是重疊的。所謂的重疊是指同一塊內(nèi)存區(qū)域可能被多個進程同時使用。當(dāng)調(diào)用 CreateFileMapping 創(chuàng)建命名的內(nèi)存映射文件對象時, Windows 即在物理內(nèi)存中申請了一塊指定大小的內(nèi)存區(qū)域,返回文件映射對象的新句柄 hMap 。為了能夠訪問這塊區(qū)域必須調(diào) MapViewOfiFile 函數(shù),促使 Windows 將此內(nèi)存空間映射到進程的地址空間中。當(dāng)在其他進程中訪問這塊區(qū)域時,則必須使用 OpenFileMapping 函數(shù)來取得對象句柄 hMap ,并調(diào)用 MapViewOfFile 函數(shù)得到此內(nèi)存空間的一個映射。這樣一來,系統(tǒng)就把同一塊內(nèi)存區(qū)域映射到了不同進程的地址空間中,從而達到共享內(nèi)存的目的。

          一段實例代碼:
          ?BOOL?????bRet?????=?TRUE;
          ????HANDLE???hMapFile?
          =?NULL;
          ????FILEMAP
          *?pFileMap?=?NULL;

          ????g_hFileMap?
          =?::CreateFileMapping(INVALID_HANDLE_VALUE,
          ????????NULL,?
          ????????PAGE_READWRITE,?
          ????????
          0,?
          ????????
          sizeof(FILEMAP),?
          ????????g_FileMapFlag);

          ????
          if?(g_hFileMap?&&?ERROR_ALREADY_EXISTS?==?::GetLastError())
          ????{
          ????????pFileMap?
          =?(FILEMAP*)::MapViewOfFile(g_hFileMap,?FILE_MAP_READ,?0,?0,?0);
          ????????
          if?(pFileMap)
          ????????{
          ????????????ATLASSERT(::IsWindow(pFileMap
          ->hForegroundWnd));

          ????????????::PostMessage(pFileMap
          ->hForegroundWnd,?WM_SYSCOMMAND,?SC_RESTORE,?0);
          ????????????::SetForegroundWindow(pFileMap
          ->hForegroundWnd);
          ????????????bRet?
          =?FALSE;
          ????????}

          ????????::UnmapViewOfFile(pFileMap);
          ????}
          posted on 2009-04-14 00:34 -274°C 閱讀(1557) 評論(1)  編輯  收藏 所屬分類: C++


          FeedBack:
          # re: 內(nèi)存映射文件
          2009-04-14 11:42 | -274°C
          寫入:
          pFileMap = (FILEMAP*)::MapViewOfFile(g_hFileMap, FILE_MAP_WRITE, 0, 0, 0);
          if (pFileMap)
          {
          pFileMap->hForegroundWnd = hWnd;
          bRet = TRUE;
          }
          ::UnmapViewOfFile(pFileMap);  回復(fù)  更多評論
            

          常用鏈接

          留言簿(21)

          隨筆分類(265)

          隨筆檔案(242)

          相冊

          JAVA網(wǎng)站

          關(guān)注的Blog

          搜索

          •  

          積分與排名

          • 積分 - 916878
          • 排名 - 40

          最新評論

          主站蜘蛛池模板: 全椒县| 土默特右旗| 尼勒克县| 屯门区| 子长县| 防城港市| 兴安盟| 余干县| 呼伦贝尔市| 花莲县| 会昌县| 青州市| 田阳县| 凤山县| 湖南省| 寻乌县| 张家港市| 同江市| 本溪| 浏阳市| 伊川县| 淮安市| 湟源县| 浠水县| 磴口县| 石屏县| 珲春市| 翁牛特旗| 云南省| 抚州市| 曲靖市| 巴彦县| 嘉鱼县| 崇信县| 象山县| 旌德县| 常宁市| 遵义市| 班戈县| 临城县| 乌兰察布市|