時間: 分類:推薦論文 瀏覽次數(shù):
摘要:CPU速度比內(nèi)存更快,內(nèi)存中的緩存是用來解決CPU和內(nèi)存速度差異的。多個模塊都可以訪問內(nèi)存緩沖區(qū),據(jù)此可以實(shí)用內(nèi)存來實(shí)現(xiàn)進(jìn)程間的數(shù)據(jù)共享。本文在Unix環(huán)境下實(shí)現(xiàn)該技術(shù)。
關(guān)鍵字:共享內(nèi)存 多進(jìn)程 文件映射
Abstract: CPU speed faster than the memory, the cache memory is used to solve the CPU and memory speed differences. Multiple modules can access memory buffer, accordingly can realize between memories to practical process data sharing based on UNIX environment to realize this technology.
Key Word: shared memory, processes, file mapping
中圖分類號:C37 文獻(xiàn)標(biāo)識碼:A 文章編號:
一、Windows系統(tǒng)中的共享內(nèi)存的概念
共享內(nèi)存是在不同進(jìn)程間可共享的內(nèi)存塊,是通過將同一塊物理內(nèi)存映射到不同進(jìn)程地址空間中的方法,實(shí)現(xiàn)數(shù)據(jù)在內(nèi)存中直接被不同進(jìn)程共享。共享內(nèi)存在幾乎所有的操作系統(tǒng)中都存在,是進(jìn)程間共享數(shù)據(jù)最高效的方法。
在Windows操作系統(tǒng)中,共享內(nèi)存是通過文件映射來使用。文件映射按共享方式可分為命名文件映射和非命名文件映射,按底層文件支持方式,又可分為有文件支持的文件映射和無文件支持的文件映射。
命名文件映射指在創(chuàng)建文件映射時,為該文件映射提供一個名稱,其它進(jìn)程需要使用該文件映射時,通過該名稱打開已經(jīng)存在的文件映射。為文件映射起名時要注意,如果是在安裝了終端服務(wù)器的服務(wù)器操作系統(tǒng)上,需要指定\\Global\或\\Local\名稱前綴,指示是全局名稱還是當(dāng)前用戶會話范圍的名稱。
有底層文件支持的文件映射在創(chuàng)建文件映射時,為文件映射提供一個打開的文件句柄,該文件映射將對應(yīng)使用提供的文件。文件映射創(chuàng)建的文件的一塊區(qū)域或全部文件范圍。文件映射的大小和文件本身的大小無關(guān),如果文件的原始長度小于創(chuàng)建文件映射時指定的長度,Windows系統(tǒng)將首先將文件擴(kuò)展到需要的長度,然后再創(chuàng)建文件映射。在文件映射被關(guān)閉后,共享內(nèi)存中的數(shù)據(jù)會由操作系統(tǒng)自動保存到底層文件中,無需共享內(nèi)存使用進(jìn)程來處理數(shù)據(jù)的保存。當(dāng)再次打開文件映射時,只需指定不要清除文件中的原有數(shù)據(jù),即可直接使用上次進(jìn)程關(guān)閉時所保存的數(shù)據(jù)。利用這個功能,可以很容易實(shí)現(xiàn)進(jìn)程執(zhí)行狀態(tài)的保存。
無底層文件支持的文件映射是在創(chuàng)建文件映射時,為該文件映射提供一個無效的文件句柄作為創(chuàng)建參數(shù),同時提供文件映射的大小參數(shù)。Windows將在系統(tǒng)頁面文件上,創(chuàng)建該文件映射。當(dāng)文件映射被關(guān)閉時,共享內(nèi)存中的數(shù)據(jù)將丟失。
二、如何通過Windows Native API調(diào)用,使用共享內(nèi)存
使用共享內(nèi)存的進(jìn)程,需要完成以下步驟,來創(chuàng)建或打開共享內(nèi)存:
1) 利用CreateFile()函數(shù)打開底層支持文件。
2) 使用CreateFileMapping()創(chuàng)建文件映射。如果創(chuàng)建文件映射成功,本函數(shù)將返回文件映射對象的句柄。如果同名的文件映射對象已經(jīng)存在,本函數(shù)將返回該對象的句柄,使用GetLastError()將返回ERROR_ALREADY_EXISTS。當(dāng)創(chuàng)建出錯時,本函數(shù)將返回null,通過GetLastError()函數(shù)將返回錯誤代碼。
3) 使用MapViewOfFile()或MapViewOfFileEx()函數(shù),將文件的一部分映射到進(jìn)程的地址空間中。本函數(shù)將文件的一部分或全部映射到進(jìn)程的地址空間中,函數(shù)返回共享內(nèi)存的起始地址指針。
對于后啟動的進(jìn)程,可以使用OpenFileMapping()函數(shù)來打開一個已知名稱的文件映射,或使用繼承得到或復(fù)制得到的句柄,直接使用文件映射對象。
在使用共享內(nèi)存的過程中,所有進(jìn)程通過共享內(nèi)存看到的文件相同部分的內(nèi)容是一致的。但如果是通過文件讀寫來訪問文件,看到文件相同部分,不保證是一致的。
在使用完共享內(nèi)存后,請使用UnmapViewOfFile()釋放共享內(nèi)存的映射。關(guān)閉同一個文件映射上的所有共享內(nèi)存映射后,可使用CloseHandle()函數(shù)關(guān)閉文件映射對象和底層文件。所有使用共享內(nèi)存對象的進(jìn)程都關(guān)閉了共享內(nèi)存對象后,共享內(nèi)存對象才會被Windows系統(tǒng)釋放。在釋放共享內(nèi)存對象的映射之前,使用CloseHandle()關(guān)閉函數(shù)文件映射對象,并不能釋放共享內(nèi)存對象和文件映射對象,只有該文件映射對象上的所有共享內(nèi)存映射都被釋放后,該文件映射對象才會被操作系統(tǒng)所釋放。
三、在C#中,通過封裝Windows API,實(shí)現(xiàn)托管代碼使用共享內(nèi)存
作為微軟公司下一代的開發(fā)平臺,.NET Framework近來成為Windows平臺下程序開發(fā)人員的新寵,特別是C#語言,更是如日中天,但該平臺并不能涵蓋Windows開發(fā)的所有方面,特別是托管代碼并不鼓勵直接使用內(nèi)存指針,這樣,共享內(nèi)存的使用在.NET Framework中并不被直接支持。
要想使用共享內(nèi)存在托管代碼進(jìn)程間高效共享數(shù)據(jù),必須使用C#語言,自己封裝Windows Native API,使用C#項(xiàng)目的非安全代碼,并使用C#語言支持的指針操作。
.NET Framework 4.0的發(fā)布,結(jié)束了這個痛苦的經(jīng)歷。.Net 4.0中,新增加了命名空間:System.IO.MemoryMappedFiles,該命名空間中,包括MemoryMappedFile,MemoryMappedFileSecurity,MemoryMappedViewAccessor,MemoryMappedViewStream 4個類。
MemoryMappedFile類管理內(nèi)存映像文件,其中CreateFromFile方法基于磁盤上的現(xiàn)有文件的指定路徑或 FileStream創(chuàng)建一個內(nèi)存映射文件。 未映射映射文件時,更改都將自動傳播到磁盤。CreateNew方法創(chuàng)建一個未映射到磁盤上的現(xiàn)有文件的內(nèi)存映射文件;而且這些方法還適合創(chuàng)建用于進(jìn)程間通信 (IPC) 的共享內(nèi)存。
MemoryMappedFileSecurity表示可以針對內(nèi)存映射文件授予的文件訪問和操作權(quán)限。
MemoryMappedViewAccessor類被用來訪問可隨機(jī)訪問的內(nèi)存映射文件視圖,該類通過SafeBuffer類封裝了映射到本地的非托管內(nèi)存指針,并提供了大量的訪問內(nèi)存中內(nèi)容的方法。本類使用CreateViewAccessor方法來獲取此視圖。
MemoryMappedViewStream類將內(nèi)存映射文件的視圖表示為按順序訪問的流。使用 CreateViewStream對象的MemoryMappedFile方法來獲取此流。
以下是一個訪問內(nèi)存映像文件的主要代碼片段,其中MyColor是一個自定義的結(jié)構(gòu)類型:
long offset = 0x10000000;long length = 0x20000000;
using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\ExtremelyLargeImage.data",
FileMode.Open,"ImgA"))
{ using (var accessor = mmf.CreateViewAccessor(offset, length))
{ int colorSize = Marshal.SizeOf(typeof(MyColor));
MyColor color;
for (long i = 0; i < length; i += colorSize)
{ accessor.Read(i, out color);
color.Brighten(10);
accessor.Write(i, ref color);
}
}
四、結(jié)束語
經(jīng)實(shí)際測試,共享內(nèi)存相比其他幾種方式有著更方便的數(shù)據(jù)控制能力,使用共享內(nèi)存在處理大數(shù)據(jù)量數(shù)據(jù)的快速交換時表現(xiàn)出了良好的性能,在數(shù)據(jù)可靠性等方面要遠(yuǎn)遠(yuǎn)高于發(fā)送WM_COPYDATA消息的方式,數(shù)據(jù)在讀寫過程中會更透明。這種大容量、高速的數(shù)據(jù)共享處理方式在設(shè)計(jì)高速數(shù)傳模塊通訊類軟件中有著很好的使用效果。
級別:北大核心,CSSCI,AMI擴(kuò)展
ISSN:1002-6487
刊期:進(jìn)入查看
格式:咨詢顧問
級別:北大核心,JST,CSSCI,WJCI,AMI權(quán)威
ISSN:1002-4565
刊期:進(jìn)入查看
格式:咨詢顧問
級別:北大核心,JST,CSCD,CSSCI,WJCI
ISSN:1002-2104
刊期:進(jìn)入查看
格式:咨詢顧問
級別:北大核心,CSSCI,AMI權(quán)威,社科基金資助期刊,
ISSN:1003-1707
刊期:進(jìn)入查看
格式:咨詢顧問
數(shù)據(jù)庫:SCI
ISSN:2045-2322
刊期:進(jìn)入查看
格式:咨詢顧問
數(shù)據(jù)庫:SCI
ISSN:0284-1851
刊期:進(jìn)入查看
格式:咨詢顧問
數(shù)據(jù)庫:SCI
ISSN:2352-4928
刊期:進(jìn)入查看
格式:咨詢顧問
數(shù)據(jù)庫:SCI
ISSN:0169-4332
刊期:進(jìn)入查看
格式:咨詢顧問
數(shù)據(jù)庫:SCI
ISSN:0960-7412
刊期:進(jìn)入查看
格式:咨詢顧問