精華)2020年8月31日 計算機操作系統 IO概念和五種IO模型">(精華)2020年8月31日 計算機操作系統 IO概念和五種IO模型
793
2025-03-31
一:內存映射文件
1.節點通信存在兩種模型:共享內存(Shared memory)和消息傳遞(Messages passing)。
2.內存映射文件對于托管世界的開發人員來說似乎很陌生,但它確實已經是很遠古的技術了,而且在操作系統中地位相當。實際上,任何想要共享數據的通信模型都會在幕后使用它。
3.內存映射文件究竟是個什么?內存映射文件允許你保留一塊地址空間,然后將該物理存儲映射到這塊內存空間中進行操作。物理存儲是文件管理,而內存映射文件是操作系統級內存管理。
優勢:
1.訪問磁盤文件上的數據不需執行I/O操作和緩存操作(當訪問文件數據時,作用尤其顯著);
2.讓運行在同一臺機器上的多個進程共享數據(單機多進程間數據通信效率最高);
利用文件與內存空間之間的映射,應用程序(包括多個進程)可以通過直接在內存中進行讀寫來修改文件。.NET Framework 4 用托管代碼按照本機Windows函數訪問內存映射文件的方式來訪問內存映射文件,管理 Win32 中的內存映射文件 。
有兩種類型的內存映射文件:
持久內存映射文件
持久文件是與磁盤上的源文件關聯的內存映射文件。在最后一個進程使用完此文件后,數據將保存到磁盤上的源文件中。這些內存映射文件適合用來處理非常大的源文件。
非持久內存映射文件
非持久文件是未與磁盤上的源文件關聯的內存映射文件。當最后一個進程使用完此文件后,數據將丟失,并且垃圾回收功能將回收此文件。這些文件適用于為進程間通信 (IPC) 創建共享內存。
1)在多個進程之間進行共享(進程可通過使用由創建同一內存映射文件的進程所指派的公用名來映射到此文件)。
2)若要使用一個內存映射文件,則必須創建該內存映射文件的完整視圖或部分視圖。還可以創建內存映射文件的同一部分的多個視圖,進而創建并發內存。為了使兩個視圖能夠并發,必須基于同一內存映射文件創建這兩個視圖。
3)如果文件大于應用程序用于內存映射的邏輯內存空間(在 32 位計算機上為2GB),則還需要使用多個視圖。
有兩種類型的視圖:流訪問視圖和隨機訪問視圖。使用流訪問視圖可對文件進行順序訪問;在使用持久文件時,隨機訪問視圖是首選方法。
.Net 共享內存 內存映射文件原理:通過操作系統的內存管理器訪問的,因此會自動將此文件分隔為多個頁,并根據需要對其進行訪問。您不需要自行處理內存管理。如下圖:
C# .Net 共享內存 演示代碼如下:
持久內存映射文件:基于現有文件創建一個具有指定公用名的內存映射文件
using (var mmf = MemoryMappedFile.CreateFromFile(@"c:\內存映射文件.data", FileMode.Open, "公用名")) { //通過指定的 偏移量和大小 創建內存映射文件視圖服務器 using (var accessor = mmf.CreateViewAccessor(offset, length)) //偏移量,可以控制數據存儲的內存位置;大小,用來控制存儲所占用的空間 { //Marshal提供了一個方法集,這些方法用于分配非托管內存、復制非托管內存塊、將托管類型轉換為非托管類型,此外還提供了在與非托管代碼交互時使用的其他雜項方法。 int size = Marshal.SizeOf(typeof(char)); //修改內存映射文件視圖 for (long i = 0; i < length; i += size) { char c= accessor.ReadChar(i); accessor.Write(i, ref c); } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//另一個進程或線程可以,在系統內存中打開一個具有指定名稱的現有內存映射文件 using (var mmf = MemoryMappedFile.OpenExisting("公用名")) { using (var accessor = mmf.CreateViewAccessor(4000000, 2000000)) { int size = Marshal.SizeOf(typeof(char)); for (long i = 0; i < length; i += size) { char c = accessor.ReadChar(i); accessor.Write(i, ref c); } } }
1
2
3
4
5
6
7
8
9
10
11
12
13
非持久內存映射文件:未映射到磁盤上的現有文件的內存映射文件
using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 10000)) { bool mutexCreated; //進程間同步 Mutex mutex = newMutex(true, "testmapmutex", out mutexCreated); using (var stream = mmf.CreateViewStream()) //創建文件內存視圖流 基于流的操作 { var writer = newBinaryWriter(stream); writer.Write(1); } mutex.ReleaseMutex(); Console.WriteLine("Start Process B and press ENTER to continue."); Console.ReadLine(); mutex.WaitOne(); using (MemoryMappedViewStream stream = mmf.CreateViewStream()) { var reader = newBinaryReader(stream); Console.WriteLine("Process A says: {0}", reader.ReadBoolean()); Console.WriteLine("Process B says: {0}", reader.ReadBoolean()); } mutex.ReleaseMutex(); }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap")) { Mutex mutex = Mutex.OpenExisting("testmapmutex"); mutex.WaitOne(); using (var stream = mmf.CreateViewStream(1, 0))//注意這里的偏移量 { var writer = newBinaryWriter(stream); writer.Write(0); } mutex.ReleaseMutex(); }
1
2
3
4
5
6
7
8
9
10
11
12
C#共享內存非持久化方式通訊的例子,通訊時的線程和進程控制也沒有問題。如下是實現的代碼。
先啟動消息服務IMServer_Message,
再啟動狀態服務IMServer_State,
IMServer_Message回車一次(創建共享內存公用名和公用線程鎖,并視圖流方式寫共享內存),
IMServer_State回車一次(獲取共享內存并視圖流方式寫、視圖訪問器寫入結構體類型)
并立刻IMServer_Message再回車一次(讀取剛剛寫入的信息),
觀察IMServer_State屏顯變化并等待(線程鎖)約5s(線程鎖被釋放)后
在IMServer_Message上觀察屏顯(顯示剛剛寫入共享內存的信息)
IMServer_Message.exe 代碼
using System; using System.IO; using System.IO.MemoryMappedFiles; using System.Runtime.InteropServices; using System.Threading; namespace IMServer_Message { ///
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
IMServer_State.exe代碼
using System; using System.IO; using System.IO.MemoryMappedFiles; using System.Runtime.InteropServices; using System.Threading; namespace IMServer_State { ///
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
C# 任務調度
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。