如果由于某個(gè)原因系統(tǒng)無(wú)法映射. e x e和所有必要的D L L文件,那么系統(tǒng)就會(huì)向用戶顯示一個(gè)消息框,并且釋放進(jìn)程的地址空間和進(jìn)程對(duì)象。
當(dāng)所有的. e x e和D L L文件都被映射到進(jìn)程的地址空間之后,系統(tǒng)就可以開(kāi)始執(zhí)行. e x e文件的啟動(dòng)代碼。當(dāng). e x e文件被映射后,系統(tǒng)將負(fù)責(zé)所有的分頁(yè)、緩沖和高速緩存的處理。
在可執(zhí)行文件或DLL的多個(gè)實(shí)例之間共享靜態(tài)數(shù)據(jù) (通過(guò)定義共享的節(jié))
全局?jǐn)?shù)據(jù)和靜態(tài)數(shù)據(jù)不能被同一個(gè). e x e或D L L文件的多個(gè)映像共享,這是個(gè)安全的默認(rèn)設(shè)置。但是,在某些情況下,讓一個(gè). e x e文件的多個(gè)映像共享一個(gè)變量的實(shí)例是非常有用和方便的。例如,Wi n d o w s沒(méi)有提供任何簡(jiǎn)便的方法來(lái)確定用戶是否在運(yùn)行應(yīng)用程序的多個(gè)實(shí)例。但是,如果能夠讓所有實(shí)例共享單個(gè)全局變量,那么這個(gè)全局變量就能夠反映正在運(yùn)行的實(shí)例的數(shù)量。
?內(nèi)存映射數(shù)據(jù)文件
操作系統(tǒng)使得內(nèi)存能夠?qū)⒁粋€(gè)數(shù)據(jù)文件映射到進(jìn)程的地址空間中。因此,對(duì)大量的數(shù)據(jù)進(jìn)行操作是非常方便的。
為了理解用這種方法來(lái)使用內(nèi)存映射文件的功能,讓我們看一看如何用4種方法來(lái)實(shí)現(xiàn)一個(gè)程序,以便將文件中的所有字節(jié)的順序進(jìn)行倒序。
方法1:一個(gè)文件,一個(gè)緩存
第一種方法也是理論上最簡(jiǎn)單的方法,它需要分配足夠大的內(nèi)存塊來(lái)存放整個(gè)文件。該文件被打開(kāi),它的內(nèi)容被讀入內(nèi)存塊,然后該文件被關(guān)閉。文件內(nèi)容進(jìn)入內(nèi)存后,我們就可以對(duì)所有字節(jié)的順序進(jìn)行倒序,方法是將第一個(gè)字節(jié)倒騰為最后一個(gè)字節(jié),第二個(gè)字節(jié)倒騰為倒數(shù)第二個(gè)字節(jié),依次類推。這個(gè)倒騰操作將一直進(jìn)行下去直到文件的中間位置。當(dāng)所有的字節(jié)都已經(jīng)倒騰之后,就可以重新打開(kāi)該文件,并用內(nèi)存塊的內(nèi)容來(lái)改寫(xiě)它的內(nèi)容。
這種方法實(shí)現(xiàn)起來(lái)非常容易,但是它有兩個(gè)缺點(diǎn)。首先,必須分配一個(gè)與文件大小相同的內(nèi)存塊。如果文件比較小,那么這沒(méi)有什么問(wèn)題。但是如果文件非常大,比如說(shuō)有2 G B大,那該怎么辦呢?一個(gè)3 2位的系統(tǒng)不允許應(yīng)用程序提交那么大的物理內(nèi)存塊。因此大文件需要使用不同的方法。
第二,如果進(jìn)程在運(yùn)行過(guò)程的中間被中斷,也就是說(shuō)當(dāng)?shù)剐蚝蟮淖止?jié)被重新寫(xiě)入該文件時(shí)進(jìn)程被中斷,那么文件的內(nèi)容就會(huì)遭到破壞。防止出現(xiàn)這種情況的最簡(jiǎn)單的方法是在對(duì)它的內(nèi)容進(jìn)行倒序之前先制作一個(gè)原始文件的拷貝。如果整個(gè)進(jìn)程運(yùn)行成功,那么可以刪除該文件的拷貝。這種方法需要更多的磁盤空間。
?方法2:兩個(gè)文件,一個(gè)緩存
在第二種方法中,你打開(kāi)現(xiàn)有的文件,并且在磁盤上創(chuàng)建一個(gè)長(zhǎng)度為0的新文件。然后分配一個(gè)比較小的內(nèi)部緩存,比如說(shuō)8 KB。你找到離原始文件結(jié)尾還有8 KB的位置,將這最后的8 KB讀入緩存,將字節(jié)倒序,再將緩存中的內(nèi)容寫(xiě)入新創(chuàng)建的文件。這個(gè)尋找、讀入、倒序和寫(xiě)入的操作過(guò)程要反復(fù)進(jìn)行,直到到達(dá)原始文件的開(kāi)頭。如果文件的長(zhǎng)度不是8 KB的倍數(shù),那么必須進(jìn)行某些特殊的處理。當(dāng)原始文件完全處理完畢之后,將原始文件和新文件關(guān)閉,并刪除原始文件。
這種方法實(shí)現(xiàn)起來(lái)比第一種方法要復(fù)雜一些。它對(duì)內(nèi)存的使用效率要高得多,因?yàn)樗恍枰峙湟粋€(gè)8 KB的緩存塊,但是它存在兩個(gè)大問(wèn)題。首先,它的處理速度比第一種方法要慢,原因是在每個(gè)循環(huán)操作過(guò)程中,在執(zhí)行讀入操作之前,必須對(duì)原始文件進(jìn)行尋找操作。第二,這種方法可能要使用大量的硬盤空間。如果原始文件是400 MB,那么隨著進(jìn)程的不斷運(yùn)行,新文件就會(huì)增大為400 MB。在原始文件被刪除之前,兩個(gè)文件總共需要占用800 MB的磁盤空間。這比應(yīng)該需要的空間大400 MB。由于存在這個(gè)缺點(diǎn),因此引來(lái)了下一個(gè)方法。
?方法3:一個(gè)文件,兩個(gè)緩存
如果使用這個(gè)方法,那么我們假設(shè)程序初始化時(shí)分配了兩個(gè)獨(dú)立的8 KB緩存。程序?qū)⑽募牡谝粋€(gè)8 KB讀入一個(gè)緩存,再將文件的第二個(gè)8 KB 讀入另一個(gè)緩存。然后進(jìn)程將兩個(gè)緩存的內(nèi)容進(jìn)行倒序,并將第一個(gè)緩存的內(nèi)容寫(xiě)回文件的結(jié)尾處,將第二個(gè)緩存的內(nèi)容寫(xiě)回同一個(gè)文件的開(kāi)始處。每個(gè)迭代操作不斷進(jìn)行(以8 KB為單位,從文件的開(kāi)始和結(jié)尾處移動(dòng)文件塊)。如果文件的長(zhǎng)度不是16 KB的倍數(shù),并且有兩個(gè)8 KB的文件塊相重疊,那么就需要進(jìn)行一些特殊的處理。這種特殊處理比上一種方法中的特殊處理更加復(fù)雜,不過(guò)這難不倒經(jīng)驗(yàn)豐富的編程員。
與前面的兩種方法相比,這種方法在節(jié)省硬盤空間方面有它的優(yōu)點(diǎn)。由于所有內(nèi)容都是從同一個(gè)文件讀取并寫(xiě)入同一個(gè)文件,因此不需要增加額外的磁盤空間,至于內(nèi)存的使用,這種方法也不錯(cuò),它只需要使用16 KB的內(nèi)存。當(dāng)然,這種方法也許是最難實(shí)現(xiàn)的方法。與第一種方法一樣,如果進(jìn)程被中斷,本方法會(huì)導(dǎo)致數(shù)據(jù)文件被破壞。
下面讓我們來(lái)看一看如何使用內(nèi)存映射文件來(lái)完成這個(gè)過(guò)程。
方法4:一個(gè)文件,零緩存
當(dāng)使用內(nèi)存映射文件對(duì)文件內(nèi)容進(jìn)行倒序時(shí),你打開(kāi)該文件,然后告訴系統(tǒng)將虛擬地址空間的一個(gè)區(qū)域進(jìn)行倒序。你告訴系統(tǒng)將文件的第一個(gè)字節(jié)映射到該保留區(qū)域的第一個(gè)字節(jié)。然后可以訪問(wèn)該虛擬內(nèi)存的區(qū)域,就像它包含了這個(gè)文件一樣。實(shí)際上,如果在文件的結(jié)尾處有一個(gè)單個(gè)0字節(jié),那么只需要調(diào)用C運(yùn)行期函數(shù)_ s t r r e v,就可以對(duì)文件中的數(shù)據(jù)進(jìn)行倒序操作。
這種方法的最大優(yōu)點(diǎn)是,系統(tǒng)能夠?yàn)槟愎芾硭械奈募彺娌僮?。不必分配任何?nèi)存,或者將文件數(shù)據(jù)加載到內(nèi)存,也不必將數(shù)據(jù)重新寫(xiě)入該文件,或者釋放任何內(nèi)存塊。但是,內(nèi)存映射文件仍然可能出現(xiàn)因?yàn)殡娫垂收现惖倪M(jìn)程中斷而造成數(shù)據(jù)被破壞的問(wèn)題。
?使用內(nèi)存映射文件
若要使用內(nèi)存映射文件,必須執(zhí)行下列操作步驟:
1) 創(chuàng)建或打開(kāi)一個(gè)文件內(nèi)核對(duì)象,該對(duì)象用于標(biāo)識(shí)磁盤上你想用作內(nèi)存映射文件的文件。
2) 創(chuàng)建一個(gè)文件映射內(nèi)核對(duì)象,告訴系統(tǒng)該文件的大小和你打算如何訪問(wèn)該文件。
3) 讓系統(tǒng)將文件映射對(duì)象的全部或一部分映射到你的進(jìn)程地址空間中。
當(dāng)完成對(duì)內(nèi)存映射文件的使用時(shí),必須執(zhí)行下面這些步驟將它清除:
1) 告訴系統(tǒng)從你的進(jìn)程的地址空間中撤消文件映射內(nèi)核對(duì)象的映像。
2) 關(guān)閉文件映射內(nèi)核對(duì)象。
3) 關(guān)閉文件內(nèi)核對(duì)象。
步驟1:創(chuàng)建或打開(kāi)文件內(nèi)核對(duì)象
若要?jiǎng)?chuàng)建或打開(kāi)一個(gè)文件內(nèi)核對(duì)象,總是要調(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)建一個(gè)文件映射內(nèi)核對(duì)象
調(diào)用C r e a t e F i l e函數(shù),就可以將文件映像的物理存儲(chǔ)器的位置告訴操作系統(tǒng)。你傳遞的路徑名用于指明支持文件映像的物理存儲(chǔ)器在磁盤(或網(wǎng)絡(luò)或光盤)上的確切位置。這時(shí),必須告訴系統(tǒng),文件映射對(duì)象需要多少物理存儲(chǔ)器。若要進(jìn)行這項(xiàng)操作,可以調(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)建了一個(gè)文件映射對(duì)象后,仍然必須讓系統(tǒng)為文件的數(shù)據(jù)保留一個(gè)地址空間區(qū)域,并將文件的數(shù)據(jù)作為映射到該區(qū)域的物理存儲(chǔ)器進(jìn)行提交??梢酝ㄟ^(guò)調(diào)用M a p Vi e w O f F i l e函數(shù)來(lái)進(jìn)行這項(xiàng)操作:
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ù)時(shí),可以通過(guò)調(diào)用下面的函數(shù)將它釋放:
BOOL UnmapViewOfFile(PVOID pvBaseAddress);
為了提高速度,系統(tǒng)將文件的數(shù)據(jù)頁(yè)面進(jìn)行高速緩存,并且在對(duì)文件的映射視圖進(jìn)行操作時(shí)不立即更新文件的磁盤映像。如果需要確保你的更新被寫(xiě)入磁盤,可以強(qiáng)制系統(tǒng)將修改過(guò)的數(shù)據(jù)的一部分或全部重新寫(xiě)入磁盤映像中,方法是調(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)閉文件映射對(duì)象和文件對(duì)象
不用說(shuō),你總是要關(guān)閉你打開(kāi)了的內(nèi)核對(duì)象。如果忘記關(guān)閉,在你的進(jìn)程繼續(xù)運(yùn)行時(shí)會(huì)出現(xiàn)資源泄漏的問(wèn)題。當(dāng)然,當(dāng)你的進(jìn)程終止運(yùn)行時(shí),系統(tǒng)會(huì)自動(dòng)關(guān)閉你的進(jìn)程已經(jīng)打開(kāi)但是忘記關(guān)閉的任何對(duì)象。但是如果你的進(jìn)程暫時(shí)沒(méi)有終止運(yùn)行,你將會(huì)積累許多資源句柄。因此你始終都應(yīng)該編寫(xiě)清楚而又“正確的”代碼,以便關(guān)閉你已經(jīng)打開(kāi)的任何對(duì)象。若要關(guān)閉文件映射對(duì)象和文件對(duì)象,只需要兩次調(diào)用C l o s e H a n d l e函數(shù),每個(gè)句柄調(diào)用一次:
讓我們更加仔細(xì)地觀察一下這個(gè)進(jìn)程。下面的偽代碼顯示了一個(gè)內(nèi)存映射文件的例子:
HANDLE hFile = CreateFile(...);
HANDLE hFileMapping = CreateFileMapping(hFile, ...);
PVOID pvFile = MapViewOfFile(hFileMapping, ...);
// Use the memory-mapped file.
UnmapViewOfFile(pvFile);
CloseHandle(hFileMapping);
CloseHandle(hFile);
上面的代碼顯示了對(duì)內(nèi)存映射文件進(jìn)行操作所用的“預(yù)期”方法。但是,它沒(méi)有顯示,當(dāng)你調(diào)用M a p Vi e w O f F i l e時(shí)系統(tǒng)對(duì)文件對(duì)象和文件映射對(duì)象的使用計(jì)數(shù)的遞增情況。這個(gè)副作用是很大的,因?yàn)樗馕吨覀兛梢詫⑸厦娴拇a段重新編寫(xiě)成下面的樣子:
HANDLE hFile = CreateFile(...);
HANDLE hFileMapping = CreateFileMapping(hFile, ...);
CloseHandle(hFile);
PVOID pvFile = MapViewOfFile(hFileMapping, ...);
CloseHandle(hFileMapping);
// Use the memory-mapped file.
UnmapViewOfFile(pvFile);
當(dāng)對(duì)內(nèi)存映射文件進(jìn)行操作時(shí),通常要打開(kāi)文件,創(chuàng)建文件映射對(duì)象,然后使用文件映射對(duì)象將文件的數(shù)據(jù)視圖映射到進(jìn)程的地址空間。由于系統(tǒng)遞增了文件對(duì)象和文件映射對(duì)象的內(nèi)部使用計(jì)數(shù),因此可以在你的代碼開(kāi)始運(yùn)行時(shí)關(guān)閉這些對(duì)象,以消除資源泄漏的可能性。
如果用同一個(gè)文件來(lái)創(chuàng)建更多的文件映射對(duì)象,或者映射同一個(gè)文件映射對(duì)象的多個(gè)視圖,那么就不能較早地調(diào)用C l o s e H a n d l e函數(shù)——以后你可能還需要使用它們的句柄,以便分別對(duì)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)存映射文件來(lá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中,在單個(gè)計(jì)算機(jī)上共享數(shù)據(jù)的最低層機(jī)制是內(nèi)存映射文件。不錯(cuò),如果互相進(jìn)行通信的所有進(jìn)程都在同一臺(tái)計(jì)算機(jī)上的話,上面提到的所有機(jī)制均使用內(nèi)存映射文件從事它們的煩瑣工作。如果要求達(dá)到較高的性能和較小的開(kāi)銷,內(nèi)存映射文件是舉手可得的最佳機(jī)制。
數(shù)據(jù)共享方法是通過(guò)讓兩個(gè)或多個(gè)進(jìn)程映射同一個(gè)文件映射對(duì)象的視圖來(lái)實(shí)現(xiàn)的,這意味著它們將共享物理存儲(chǔ)器的同一個(gè)頁(yè)面。因此,當(dāng)一個(gè)進(jìn)程將數(shù)據(jù)寫(xiě)入一個(gè)共享文件映射對(duì)象的視圖時(shí),其他進(jìn)程可以立即看到它們視圖中的數(shù)據(jù)變更情況。注意,如果多個(gè)進(jìn)程共享單個(gè)文件映射對(duì)象,那么所有進(jìn)程必須使用相同的名字來(lái)表示該文件映射對(duì)象。
讓我們觀察一個(gè)例子,啟動(dòng)一個(gè)應(yīng)用程序。當(dāng)一個(gè)應(yīng)用程序啟動(dòng)時(shí),系統(tǒng)調(diào)用C r e a t e F i l e函數(shù),打開(kāi)磁盤上的. 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)建一個(gè)文件映射對(duì)象。最后,系統(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í)行代碼的第一個(gè)字節(jié)的地址放入線程的指令指針,然后C P U啟動(dòng)該代碼的運(yùn)行。
如果用戶運(yùn)行同一個(gè)應(yīng)用程序的第二個(gè)實(shí)例,系統(tǒng)就認(rèn)為規(guī)定的. e x e文件已經(jīng)存在一個(gè)文件映射對(duì)象,因此不會(huì)創(chuàng)建新的文件對(duì)象或者文件映射對(duì)象。相反,系統(tǒng)將第二次映射該文件的一個(gè)視圖,這次是在新創(chuàng)建的進(jìn)程的地址空間環(huán)境中映射的。系統(tǒng)所做的工作是將相同的文件同時(shí)映射到兩個(gè)地址空間。顯然,這是對(duì)內(nèi)存的更有效的使用,因?yàn)閮蓚€(gè)進(jìn)程將共享包含正在執(zhí)行的這部分代碼的物理存儲(chǔ)器的同一個(gè)頁(yè)面。
與所有內(nèi)核對(duì)象一樣,可以使用3種方法與多個(gè)進(jìn)程共享對(duì)象,這3種方法是句柄繼承性、句柄命名和句柄復(fù)制。
?內(nèi)存映射文件與數(shù)據(jù)視圖的相關(guān)性
附錄:
系統(tǒng)允許你映射一個(gè)文件的相同數(shù)據(jù)的多個(gè)視圖。例如,你可以將文件開(kāi)頭的10 KB映射到一個(gè)視圖,然后將同一個(gè)文件的頭4 KB映射到另一個(gè)視圖。只要你是映射相同的文件映射對(duì)象,系統(tǒng)就會(huì)確保映射的視圖數(shù)據(jù)的相關(guān)性。例如,如果你的應(yīng)用程序改變了一個(gè)視圖中的文件內(nèi)容,那么所有其他視圖均被更新以反映這個(gè)變化。這是因?yàn)楸M管頁(yè)面多次被映射到進(jìn)程的虛擬地址空間,但是系統(tǒng)只將數(shù)據(jù)放在單個(gè)R A M頁(yè)面上。如果多個(gè)進(jìn)程映射單個(gè)數(shù)據(jù)文件的視圖,那么數(shù)據(jù)仍然是相關(guān)的,因?yàn)樵跀?shù)據(jù)文件中,每個(gè)R A M頁(yè)面只有一個(gè)實(shí)例——正是這個(gè)R A M頁(yè)面被映射到多個(gè)進(jìn)程的地址空間。
注意Wi n d o w s允許創(chuàng)建若干個(gè)由單個(gè)數(shù)據(jù)文件支持的文件映射對(duì)象。Wi n d o w s不能保證這些不同的文件映射對(duì)象的視圖具有相關(guān)性。它只能保證單個(gè)文件映射對(duì)象的多個(gè)視圖具有相關(guān)性。
然而,當(dāng)對(duì)文件進(jìn)行操作時(shí),沒(méi)有理由使另一個(gè)應(yīng)用程序無(wú)法調(diào)用C r e a t e F i l e函數(shù)以打開(kāi)由另一個(gè)進(jìn)程映射的同一個(gè)文件。這個(gè)新進(jìn)程可以使用R e a d F i l e和Wr i t e F i l e函數(shù)來(lái)讀取該文件的數(shù)據(jù)和將數(shù)據(jù)寫(xiě)入該文件。當(dāng)然,每當(dāng)一個(gè)進(jìn)程調(diào)用這些函數(shù)時(shí),它必須從內(nèi)存緩沖區(qū)讀取文件數(shù)據(jù)或者將文件數(shù)據(jù)寫(xiě)入內(nèi)存緩沖區(qū)。該內(nèi)存緩沖區(qū)必須是進(jìn)程自己創(chuàng)建的一個(gè)緩沖區(qū),而不是映射文件使用的內(nèi)存緩沖區(qū)。當(dāng)兩個(gè)應(yīng)用程序打開(kāi)同一個(gè)文件時(shí),問(wèn)題就可能產(chǎn)生:一個(gè)進(jìn)程可以調(diào)用R e a d F i l e函數(shù)來(lái)讀取文件的一個(gè)部分,并修改它的數(shù)據(jù),然后使用Wr i t e F i l e函數(shù)將數(shù)據(jù)重新寫(xiě)入文件,而第二個(gè)進(jìn)程的文件映射對(duì)象卻不知道第一個(gè)進(jìn)程執(zhí)行的這些操作。由于這個(gè)原因,當(dāng)你為將被內(nèi)存映射的文件調(diào)用C r e a t e F i l e函數(shù)時(shí),最好將d w S h a r e M o d e參數(shù)的值設(shè)置為0。這樣就可以告訴系統(tǒng),你想要單獨(dú)訪問(wèn)這個(gè)文件,而其他進(jìn)程都不能打開(kāi)它。
只讀文件不存在相關(guān)性問(wèn)題,因此它們可以作為很好的內(nèi)存映射文件。內(nèi)存映射文件決不應(yīng)該用于共享網(wǎng)絡(luò)上的可寫(xiě)入文件,因?yàn)橄到y(tǒng)無(wú)法保證數(shù)據(jù)視圖的相關(guān)性。如果某個(gè)人的計(jì)算機(jī)更新了文件的內(nèi)容,其他內(nèi)存中含有原始數(shù)據(jù)的計(jì)算機(jī)將不知道它的信息已經(jīng)被修改。