轉自:http://www.zxbc.cn/html/20080524/51094.html

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

          ??內存映射文件可以用于3個不同的目的:

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

          一.內存映射文件的函數包括

          CreateFileMapping , OpenFileMapping, MapViewOfFile, UnmapViewOfFile FlushViewOfFile

          用法如下:

          1 HANDLE CreateFileMapping(

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

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

          ? DWORD?????????????????? flProtect,?????????? // 該內存映射文件的保護類型

          ? DWORD?????????????????? dwMaximumSizeHigh,// 內存映射文件的長度

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

          ? LPCTSTR????????????????? lpName???????????? // 內存映射文件的名字

          )

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

          lpAttribute? 安全屬性,一般設為 NULL

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

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

          2 HANDLE OpenFileMapping(

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

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

          ????? LPCSTR??????????????? lpName???????????? // 創建對象時使用的名字

          ????

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

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

          3 LPVOID? MapViewOfFile(

          ????? HANDLE? hFileMappingObject,??? // 前兩個函數返回的內存映射文件的句柄

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

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

          ????? DWORD? dwFileOffsetLow,

          ????? SIZE_T?? dwNumberOfBytesToMap // 要映射的字節數,為 0 則映射整個文件

          4 BOOL? UnmapViewOfFile( LPCVOID? lpBaseAddress )

          當不再使用內存映射文件時,可以通過 UmmapViewOfFile 函數撤銷映射并使用 CloseHandle 函數關閉內存映射文件的句柄。

          5 BOOL? FlushViewOfFile(

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

          ?????? SIZE_T???? dwNumberOfBytesToFlush // 數據塊的大小

          ?

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

          二.使用步驟

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

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

          ?

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

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

          (2)??????? 調用 CreateFileMapping 函數,并傳入文件句柄 hFile ,為該文件創建一個內存映射內核對象,得到內存映射文件的句柄 hMap

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

          (4)??????? 調用 UnmapViewOfFile 函數來解除文件映射。

          (5)??????? 調用 CloseHandle 函數關閉文件對象,必須傳入內存映射文件句柄 hMap

          (6)??????? 調用 CloseHandle 函數關閉文件對象,必須傳入文件句柄 hFile

          ?

          四.進程間共享內存:

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

          一段實例代碼:
          ?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 閱讀(1548) 評論(1)  編輯  收藏 所屬分類: C++


          FeedBack:
          # re: 內存映射文件
          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);  回復  更多評論
            

          常用鏈接

          留言簿(21)

          隨筆分類(265)

          隨筆檔案(242)

          相冊

          JAVA網站

          關注的Blog

          搜索

          •  

          積分與排名

          • 積分 - 914103
          • 排名 - 40

          最新評論

          主站蜘蛛池模板: 建始县| 延吉市| 松江区| 清涧县| 东莞市| 瑞昌市| 滦平县| 中方县| 阿合奇县| 峡江县| 镇安县| 安国市| 桦南县| 金山区| 广德县| 滕州市| 郧西县| 柳江县| 莱阳市| 砀山县| 武清区| 麻阳| 息烽县| 大方县| 汶上县| 馆陶县| 陇川县| 舒城县| 游戏| 广东省| 克拉玛依市| 咸阳市| 河曲县| 罗田县| 阿荣旗| 贵溪市| 通江县| 涞源县| 周宁县| 随州市| 普定县|