Windows核心编程 第十七章 -内存映射文件(下)
17.3?使用內(nèi)存映射文件
若要使用內(nèi)存映射文件,必須執(zhí)行下列操作步驟:
1)?創(chuàng)建或打開一個文件內(nèi)核對象,該對象用于標(biāo)識磁盤上你想用作內(nèi)存映射文件的文件。
2)?創(chuàng)建一個文件映射內(nèi)核對象,告訴系統(tǒng)該文件的大小和你打算如何訪問該文件。
3)?讓系統(tǒng)將文件映射對象的全部或一部分映射到你的進(jìn)程地址空間中。
當(dāng)完成對內(nèi)存映射文件的使用時,必須執(zhí)行下面這些步驟將它清除:
1)?告訴系統(tǒng)從你的進(jìn)程的地址空間中撤消文件映射內(nèi)核對象的映像。
2)?關(guān)閉文件映射內(nèi)核對象。
3)?關(guān)閉文件內(nèi)核對象。
下面將詳細(xì)介紹這些操作步驟。
17.3.1?步驟1:創(chuàng)建或打開文件內(nèi)核對象
? ? 若要創(chuàng)建或打開一個文件內(nèi)核對象,總是要調(diào)用C?r?e?a?t?e?F?i?l?e函數(shù):
? ? C?r?e?a?t?e?F?i?l?e函數(shù)擁有好幾個參數(shù)。這里只重點(diǎn)介紹前?3個參數(shù),即p?s?z?F?i?l?e?N?a?m?e,d?w?D?e?s?i?r?e?dA?c?c?e?s?s和d?w?S?h?a?r?e?M?o?d?e。
你可能會猜到,第一個參數(shù)?p?s?z?F?i?l?e?N?a?m?e用于指明要創(chuàng)建或打開的文件的名字(包括一個選項(xiàng)路徑)。第二個參數(shù)d?w?D?e?s?i?r?e?d?A?c?c?e?s?s用于設(shè)定如何訪問該文件的內(nèi)容。可以設(shè)定表?1?7?-?3所列的4個值中的一個。
? ? 當(dāng)創(chuàng)建或打開一個文件,將它作為一個內(nèi)存映射文件來使用時,請選定最有意義的一個或
多個訪問標(biāo)志,以說明你打算如何訪問文件的數(shù)據(jù)。對內(nèi)存映射文件來說,必須打開用于只讀訪問或讀寫訪問的文件,因此,可以分別設(shè)定?G?E?N?E?R?I?C?_?R?E?A?D或GENERIC_READ??|G?E?N?E?R?I?C?_?W?R?I?T?E。
? ? 第三個參數(shù)d?w?S?h?a?r?e?M?o?d?e告訴系統(tǒng)你想如何共享該文件。可以為?d?w?S?h?a?r?e?M?o?d?e設(shè)定表1?7?-?4所列的4個值之一。
? ? 如果C?r?e?a?t?e?F?i?l?e函數(shù)成功地創(chuàng)建或打開指定的文件,便返回一個文件內(nèi)核對象的句柄,否則返回I?N?VA?L?I?D?_?H?A?N?D?L?E?_?VA?L?U?E。
注意?能夠返回句柄的大多數(shù)Wi?n?d?o?w?s函數(shù)如果運(yùn)行失敗,那么就會返回N?U?L?L。但是,C?r?e?a?t?e?F?i?l?e函數(shù)將返回I?N?VA?L?I?D?_?H?A?N?D?L?E?_?VA?L?U?E,它定義為((H?A?N?D?L?E)-?1)。
17.3.2?步驟2:創(chuàng)建一個文件映射內(nèi)核對象
????調(diào)用C?r?e?a?t?e?F?i?l?e函數(shù),就可以將文件映像的物理存儲器的位置告訴操作系統(tǒng)。你傳遞的路徑名用于指明支持文件映像的物理存儲器在磁盤(或網(wǎng)絡(luò)或光盤)上的確切位置。這時,必須告訴系統(tǒng),文件映射對象需要多少物理存儲器。若要進(jìn)行這項(xiàng)操作,可以調(diào)用?C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù):
????第一個參數(shù)h?F?i?l?e用于標(biāo)識你想要映射到進(jìn)程地址空間中的文件句柄。該句柄由前面調(diào)用的C?r?e?a?t?e?F?i?l?e函數(shù)返回。p?s?a參數(shù)是指向文件映射內(nèi)核對象的S?E?C?U?R?I?T?Y?_?AT?T?R?I?B?U?T?E?S結(jié)構(gòu)的指針,通常傳遞的值是N?U?L?L(它提供默認(rèn)的安全特性,返回的句柄是不能繼承的)。
????本章開頭講過,創(chuàng)建內(nèi)存映射文件就像保留一個地址空間區(qū)域然后將物理存儲器提交給該區(qū)域一樣。因?yàn)閮?nèi)存映射文件的物理存儲器來自磁盤上的一個文件,而不是來自從系統(tǒng)的頁文件中分配的空間。當(dāng)創(chuàng)建一個文件映射對象時,系統(tǒng)并不為它保留地址空間區(qū)域,也不將文件的存儲器映射到該區(qū)域(下一節(jié)將介紹如何進(jìn)行這項(xiàng)操作)。但是,當(dāng)系統(tǒng)將存儲器映射到進(jìn)程的地址空間中去時,系統(tǒng)必須知道應(yīng)該將什么保護(hù)屬性賦予物理存儲器的頁面。
C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù)的f?d?w?P?r?o?t?e?c?t參數(shù)使你能夠設(shè)定這些保護(hù)屬性。大多數(shù)情況下,可以設(shè)定表1?7?-?5中列出的3個保護(hù)屬性之一。
????Windows?98?在Windows?98下,可以將PA?G?E?_?W?R?I?T?E?C?O?P?Y標(biāo)志傳遞給C?r?e?a?t?e?F?i?l?eM?a?p?p?i?n?g,這將告訴系統(tǒng)從頁文件中提交存儲器。該頁文件存儲器是為數(shù)據(jù)文件的數(shù)據(jù)拷貝保留的,只有修改過的頁面才被寫入頁文件。你對該文件的數(shù)據(jù)所作的任何修
改都不會重新填入原始數(shù)據(jù)文件。其最終結(jié)果是,?PA?G?E?_?W?R?I?T?E?C?O?P?Y標(biāo)志的作用在Windows?2000和Windows?98上是相同的。
? ? 除了上面的頁面保護(hù)屬性外,還有?4個節(jié)保護(hù)屬性,你可以用?O?R將它們連接起來放入C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù)的f?d?w?P?r?o?t?e?c?t參數(shù)中。節(jié)只是用于內(nèi)存映射的另一個術(shù)語。
? ? 節(jié)的第一個保護(hù)屬性是?S?E?C?_?N?O?C?A?C?H?E,它告訴系統(tǒng),沒有將文件的任何內(nèi)存映射頁面放入高速緩存。因此,當(dāng)將數(shù)據(jù)寫入該文件時,系統(tǒng)將更加經(jīng)常地更新磁盤上的文件數(shù)據(jù)。這個標(biāo)志與PA?G?E?_?N?O?C?A?C?H?E保護(hù)屬性標(biāo)志一樣,是供設(shè)備驅(qū)動程序開發(fā)人員使用的,應(yīng)用程序通常不使用。
Windows?98?Windows?98將忽略S?E?C?_?N?O?C?A?C?H?E標(biāo)志。
? ? 節(jié)的第二個保護(hù)屬性是?S?E?C?_?I?M?A?G?E,它告訴系統(tǒng),你映射的文件是個可移植的可執(zhí)行(P?E)文件映像。當(dāng)系統(tǒng)將該文件映射到你的進(jìn)程的地址空間中時,系統(tǒng)要查看文件的內(nèi)容,以確定將哪些保護(hù)屬性賦予文件映像的各個頁面。例如,?P?E文件的代碼節(jié)(?.?t?e?x?t)通常用PA?G?E?_?E?X?E?C?U?T?E?_?R?E?A?D?屬?性進(jìn)?行映?射,?而?P?E文?件的?數(shù)據(jù)?節(jié)?(?.?d?a?t?a?)?則通?常用PA?G?E?_?R?E?A?D?W?R?I?T?E屬性進(jìn)行映射。如果設(shè)定的屬性是?S?E?C?_?I?M?A?G?E,則告訴系統(tǒng)進(jìn)行文件映像的映射,并設(shè)置相應(yīng)的頁面保護(hù)屬性。
? ? Windows?98?Windows?98將忽略S?E?C?_?I?M?A?G?E標(biāo)志。
? ? 最后兩個保護(hù)屬性是?S?E?C?_?R?E?S?E?RV?E和S?E?C?_?C?O?M?M?I?T,它們是兩個互斥屬性,當(dāng)使用內(nèi)存映射數(shù)據(jù)文件時,它們不能使用。這兩個標(biāo)志將在本章后面介紹。當(dāng)創(chuàng)建內(nèi)存映射數(shù)據(jù)文件時,不應(yīng)該設(shè)定這些標(biāo)志中的任何一個標(biāo)志。C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g將忽略這些標(biāo)志。
? ? C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g的另外兩個參數(shù)是d?w?M?a?x?i?m?u?m?S?i?z?e?H?i?g?h和d?w?M?a?x?i?m?u?m?S?i?z?e?L?o?w,它們是兩個最重要的參數(shù)。C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù)的主要作用是保證文件映射對象能夠得到足夠的物理存儲器。這兩個參數(shù)將告訴系統(tǒng)該文件的最大字節(jié)數(shù)。它需要兩個?3?2位的值,因?yàn)?/span>Wi?n?d?o?w?s支持的文件大小可以用?6?4位的值來表示。d?w?M?a?x?i?m?u?m?S?i?z?e?H?i?g?h參數(shù)用于設(shè)定較高的3?2位,而d?w?M?a?x?i?m?u?m?S?i?z?e?L?o?w參數(shù)則用于設(shè)定較低的?3?2位值。對于?4?GB或小于4?GB的文件來說,d?w?M?a?x?i?m?u?m?S?i?z?e?H?i?g?h的值將始終是0。
? ? 使用6?4位的值,意味著Wi?n?d?o?w?s能夠處理最大為1?6?E?B(1?0?1?8?字節(jié))的文件。如果想要創(chuàng)建一個文件映射對象,使它能夠反映文件當(dāng)前的大小,那么可以為上面兩個參數(shù)傳遞?0。如果只打算讀取該文件或者訪問文件而不改變它的大小,那么為這兩個參數(shù)傳遞?0。如果打算將數(shù)據(jù)附加給該文件,可以選擇最大的文件大小,以便為你留出一些富裕的空間。如果當(dāng)前磁盤上的文件包含0字節(jié),那么可以給?C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù)的d?w?M?a?x?i?m?u?m?S?i?z?e?H?i?g?h和d?w?M?a?x?i?m?u?mS?i?z?e?L?o?w傳遞兩個0。這樣做就可以告訴系統(tǒng),你要的文件映射對象里面的存儲器為?0字節(jié)。這是個錯誤,C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g將返回N?U?L?L。
? ? 如果你對我們講述的內(nèi)容一直非常關(guān)注,你一定認(rèn)為這里存在嚴(yán)重的問題。?Wi?n?d?o?w?s支持最大為1?6?E?B的文件和文件映射對象,這當(dāng)然很好,但是,怎樣將這樣大的文件映射到?3?2位進(jìn)程的地址空間(3?2位地址空間是4?G?B文件的上限)中去呢?下一節(jié)介紹解決這個問題的辦法。當(dāng)然,6?4位進(jìn)程擁有16?EB的地址空間,因此可以進(jìn)行更大的文件的映射操作,但是,如果文件是個超大規(guī)模的文件,仍然會遇到類似的問題。
書中給了個例子,讓自己一步一步調(diào)看文件大小變化:
上面是我寫的,CreadeFile會創(chuàng)建一個0字節(jié)大小的aaaa.dat,然后下面那個CreateFileMapping會把文件大小編程100字節(jié)。里面內(nèi)容是空(NULL)。
????如果調(diào)用C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù),傳遞PA?G?E?_?R?E?A?D?W?R?I?T?E標(biāo)志,那么系統(tǒng)將設(shè)法確保磁盤上的相關(guān)數(shù)據(jù)文件的大小至少與?d?w?M?a?x?i?m?u?m?S?i?z?e?H?i?g?h和d?w?M?a?x?i?m?u?m?S?i?z?e?L?o?w參數(shù)中設(shè)定的大小相同。如果該文件小于設(shè)定的大小,?C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù)將擴(kuò)展該文件的大小,使磁盤上的文件變大。這種擴(kuò)展是必要的,這樣,當(dāng)以后將該文件作為內(nèi)存映射文件使用時,物理存儲器就已經(jīng)存在了。如果正在用?PA?G?E?_?R?E?A?D?O?N?LY或PA?G?E?_?W?R?I?T?E?C?O?P?Y標(biāo)志創(chuàng)建該文件映射對象,那么C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g特定的文件大小不得大于磁盤文件的物理大小。這是因?yàn)槟銦o法將任何數(shù)據(jù)附加給該文件。
????C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù)的最后一個參數(shù)是p?s?z?N?a?m?e。它是個以0結(jié)尾的字符串,用于給該文件映射對象賦予一個名字。該名字用于與其他進(jìn)程共享文件映射對象(本章后面展示了它的一個例子。第3章詳細(xì)介紹了內(nèi)核對象的共享操作)。內(nèi)存映射數(shù)據(jù)文件通常并不需要被共享,因此這個參數(shù)通常是N?U?L?L。
系統(tǒng)創(chuàng)建文件映射對象,并將用于標(biāo)識該對象的句柄返回該調(diào)用線程。如果系統(tǒng)無法創(chuàng)建文件映射對象,便返回一個N?U?L?L句柄值。記住,當(dāng)C?r?e?a?t?e?F?i?l?e運(yùn)行失敗時,它將返回I?N?VA?L?I?D?_H?A?N?D?L?E?_?VA?L?U?E(定義為-1),當(dāng)C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g運(yùn)行失敗時,它返回N?U?L?L。請不要混淆這些錯誤值。
17.3.3?步驟3:將文件數(shù)據(jù)映射到進(jìn)程的地址空間
? ? 當(dāng)創(chuàng)建了一個文件映射對象后,仍然必須讓系統(tǒng)為文件的數(shù)據(jù)保留一個地址空間區(qū)域,并將文件的數(shù)據(jù)作為映射到該區(qū)域的物理存儲器進(jìn)行提交。可以通過調(diào)用?M?a?p?Vi?e?w?O?f?F?i?l?e函數(shù)來進(jìn)行這項(xiàng)操作:
? ? 參數(shù)h?F?i?l?e?M?a?p?p?i?n?g?O?b?j?e?c?t用于標(biāo)識文件映射對象的句柄,該句柄是前面調(diào)用CreateFile?Mapping或O?p?e?n?F?i?l?e?M?a?p?p?i?n?g(本章后面介紹)函數(shù)返回的。參數(shù)d?w?D?e?s?i?r?e?d?A?c?c?e?s?s用于標(biāo)識如何訪問該數(shù)據(jù)。不錯,必須再次設(shè)定如何訪問文件的數(shù)據(jù)。可以設(shè)定表1?7?-?6所列的4個值中的一個。
? ? 剩下的3個參數(shù)與保留地址空間區(qū)域及將物理存儲器映射到該區(qū)域有關(guān)。當(dāng)你將一個文件映射到你的進(jìn)程的地址空間中時,你不必一次性地映射整個文件。相反,可以只將文件的一小部分映射到地址空間。被映射到進(jìn)程的地址空間的這部分文件稱為一個視圖,這可以說明M?a?p?Vi?e?w?O?f?F?i?l?e是如何而得名的。
? ? 當(dāng)將一個文件視圖映射到進(jìn)程的地址空間中時,必須規(guī)定兩件事情。首先,必須告訴系統(tǒng),數(shù)據(jù)文件中的哪個字節(jié)應(yīng)該作為視圖中的第一個字節(jié)來映射。你可以使用?d?w?F?i?l?e?O?ff?s?e?t?H?i?g?h和d?w?F?i?l?e?O?ff?s?e?t?L?o?w參數(shù)來進(jìn)行這項(xiàng)操作。由于?Wi?n?d?o?w?s支持的文件最大可達(dá)1?6?E?B,因此必須用一個?6?4位的值來設(shè)定這個字節(jié)的位移值。這個?6?4位值中,較高的?3?2位傳遞給參數(shù)d?w?F?i?l?e?O?ff?s?e?t?H?i?g?h,較低的3?2位傳遞給參數(shù)d?w?F?i?l?e?O?ff?s?e?t?L?o?w。注意,文件中的這個位移值必須是系統(tǒng)的分配粒度的倍數(shù)(迄今為止,Wi?n?d?o?w?s的所有實(shí)現(xiàn)代碼的分配粒度均為64?KB)。第1?4章介紹了如何獲取某個系統(tǒng)的分配粒度。
????第二,必須告訴系統(tǒng)?,數(shù)據(jù)文件有多少字節(jié)要映射到地址空間。這與設(shè)定要保留多大的地址空間區(qū)域的情況是相同的。可以使用?d?w?N?u?m?b?e?r?O?f?B?y?t?e?s?To?M?a?p參數(shù)來設(shè)定這個值。如果設(shè)定的值是0,那么系統(tǒng)將設(shè)法把從文件中的指定位移開始到整個文件的結(jié)尾的視圖映射到地址空間。
????如果在調(diào)用M?a?p?Vi?e?w?O?f?F?i?l?e函數(shù)時設(shè)定了F?I?L?E?_?M?A?P?_?C?O?P?Y標(biāo)志,系統(tǒng)就會從系統(tǒng)的頁文件中提交物理存儲器。提交的地址空間數(shù)量由?d?w?N?u?m?b?e?r?O?f?B?y?t?e?s?To?M?a?p參數(shù)決定。只要你不進(jìn)行其他操作,只是從文件的映像視圖中讀取數(shù)據(jù),那么系統(tǒng)將決不會使用頁文件中的這些提交的頁面。但是,如果進(jìn)程中的任何線程將數(shù)據(jù)寫入文件的映像視圖中的任何內(nèi)存地址,那么系統(tǒng)將從頁文件中抓取已提交頁面中的一個頁面,將原始數(shù)據(jù)頁面拷貝到該頁交換文件中,然后將該拷貝的頁面映射到你的進(jìn)程的地址空間。從這時起,你的進(jìn)程中的線程就要訪問數(shù)據(jù)的本地拷貝,不能讀取或修改原始數(shù)據(jù)。
17.3.4?步驟4:從進(jìn)程的地址空間中撤消文件數(shù)據(jù)的映像
? ? 當(dāng)不再需要保留映射到你的進(jìn)程地址空間區(qū)域中的文件數(shù)據(jù)時,可以通過調(diào)用下面的函數(shù)將它釋放:
17.3.5?步驟5和步驟6:關(guān)閉文件映射對象和文件對象
? ? 不用說,你總是要關(guān)閉你打開了的內(nèi)核對象。如果忘記關(guān)閉,在你的進(jìn)程繼續(xù)運(yùn)行時會出現(xiàn)資源泄漏的問題。當(dāng)然,當(dāng)你的進(jìn)程終止運(yùn)行時,系統(tǒng)會自動關(guān)閉你的進(jìn)程已經(jīng)打開但是忘記關(guān)閉的任何對象。但是如果你的進(jìn)程暫時沒有終止運(yùn)行,你將會積累許多資源句柄。因此你始終都應(yīng)該編寫清楚而又“正確的”代碼,以便關(guān)閉你已經(jīng)打開的任何對象。若要關(guān)閉文件映射對象和文件對象,只需要兩次調(diào)用C?l?o?s?e?H?a?n?d?l?e函數(shù),每個句柄調(diào)用一次:
17.8?使用內(nèi)存映射文件在進(jìn)程之間共享數(shù)據(jù)
? ? Wi?n?d?o?w?s總是出色地提供各種機(jī)制,使應(yīng)用程序能夠迅速而方便地共享數(shù)據(jù)和信息。這些機(jī)制包括R?P?C、C?O?M、O?L?E、D?D?E、窗口消息(尤其是?W?M?_?C?O?P?Y?D?ATA)、剪貼板、郵箱、管道和套接字等。在Wi?n?d?o?w?s中,在單個計算機(jī)上共享數(shù)據(jù)的最低層機(jī)制是內(nèi)存映射文件。不錯,如果互相進(jìn)行通信的所有進(jìn)程都在同一臺計算機(jī)上的話,上面提到的所有機(jī)制均使用內(nèi)存映射文件從事它們的煩瑣工作。如果要求達(dá)到較高的性能和較小的開銷,內(nèi)存映射文件是舉手可得的最佳機(jī)制。
? ? 數(shù)據(jù)共享方法是通過讓兩個或多個進(jìn)程映射同一個文件映射對象的視圖來實(shí)現(xiàn)的,這意味著它們將共享物理存儲器的同一個頁面。因此,當(dāng)一個進(jìn)程將數(shù)據(jù)寫入一個共享文件映射對象的視圖時,其他進(jìn)程可以立即看到它們視圖中的數(shù)據(jù)變更情況。注意,如果多個進(jìn)程共享單個文件映射對象,那么所有進(jìn)程必須使用相同的名字來表示該文件映射對象。
? ? 讓我們觀察一個例子,啟動一個應(yīng)用程序。當(dāng)一個應(yīng)用程序啟動時,系統(tǒng)調(diào)用?C?r?e?a?t?e?F?i?l?e函數(shù),打開磁盤上的.?e?x?e文件。然后系統(tǒng)調(diào)用C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù),創(chuàng)建一個文件映射對象。最后,系統(tǒng)代表新創(chuàng)建的進(jìn)程調(diào)用?M?a?p?Vi?e?w?O?f?F?i?l?e?E?x函數(shù)(它帶有?S?E?C?_?I?M?A?G?E標(biāo)志),這樣,?.?e?x?e文件就可以映射到進(jìn)程的地址空間。這里調(diào)用的是?M?a?p?Vi?e?w?O?f?F?i?l?e?E?x,而不是M?a?p?Vi?e?w?O?f?F?i?l?e,這樣,文件的映像將被映射到存放在?.?e?x?e文件映像中的基地址中。系統(tǒng)創(chuàng)建該進(jìn)程的主線程,將該映射視圖的可執(zhí)行代碼的第一個字節(jié)的地址放入線程的指令指針,然后C?P?U啟動該代碼的運(yùn)行。
? ? 如果用戶運(yùn)行同一個應(yīng)用程序的第二個實(shí)例,系統(tǒng)就認(rèn)為規(guī)定的?.?e?x?e文件已經(jīng)存在一個文件映射對象,因此不會創(chuàng)建新的文件對象或者文件映射對象。相反,系統(tǒng)將第二次映射該文件的一個視圖,這次是在新創(chuàng)建的進(jìn)程的地址空間環(huán)境中映射的。系統(tǒng)所做的工作是將相同的文件同時映射到兩個地址空間。顯然,這是對內(nèi)存的更有效的使用,因?yàn)閮蓚€進(jìn)程將共享包含正在執(zhí)行的這部分代碼的物理存儲器的同一個頁面。與所有內(nèi)核對象一樣,可以使用?3種方法與多個進(jìn)程共享對象,這?3種方法是句柄繼承性、句柄命名和句柄復(fù)制。關(guān)于這3種方法的詳細(xì)說明,參見第3章的內(nèi)容。
17.9?頁文件支持的內(nèi)存映射文件
? ? 到現(xiàn)在為止,已經(jīng)介紹了映射駐留在磁盤驅(qū)動器上的文件視圖的方法。許多應(yīng)用程序在運(yùn)行時都要創(chuàng)建一些數(shù)據(jù),并且需要將數(shù)據(jù)傳送給其他進(jìn)程,或者與其他進(jìn)程共享。如果應(yīng)用程序必須在磁盤驅(qū)動器上創(chuàng)建數(shù)據(jù)文件,并且將數(shù)據(jù)存儲在磁盤上以便對它進(jìn)行共享,那么這將是非常不方便的。
M?i?c?r?o?s?o?f?t公司認(rèn)識到了這一點(diǎn),并且增加了一些功能,以便創(chuàng)建由系統(tǒng)的頁文件支持的內(nèi)存映射文件,而不是由專用硬盤文件支持的內(nèi)存映射文件。這個方法與創(chuàng)建內(nèi)存映射磁盤文件所用的方法幾乎相同,不同之處是它更加方便。一方面,它不必調(diào)用?C?r?e?a?t?e?F?i?l?e函數(shù),因?yàn)槟悴皇且獎?chuàng)建或打開一個指定的文件,你只需要像通常那樣調(diào)用?C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù),并且傳遞I?N?VA?L?I?D?_?H?A?N?D?L?E?_?VA?L?U?E作為h?F?i?l?e參數(shù)。這將告訴系統(tǒng),你不是創(chuàng)建其物理存儲器駐留在磁盤上的文件中的文件映射對象,相反,你想讓系統(tǒng)從它的頁文件中提交物理存儲器。分配的存儲器的數(shù)量由C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù)的d?w?M?a?x?i?m?u?m?S?i?z?e?H?i?g?h和d?w?M?a?x?i?m?u?m?S?i?z?e?L?o?w兩個參數(shù)來決定。
? ? 當(dāng)創(chuàng)建了文件映射對象并且將它的一個視圖映射到進(jìn)程的地址空間之后,就可以像使用任何內(nèi)存區(qū)域那樣使用它。如果你想要與其他進(jìn)程共享該數(shù)據(jù),可調(diào)用?C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g函數(shù),并傳遞一個以0結(jié)尾的字符串作為p?s?z?N?a?m?e參數(shù)。然后,想要訪問該存儲器的其他進(jìn)程就可以調(diào)用C?r?e?a?t?e?F?i?l?e?M?a?p?p?i?n?g或O?p?e?n?F?i?l?e?M?a?p?p?i?n?g函數(shù),并傳遞相同的名字。
? ? 當(dāng)進(jìn)程不再想要訪問文件映射對象時,該進(jìn)程應(yīng)該調(diào)用?C?l?o?s?e?H?a?n?d?l?e函數(shù)。當(dāng)所有句柄均被關(guān)閉后,系統(tǒng)將從系統(tǒng)的頁文件中收回已經(jīng)提交的存儲器。
總結(jié)
以上是生活随笔為你收集整理的Windows核心编程 第十七章 -内存映射文件(下)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: WindowsPE 第五章 导出表编程-
- 下一篇: PowerShell-4.API调用以及