• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            C++ Programmer's Cookbook

            {C++ 基礎(chǔ)} {C++ 高級} {C#界面,C++核心算法} {設(shè)計模式} {C#基礎(chǔ)}

            windows核心編程--內(nèi)存映射文件

            與虛擬內(nèi)存一樣,內(nèi)存映射文件可以用來保留一個地址空間的區(qū)域,并將物理存儲器提交給該區(qū)域。它們之間的差別是,物理存儲器來自一個已經(jīng)位于磁盤上的文件,而不是系統(tǒng)的頁文件。一旦該文件被映射,就可以訪問它,就像整個文件已經(jīng)加載內(nèi)存一樣。

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

            ? 系統(tǒng)使用內(nèi)存映射文件,以便加載和執(zhí)行. e x e和D L L文件。這可以大大節(jié)省頁文件空間和應(yīng)用程序啟動運(yùn)行所需的時間。

            ? 可以使用內(nèi)存映射文件來訪問磁盤上的數(shù)據(jù)文件。這使你可以不必對文件執(zhí)行I / O操作,并且可以不必對文件內(nèi)容進(jìn)行緩存。

            ? 可以使用內(nèi)存映射文件,使同一臺計算機(jī)上運(yùn)行的多個進(jìn)程能夠相互之間共享數(shù)據(jù)。Wi n d o w s確實(shí)提供了其他一些方法,以便在進(jìn)程之間進(jìn)行數(shù)據(jù)通信,但是這些方法都是使用內(nèi)存映射文件來實(shí)現(xiàn)的,這使得內(nèi)存映射文件成為單個計算機(jī)上的多個進(jìn)程互相進(jìn)行通信的最有效的方法。

            內(nèi)存映射的可執(zhí)行文件和DLL文件

            當(dāng)線程調(diào)用C r e a t e P r o c e s s時,系統(tǒng)將執(zhí)行下列操作步驟:

            1) 系統(tǒng)找出在調(diào)用C r e a t e P r o c e s s時設(shè)定的. e x e文件。如果找不到這個. e x e文件,進(jìn)程將無法創(chuàng)建,C r e a t e P r o c e s s將返回FA L S E。

            2) 系統(tǒng)創(chuàng)建一個新進(jìn)程內(nèi)核對象。

            3) 系統(tǒng)為這個新進(jìn)程創(chuàng)建一個私有地址空間。

            4) 系統(tǒng)保留一個足夠大的地址空間區(qū)域,用于存放該. e x e文件。該區(qū)域需要的位置在. e x e文件本身中設(shè)定。按照默認(rèn)設(shè)置, . e x e文件的基地址是0 x 0 0 4 0 0 0 0 0(這個地址可能不同于在6 4位Windows 2000上運(yùn)行的6 4位應(yīng)用程序的地址),但是,可以在創(chuàng)建應(yīng)用程序的. e x e文件時重載這個地址,方法是在鏈接應(yīng)用程序時使用鏈接程序的/ B A S E選項。

            5) 系統(tǒng)注意到支持已保留區(qū)域的物理存儲器是在磁盤上的. e x e文件中,而不是在系統(tǒng)的頁文件中。

            當(dāng). e x e文件被映射到進(jìn)程的地址空間中之后,系統(tǒng)將訪問. e x e文件的一個部分,該部分列出了包含. e x e文件中的代碼要調(diào)用的函數(shù)的D L L文件。然后,系統(tǒng)為每個D L L文件調(diào)用L o a d L i b r a r y函數(shù),如果任何一個D L L需要更多的D L L,那么系統(tǒng)將調(diào)用L o a d L i b r a r y函數(shù),以便加載這些D L L。每當(dāng)調(diào)用L o a d L i b r a r y來加載一個D L L時,系統(tǒng)將執(zhí)行下列操作步驟,它們均類似上面的第4和第5個步驟:

            1) 系統(tǒng)保留一個足夠大的地址空間區(qū)域,用于存放該D L L文件。該區(qū)域需要的位置在D L L文件本身中設(shè)定。按照默認(rèn)設(shè)置, M i c r o s o f t的Visual C++ 建立的D L L文件基地址是0 x 1 0 0 0 0 0 0 0(這個地址可能不同于在6 4位Windows 2000上運(yùn)行的6 4位D L L的地址)但是,你可以在創(chuàng)建D L L文件時重載這個地址,方法是使用鏈接程序的/ B A S E選項。Wi n d o w s提供的所有標(biāo)準(zhǔn)系統(tǒng)D L L都擁有不同的基地址,這樣,如果加載到單個地址空間,它們就不會重疊。

            2) 如果系統(tǒng)無法在該D L L的首選基地址上保留一個區(qū)域,其原因可能是該區(qū)域已經(jīng)被另一個D L L或. e x e占用,也可能是因為該區(qū)域不夠大,此時系統(tǒng)將設(shè)法尋找另一個地址空間的區(qū)域來保留該D L L。

            3) 系統(tǒng)會注意到支持已保留區(qū)域的物理存儲器位于磁盤上的D L L文件中,而不是在系統(tǒng)的頁文件中。

            如果由于某個原因系統(tǒng)無法映射. e x e和所有必要的D L L文件,那么系統(tǒng)就會向用戶顯示一個消息框,并且釋放進(jìn)程的地址空間和進(jìn)程對象。
            當(dāng)所有的. e x e和D L L文件都被映射到進(jìn)程的地址空間之后,系統(tǒng)就可以開始執(zhí)行. e x e文件的啟動代碼。當(dāng). e x e文件被映射后,系統(tǒng)將負(fù)責(zé)所有的分頁、緩沖和高速緩存的處理。
            在可執(zhí)行文件或DLL的多個實(shí)例之間共享靜態(tài)數(shù)據(jù) (通過定義共享的節(jié))

            全局?jǐn)?shù)據(jù)和靜態(tài)數(shù)據(jù)不能被同一個. e x e或D L L文件的多個映像共享,這是個安全的默認(rèn)設(shè)置。但是,在某些情況下,讓一個. e x e文件的多個映像共享一個變量的實(shí)例是非常有用和方便的。例如,Wi n d o w s沒有提供任何簡便的方法來確定用戶是否在運(yùn)行應(yīng)用程序的多個實(shí)例。但是,如果能夠讓所有實(shí)例共享單個全局變量,那么這個全局變量就能夠反映正在運(yùn)行的實(shí)例的數(shù)量。
            ?內(nèi)存映射數(shù)據(jù)文件

            操作系統(tǒng)使得內(nèi)存能夠?qū)⒁粋€數(shù)據(jù)文件映射到進(jìn)程的地址空間中。因此,對大量的數(shù)據(jù)進(jìn)行操作是非常方便的。

            為了理解用這種方法來使用內(nèi)存映射文件的功能,讓我們看一看如何用4種方法來實(shí)現(xiàn)一個程序,以便將文件中的所有字節(jié)的順序進(jìn)行倒序。

            方法1:一個文件,一個緩存

            第一種方法也是理論上最簡單的方法,它需要分配足夠大的內(nèi)存塊來存放整個文件。該文件被打開,它的內(nèi)容被讀入內(nèi)存塊,然后該文件被關(guān)閉。文件內(nèi)容進(jìn)入內(nèi)存后,我們就可以對所有字節(jié)的順序進(jìn)行倒序,方法是將第一個字節(jié)倒騰為最后一個字節(jié),第二個字節(jié)倒騰為倒數(shù)第二個字節(jié),依次類推。這個倒騰操作將一直進(jìn)行下去直到文件的中間位置。當(dāng)所有的字節(jié)都已經(jīng)倒騰之后,就可以重新打開該文件,并用內(nèi)存塊的內(nèi)容來改寫它的內(nèi)容。

            這種方法實(shí)現(xiàn)起來非常容易,但是它有兩個缺點(diǎn)。首先,必須分配一個與文件大小相同的內(nèi)存塊。如果文件比較小,那么這沒有什么問題。但是如果文件非常大,比如說有2 G B大,那該怎么辦呢?一個3 2位的系統(tǒng)不允許應(yīng)用程序提交那么大的物理內(nèi)存塊。因此大文件需要使用不同的方法。

            第二,如果進(jìn)程在運(yùn)行過程的中間被中斷,也就是說當(dāng)?shù)剐蚝蟮淖止?jié)被重新寫入該文件時進(jìn)程被中斷,那么文件的內(nèi)容就會遭到破壞。防止出現(xiàn)這種情況的最簡單的方法是在對它的內(nèi)容進(jìn)行倒序之前先制作一個原始文件的拷貝。如果整個進(jìn)程運(yùn)行成功,那么可以刪除該文件的拷貝。這種方法需要更多的磁盤空間。

            ?方法2:兩個文件,一個緩存

            在第二種方法中,你打開現(xiàn)有的文件,并且在磁盤上創(chuàng)建一個長度為0的新文件。然后分配一個比較小的內(nèi)部緩存,比如說8 KB。你找到離原始文件結(jié)尾還有8 KB的位置,將這最后的8 KB讀入緩存,將字節(jié)倒序,再將緩存中的內(nèi)容寫入新創(chuàng)建的文件。這個尋找、讀入、倒序和寫入的操作過程要反復(fù)進(jìn)行,直到到達(dá)原始文件的開頭。如果文件的長度不是8 KB的倍數(shù),那么必須進(jìn)行某些特殊的處理。當(dāng)原始文件完全處理完畢之后,將原始文件和新文件關(guān)閉,并刪除原始文件。

            這種方法實(shí)現(xiàn)起來比第一種方法要復(fù)雜一些。它對內(nèi)存的使用效率要高得多,因為它只需要分配一個8 KB的緩存塊,但是它存在兩個大問題。首先,它的處理速度比第一種方法要慢,原因是在每個循環(huán)操作過程中,在執(zhí)行讀入操作之前,必須對原始文件進(jìn)行尋找操作。第二,這種方法可能要使用大量的硬盤空間。如果原始文件是400 MB,那么隨著進(jìn)程的不斷運(yùn)行,新文件就會增大為400 MB。在原始文件被刪除之前,兩個文件總共需要占用800 MB的磁盤空間。這比應(yīng)該需要的空間大400 MB。由于存在這個缺點(diǎn),因此引來了下一個方法。

            ?方法3:一個文件,兩個緩存

            如果使用這個方法,那么我們假設(shè)程序初始化時分配了兩個獨(dú)立的8 KB緩存。程序?qū)⑽募牡谝粋€8 KB讀入一個緩存,再將文件的第二個8 KB 讀入另一個緩存。然后進(jìn)程將兩個緩存的內(nèi)容進(jìn)行倒序,并將第一個緩存的內(nèi)容寫回文件的結(jié)尾處,將第二個緩存的內(nèi)容寫回同一個文件的開始處。每個迭代操作不斷進(jìn)行(以8 KB為單位,從文件的開始和結(jié)尾處移動文件塊)。如果文件的長度不是16 KB的倍數(shù),并且有兩個8 KB的文件塊相重疊,那么就需要進(jìn)行一些特殊的處理。這種特殊處理比上一種方法中的特殊處理更加復(fù)雜,不過這難不倒經(jīng)驗豐富的編程員。

            與前面的兩種方法相比,這種方法在節(jié)省硬盤空間方面有它的優(yōu)點(diǎn)。由于所有內(nèi)容都是從同一個文件讀取并寫入同一個文件,因此不需要增加額外的磁盤空間,至于內(nèi)存的使用,這種方法也不錯,它只需要使用16 KB的內(nèi)存。當(dāng)然,這種方法也許是最難實(shí)現(xiàn)的方法。與第一種方法一樣,如果進(jìn)程被中斷,本方法會導(dǎo)致數(shù)據(jù)文件被破壞。

            下面讓我們來看一看如何使用內(nèi)存映射文件來完成這個過程。

            方法4:一個文件,零緩存

            當(dāng)使用內(nèi)存映射文件對文件內(nèi)容進(jìn)行倒序時,你打開該文件,然后告訴系統(tǒng)將虛擬地址空間的一個區(qū)域進(jìn)行倒序。你告訴系統(tǒng)將文件的第一個字節(jié)映射到該保留區(qū)域的第一個字節(jié)。然后可以訪問該虛擬內(nèi)存的區(qū)域,就像它包含了這個文件一樣。實(shí)際上,如果在文件的結(jié)尾處有一個單個0字節(jié),那么只需要調(diào)用C運(yùn)行期函數(shù)_ s t r r e v,就可以對文件中的數(shù)據(jù)進(jìn)行倒序操作。

            這種方法的最大優(yōu)點(diǎn)是,系統(tǒng)能夠為你管理所有的文件緩存操作。不必分配任何內(nèi)存,或者將文件數(shù)據(jù)加載到內(nèi)存,也不必將數(shù)據(jù)重新寫入該文件,或者釋放任何內(nèi)存塊。但是,內(nèi)存映射文件仍然可能出現(xiàn)因為電源故障之類的進(jìn)程中斷而造成數(shù)據(jù)被破壞的問題。


            ?使用內(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)核對象。

            步驟1:創(chuàng)建或打開文件內(nèi)核對象

            若要創(chuàng)建或打開一個文件內(nèi)核對象,總是要調(diào)用C r e a t e F i l e函數(shù):

            HANDLE CreateFile(
               PCSTR pszFileName,
               DWORD dwDesiredAccess,
               DWORD dwShareMode,
               PSECURITY_ATTRIBUTES psa,
               DWORD dwCreationDisposition,
               DWORD dwFlagsAndAttributes,
               HANDLE hTemplateFile);

            步驟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)行這項操作,可以調(diào)用C r e a t e F i l e M a p p i n g函數(shù):

            HANDLE CreateFileMapping(
               HANDLE hFile,
               PSECURITY_ATTRIBUTES psa,
               DWORD fdwProtect,
               DWORD dwMaximumSizeHigh,
               DWORD dwMaximumSizeLow,
               PCTSTR pszName);

            步驟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)行這項操作:

            PVOID MapViewOfFile(
               HANDLE hFileMappingObject,
               DWORD dwDesiredAccess,
               DWORD dwFileOffsetHigh,
               DWORD dwFileOffsetLow,
               SIZE_T dwNumberOfBytesToMap);

            步驟4:從進(jìn)程的地址空間中撤消文件數(shù)據(jù)的映像

            當(dāng)不再需要保留映射到你的進(jìn)程地址空間區(qū)域中的文件數(shù)據(jù)時,可以通過調(diào)用下面的函數(shù)將它釋放:

            BOOL UnmapViewOfFile(PVOID pvBaseAddress);

            為了提高速度,系統(tǒng)將文件的數(shù)據(jù)頁面進(jìn)行高速緩存,并且在對文件的映射視圖進(jìn)行操作時不立即更新文件的磁盤映像。如果需要確保你的更新被寫入磁盤,可以強(qiáng)制系統(tǒng)將修改過的數(shù)據(jù)的一部分或全部重新寫入磁盤映像中,方法是調(diào)用F l u s h Vi e w O f F i l e函數(shù):

            BOOL FlushViewOfFile(
               PVOID pvAddress,
               SIZE_T dwNumberOfBytesToFlush);

            步驟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)用一次:

            讓我們更加仔細(xì)地觀察一下這個進(jìn)程。下面的偽代碼顯示了一個內(nèi)存映射文件的例子:

            HANDLE hFile = CreateFile(...);
            HANDLE hFileMapping = CreateFileMapping(hFile, ...);
            PVOID pvFile = MapViewOfFile(hFileMapping, ...);
            
            // Use the memory-mapped file.
            
            UnmapViewOfFile(pvFile);
            CloseHandle(hFileMapping);
            CloseHandle(hFile);

            上面的代碼顯示了對內(nèi)存映射文件進(jìn)行操作所用的“預(yù)期”方法。但是,它沒有顯示,當(dāng)你調(diào)用M a p Vi e w O f F i l e時系統(tǒng)對文件對象和文件映射對象的使用計數(shù)的遞增情況。這個副作用是很大的,因為它意味著我們可以將上面的代碼段重新編寫成下面的樣子:

            HANDLE hFile = CreateFile(...);
            HANDLE hFileMapping = CreateFileMapping(hFile, ...);
            CloseHandle(hFile);
            PVOID pvFile = MapViewOfFile(hFileMapping, ...);
            CloseHandle(hFileMapping);
            
            // Use the memory-mapped file.
            
            UnmapViewOfFile(pvFile);

            當(dāng)對內(nèi)存映射文件進(jìn)行操作時,通常要打開文件,創(chuàng)建文件映射對象,然后使用文件映射對象將文件的數(shù)據(jù)視圖映射到進(jìn)程的地址空間。由于系統(tǒng)遞增了文件對象和文件映射對象的內(nèi)部使用計數(shù),因此可以在你的代碼開始運(yùn)行時關(guān)閉這些對象,以消除資源泄漏的可能性。

            如果用同一個文件來創(chuàng)建更多的文件映射對象,或者映射同一個文件映射對象的多個視圖,那么就不能較早地調(diào)用C l o s e H a n d l e函數(shù)——以后你可能還需要使用它們的句柄,以便分別對C r e a t e F i l e M a p p i n g和M a p Vi e w O f F i l e函數(shù)進(jìn)行更多的調(diào)用。

            使用內(nèi)存映射文件來處理大文件
            使用內(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)存的更有效的使用,因為兩個進(jìn)程將共享包含正在執(zhí)行的這部分代碼的物理存儲器的同一個頁面。

            與所有內(nèi)核對象一樣,可以使用3種方法與多個進(jìn)程共享對象,這3種方法是句柄繼承性、句柄命名和句柄復(fù)制。
            ?內(nèi)存映射文件與數(shù)據(jù)視圖的相關(guān)性

            附錄:

            系統(tǒng)允許你映射一個文件的相同數(shù)據(jù)的多個視圖。例如,你可以將文件開頭的10 KB映射到一個視圖,然后將同一個文件的頭4 KB映射到另一個視圖。只要你是映射相同的文件映射對象,系統(tǒng)就會確保映射的視圖數(shù)據(jù)的相關(guān)性。例如,如果你的應(yīng)用程序改變了一個視圖中的文件內(nèi)容,那么所有其他視圖均被更新以反映這個變化。這是因為盡管頁面多次被映射到進(jìn)程的虛擬地址空間,但是系統(tǒng)只將數(shù)據(jù)放在單個R A M頁面上。如果多個進(jìn)程映射單個數(shù)據(jù)文件的視圖,那么數(shù)據(jù)仍然是相關(guān)的,因為在數(shù)據(jù)文件中,每個R A M頁面只有一個實(shí)例——正是這個R A M頁面被映射到多個進(jìn)程的地址空間。

            注意Wi n d o w s允許創(chuàng)建若干個由單個數(shù)據(jù)文件支持的文件映射對象。Wi n d o w s不能保證這些不同的文件映射對象的視圖具有相關(guān)性。它只能保證單個文件映射對象的多個視圖具有相關(guān)性。

            然而,當(dāng)對文件進(jìn)行操作時,沒有理由使另一個應(yīng)用程序無法調(diào)用C r e a t e F i l e函數(shù)以打開由另一個進(jìn)程映射的同一個文件。這個新進(jìn)程可以使用R e a d F i l e和Wr i t e F i l e函數(shù)來讀取該文件的數(shù)據(jù)和將數(shù)據(jù)寫入該文件。當(dāng)然,每當(dāng)一個進(jìn)程調(diào)用這些函數(shù)時,它必須從內(nèi)存緩沖區(qū)讀取文件數(shù)據(jù)或者將文件數(shù)據(jù)寫入內(nèi)存緩沖區(qū)。該內(nèi)存緩沖區(qū)必須是進(jìn)程自己創(chuàng)建的一個緩沖區(qū),而不是映射文件使用的內(nèi)存緩沖區(qū)。當(dāng)兩個應(yīng)用程序打開同一個文件時,問題就可能產(chǎn)生:一個進(jìn)程可以調(diào)用R e a d F i l e函數(shù)來讀取文件的一個部分,并修改它的數(shù)據(jù),然后使用Wr i t e F i l e函數(shù)將數(shù)據(jù)重新寫入文件,而第二個進(jìn)程的文件映射對象卻不知道第一個進(jìn)程執(zhí)行的這些操作。由于這個原因,當(dāng)你為將被內(nèi)存映射的文件調(diào)用C r e a t e F i l e函數(shù)時,最好將d w S h a r e M o d e參數(shù)的值設(shè)置為0。這樣就可以告訴系統(tǒng),你想要單獨(dú)訪問這個文件,而其他進(jìn)程都不能打開它。

            只讀文件不存在相關(guān)性問題,因此它們可以作為很好的內(nèi)存映射文件。內(nèi)存映射文件決不應(yīng)該用于共享網(wǎng)絡(luò)上的可寫入文件,因為系統(tǒng)無法保證數(shù)據(jù)視圖的相關(guān)性。如果某個人的計算機(jī)更新了文件的內(nèi)容,其他內(nèi)存中含有原始數(shù)據(jù)的計算機(jī)將不知道它的信息已經(jīng)被修改。


            posted on 2006-09-21 13:26 夢在天涯 閱讀(6358) 評論(1)  編輯 收藏 引用 所屬分類: Windows API

            評論

            # re: windows核心編程--內(nèi)存映射文件 2006-10-07 20:15 cpp

            C++語言、學(xué)習(xí)、研究交流
            -------------------------
            論壇 : http://www.16c.cn  回復(fù)  更多評論   

            公告

            EMail:itech001#126.com

            導(dǎo)航

            統(tǒng)計

            • 隨筆 - 461
            • 文章 - 4
            • 評論 - 746
            • 引用 - 0

            常用鏈接

            隨筆分類

            隨筆檔案

            收藏夾

            Blogs

            c#(csharp)

            C++(cpp)

            Enlish

            Forums(bbs)

            My self

            Often go

            Useful Webs

            Xml/Uml/html

            搜索

            •  

            積分與排名

            • 積分 - 1811117
            • 排名 - 5

            最新評論

            閱讀排行榜

            久久久无码精品亚洲日韩京东传媒| 狠狠色丁香久久婷婷综合| 久久精品一本到99热免费| 亚洲va国产va天堂va久久| 狠色狠色狠狠色综合久久| 精品多毛少妇人妻AV免费久久| 一级做a爰片久久毛片免费陪| 国产精品99久久久精品无码| 久久综合九色综合97_久久久| 青青热久久国产久精品| 久久久久99精品成人片试看| 婷婷久久综合九色综合98| 超级碰碰碰碰97久久久久| 99久久精品国产高清一区二区| 久久91精品综合国产首页| 成人妇女免费播放久久久| 欧美日韩精品久久久久 | 久久综合九色欧美综合狠狠 | 亚洲狠狠综合久久| 久久精品国产2020| 人妻丰满?V无码久久不卡| 精品午夜久久福利大片| 日韩久久久久久中文人妻| 怡红院日本一道日本久久 | 狠狠色婷婷久久一区二区三区 | 久久免费的精品国产V∧| 久久成人国产精品一区二区| 国产V亚洲V天堂无码久久久| 2021国产精品久久精品| 欧美激情精品久久久久久久九九九 | 久久精品国产亚洲av麻豆蜜芽| 久久人人爽人人爽AV片| 国产精品热久久毛片| 久久精品国产只有精品2020| 久久久久人妻一区二区三区vr| 97久久国产综合精品女不卡| 欧美精品福利视频一区二区三区久久久精品 | 欧美与黑人午夜性猛交久久久 | 久久久久国产亚洲AV麻豆| 91秦先生久久久久久久| 久久综合综合久久狠狠狠97色88|