要用, 當然要先建立... 就如同要結婚首先要把到美眉是一樣的 XD 首先呢, 先呼叫 CreateFile() 開啟一個檔案, 或是建立一個新檔. 這視你是臨時用用, 還是開啟那個檔起來處理裡面的資料. 這邊我只關心兩個參數, 其他的請自己去查 MSDN 第一個是 Access Mode, CreateFile() 可以用 Read, Write 或是 Read | Write = Access (R/W) 的模式開啟. 當然, 這看你打算怎麼去用這塊記憶體. (它是檔案, 存在磁碟機上, 不過, 當它被mapping的時候, 它也同時是記憶體) 第二個是 Share Mode, CreateFile() 可以指定 No Share, Share Read, Share Write, 或是 Share Read | Share Write = Share Access (Share R/W). 如果是 Debug 版, 你可以考慮指定成為 Share Read 或甚至是 Share Read/Write. 這樣你就可以用個 Hex Editor 開啟這個 Memory file, 然後監看, 甚至去偷改了. 出貨版當然是不理他, 設為 0 啦. 然後, 拿著 CreateFile() 傳回來的 Handle, 丟給 CreateFileMapping(), 去建立 Mapping File handle.
請注意, 一定要檢查 CreateFile() 的傳回值, 否則.. 後述. XD 當然, 這東西等於就是記憶體, 所以你要指定一個屬性: PAGE_READONLY, PAGE_READWRITE, PAGE_WRITECOPY.
第三個指的是, 當你要對這個 memory mapping 寫入任何東西時, OS 會 copy 一份專屬你的 page . 於是乎, 原始檔案就不會被作任何的改變. Memory mapping file 可以 support 到 16 EB (註1), 比你直接可用的 RAM 還大多了. 因此呢, 你要傳兩個 32 bits 的參數去表示檔案大小. 想利用目前檔案的 Size, 請傳入 0; 如果你想擴建這個檔案, 請你要指定好 size. 就像你在 Alloc memory 是一樣的. 最後一個工作, 就是實際把 File mapping 到虛擬記憶空間去. 請呼叫 MapViewOfFile() MapViewFile() 可以指定要從檔案的哪裡開始, 然後要 View 的空間範圍有多大. 畢竟, Memory mapping file support 16 EB, 而我們沒有這麼大的 Virtual Memory space 去 mapping. 成功之後它會傳回一個 PVIOD 的指標, 你就可以用這個指標開始 access 了, 就當它是 Memory 一樣使用. 作完這些, 你就可以開始使用 Memory mapping file 了. 好吧, 我知道有人會抱怨: 我不是要處理超大型物件, 只是要跨行程分享一些資料, 能不能不要建立一個檔案啊, 我們有安全上的考量, 我們有那樣這樣的考量... 可以的, 只要你把 INVALID_HANDLE_VALUE 當成參數傳給 CreateFileMapping() 的 file handle, 如此, 這個 mapping 就不需要檔案, 可以直接建立在 swap file 中. 這也是為什麼我在前面提到一定要 check CreateFile() 傳回來的參數是否正確的原因. 因為 CreateFile() 如果 fail, 傳回來的參數也正好是 INVALID_HANDLE_VALUE. XD 好孩子在用完 OS 以後一定要記得歸還喔!
UnmapViewFile() 用來歸還 MapViewFile() mapping 的 virtual address. 不過為了確保東西寫回去了, 最好是先呼叫一下 FlushViewOfFile().
CreateFileMapping() 跟 CreateFile() 傳回的都是 Handle, 所以請用 CloseHandle() 關掉就可以了. 另外, MapViewFile() 為什麼需要指定從檔案的哪裡開始呢...
因為, 當你 Mapping 檔案到 Virtual Memory 時, OS 必需要能夠找到足夠的空間 mapping. 假設你有一個 200GB 的檔案, 檔案太大了, 無法一次 mapping 到 Virtual Memory 去, 你只好先用 CreateFileMapping() 開啟這個檔, 然後用 MapViewFile() 去 mapping 某一段, 用完以後 UnmapViewFile() 先釋放, 然後再呼叫 MapViewFile() 去 mapping 下一段... 直到你都用完了, 才呼叫 CloseHandle() 去釋回 CreateFileMapping() 及 CreateFile() 的 Handle. 壞消息是, 在 Win9x/ME 中, 要被 Mapping 到記憶空間的檔案總大小, 不能比未被使用的記憶空間大... 即使你只是要 mapping 其中一小塊. 這個功能只有 WinNT support. 最後, 讓我們用一個行程間共享記憶體的範例當結束吧 XD
註1:
Kilo-Byte = 2^10
Mega-Byte = 2^20
Giga-Byte = 2^30
Tera-Byte = 2^40
Peta-Byte = 2^50
Exa-Byte = 2^60
Zetta-Byte = 2^70
Yotta-Byte = 2^80
---
小葵..小葵有很多的夢想
等待薰下班回家, 並準備晚飯跟洗澡水
薰回家的時候, 對你說一聲 歡迎回家
在休息的日子, 兩個人坐在屋外的走廊上, 品嚐著我親自作的點心
薰如果累了, 替他搥搥肩; 冷了, 和薰一起擠著被爐
但是, 但是... 小葵最大的心願是...成為薰的..成為薰的妻子