時間: 分類:推薦論文 次數:
摘要:CPU速度比內存更快,內存中的緩存是用來解決CPU和內存速度差異的。多個模塊都可以訪問內存緩沖區,據此可以實用內存來實現進程間的數據共享。本文在Unix環境下實現該技術。
關鍵字:共享內存 多進程 文件映射
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 文獻標識碼:A 文章編號:
一、Windows系統中的共享內存的概念
共享內存是在不同進程間可共享的內存塊,是通過將同一塊物理內存映射到不同進程地址空間中的方法,實現數據在內存中直接被不同進程共享。共享內存在幾乎所有的操作系統中都存在,是進程間共享數據最高效的方法。
在Windows操作系統中,共享內存是通過文件映射來使用。文件映射按共享方式可分為命名文件映射和非命名文件映射,按底層文件支持方式,又可分為有文件支持的文件映射和無文件支持的文件映射。
命名文件映射指在創建文件映射時,為該文件映射提供一個名稱,其它進程需要使用該文件映射時,通過該名稱打開已經存在的文件映射。為文件映射起名時要注意,如果是在安裝了終端服務器的服務器操作系統上,需要指定\\Global\或\\Local\名稱前綴,指示是全局名稱還是當前用戶會話范圍的名稱。
有底層文件支持的文件映射在創建文件映射時,為文件映射提供一個打開的文件句柄,該文件映射將對應使用提供的文件。文件映射創建的文件的一塊區域或全部文件范圍。文件映射的大小和文件本身的大小無關,如果文件的原始長度小于創建文件映射時指定的長度,Windows系統將首先將文件擴展到需要的長度,然后再創建文件映射。在文件映射被關閉后,共享內存中的數據會由操作系統自動保存到底層文件中,無需共享內存使用進程來處理數據的保存。當再次打開文件映射時,只需指定不要清除文件中的原有數據,即可直接使用上次進程關閉時所保存的數據。利用這個功能,可以很容易實現進程執行狀態的保存。
無底層文件支持的文件映射是在創建文件映射時,為該文件映射提供一個無效的文件句柄作為創建參數,同時提供文件映射的大小參數。Windows將在系統頁面文件上,創建該文件映射。當文件映射被關閉時,共享內存中的數據將丟失。
二、如何通過Windows Native API調用,使用共享內存
使用共享內存的進程,需要完成以下步驟,來創建或打開共享內存:
1) 利用CreateFile()函數打開底層支持文件。
2) 使用CreateFileMapping()創建文件映射。如果創建文件映射成功,本函數將返回文件映射對象的句柄。如果同名的文件映射對象已經存在,本函數將返回該對象的句柄,使用GetLastError()將返回ERROR_ALREADY_EXISTS。當創建出錯時,本函數將返回null,通過GetLastError()函數將返回錯誤代碼。
3) 使用MapViewOfFile()或MapViewOfFileEx()函數,將文件的一部分映射到進程的地址空間中。本函數將文件的一部分或全部映射到進程的地址空間中,函數返回共享內存的起始地址指針。
對于后啟動的進程,可以使用OpenFileMapping()函數來打開一個已知名稱的文件映射,或使用繼承得到或復制得到的句柄,直接使用文件映射對象。
在使用共享內存的過程中,所有進程通過共享內存看到的文件相同部分的內容是一致的。但如果是通過文件讀寫來訪問文件,看到文件相同部分,不保證是一致的。
在使用完共享內存后,請使用UnmapViewOfFile()釋放共享內存的映射。關閉同一個文件映射上的所有共享內存映射后,可使用CloseHandle()函數關閉文件映射對象和底層文件。所有使用共享內存對象的進程都關閉了共享內存對象后,共享內存對象才會被Windows系統釋放。在釋放共享內存對象的映射之前,使用CloseHandle()關閉函數文件映射對象,并不能釋放共享內存對象和文件映射對象,只有該文件映射對象上的所有共享內存映射都被釋放后,該文件映射對象才會被操作系統所釋放。
三、在C#中,通過封裝Windows API,實現托管代碼使用共享內存
作為微軟公司下一代的開發平臺,.NET Framework近來成為Windows平臺下程序開發人員的新寵,特別是C#語言,更是如日中天,但該平臺并不能涵蓋Windows開發的所有方面,特別是托管代碼并不鼓勵直接使用內存指針,這樣,共享內存的使用在.NET Framework中并不被直接支持。
要想使用共享內存在托管代碼進程間高效共享數據,必須使用C#語言,自己封裝Windows Native API,使用C#項目的非安全代碼,并使用C#語言支持的指針操作。
.NET Framework 4.0的發布,結束了這個痛苦的經歷。.Net 4.0中,新增加了命名空間:System.IO.MemoryMappedFiles,該命名空間中,包括MemoryMappedFile,MemoryMappedFileSecurity,MemoryMappedViewAccessor,MemoryMappedViewStream 4個類。
MemoryMappedFile類管理內存映像文件,其中CreateFromFile方法基于磁盤上的現有文件的指定路徑或 FileStream創建一個內存映射文件。 未映射映射文件時,更改都將自動傳播到磁盤。CreateNew方法創建一個未映射到磁盤上的現有文件的內存映射文件;而且這些方法還適合創建用于進程間通信 (IPC) 的共享內存。
MemoryMappedFileSecurity表示可以針對內存映射文件授予的文件訪問和操作權限。
MemoryMappedViewAccessor類被用來訪問可隨機訪問的內存映射文件視圖,該類通過SafeBuffer類封裝了映射到本地的非托管內存指針,并提供了大量的訪問內存中內容的方法。本類使用CreateViewAccessor方法來獲取此視圖。
MemoryMappedViewStream類將內存映射文件的視圖表示為按順序訪問的流。使用 CreateViewStream對象的MemoryMappedFile方法來獲取此流。
以下是一個訪問內存映像文件的主要代碼片段,其中MyColor是一個自定義的結構類型:
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);
}
}
四、結束語
經實際測試,共享內存相比其他幾種方式有著更方便的數據控制能力,使用共享內存在處理大數據量數據的快速交換時表現出了良好的性能,在數據可靠性等方面要遠遠高于發送WM_COPYDATA消息的方式,數據在讀寫過程中會更透明。這種大容量、高速的數據共享處理方式在設計高速數傳模塊通訊類軟件中有著很好的使用效果。
級別:CSSCI南大期刊,北大期刊,統計源期刊
ISSN:1001-4233
刊期:進入查看
格式:咨詢顧問
級別:北大期刊,CSSCI南大期刊
ISSN:1671-7465
刊期:進入查看
格式:咨詢顧問
級別:CSSCI南大期刊,北大期刊,統計源期刊
ISSN:1005-9245
刊期:進入查看
格式:咨詢顧問
級別:北大期刊,統計源期刊,CSSCI南大期刊
ISSN:1000-5560
刊期:進入查看
格式:咨詢顧問
數據庫:SCI
ISSN:2045-2322
刊期:進入查看
格式:咨詢顧問
數據庫:SCI
ISSN:0284-1851
刊期:進入查看
格式:咨詢顧問
數據庫:SCI
ISSN:2352-4928
刊期:進入查看
格式:咨詢顧問
數據庫:SCI
ISSN:0169-4332
刊期:進入查看
格式:咨詢顧問
數據庫:SCI
ISSN:0960-7412
刊期:進入查看
格式:咨詢顧問
數據庫:SCI
ISSN:0048-9697
刊期:進入查看
格式:咨詢顧問
數據庫:SCI
ISSN:0191-2917
刊期:進入查看
格式:咨詢顧問
數據庫:SCI
ISSN:1741-7007
刊期:進入查看
格式:咨詢顧問
數據庫:SCI
ISSN:2238-7854
刊期:進入查看
格式:咨詢顧問
數據庫:SCI
ISSN:2214-7144
刊期:進入查看
格式:咨詢顧問