1
using
System;
2
using
System.Collections.Generic;
3
using
System.Text;
4
using
System.IO;
5
using
System.Runtime.InteropServices;
/**/
/* 平台调用命名空间 */
6
7
namespace
CSharpFoundationStudy
8
{
9
/**//*
10
* 操作系统实验之快速文件系统C#实现
11
* P/Invoke 平台调用
12
* extern 修饰符用于声明由程序集外部实现的成员函数
13
* 经常用于系统API函数的调用(通过 DllImport )。注意,和DllImport一起使用时要加上static修饰符,也可以用于对于同一程序集不同版本组件的调用(用 extern 声明别名)
14
*/
15
16
public enum dwCreationDisposition
17
{
18
CREATE_NEW = 1,
19
CREATE_ALWAYS = 2,
20
OPEN_EXISTING = 3,
21
OPEN_ALWAYS = 4,
22
TRUNCATE_EXISTING = 5,
23
}
24
25
//异步调用需要使用
26
public struct OVERLAPPED
27
{
28
public int Internal;
29
public int InternalHigh;
30
public int Offset;
31
public int OffsetHigh;
32
public int hEvent;
33
}
34
35
/**//*
36
* MSDN文档
37
* 要封装平台功能,一种有效的方法是将常用的 DLL 函数包装在托管类中。虽然不必在每种情形下都这样做,但由于定义 DLL 函数可能会相当麻烦并且容易出错,所以提供类包装是一种很方便的方法。
38
* 在一个类中,为每个要调用的 DLL 函数定义静态方法。定义中可以包括一些附加信息,如在传递方法参数时使用的字符集或调用约定;如果省略这些信息,将选择默认设置。
39
* 包装之后,就可以按照对其他任何静态函数调用方法的相同方式来对该函数调用方法。平台调用将自动处理底层的导出函数。
40
*/
41
class Win32Invoke
42
{
43
// dwDesiredAccess
44
public const uint GENERIC_READ = 0x80000000;
45
public const uint GENERIC_WRITE = 0x40000000;
46
47
//dwShareMode
48
public const uint FILE_NOSHARE = 0;
49
public const uint FILE_SHARE_READ = 0x00000001;
50
public const uint FILE_SHARE_WRITE = 0x00000002;
51
52
//dwFlagsAndAttributes
53
// 定义:C:\Program Files\Microsoft Visual Studio 8\VC\PlatformSDK\Include\WinBase.h
54
public const uint FILE_FLAG_WRITE_THROUGH = 0x80000000;
55
public const uint FILE_FLAG_OVERLAPPED = 0x40000000; // 异步方法
56
public const uint FILE_FLAG_NO_BUFFERING = 0x20000000; // 无缓冲
57
public const uint FILE_FLAG_RANDOM_ACCESS = 0x10000000;
58
public const uint FILE_FLAG_SEQUENTIAL_SCAN = 0x08000000; // 缓冲
59
60
//VirtualAlloc参数
61
//flAllocationType
62
public const uint MEM_COMMIT = 0x1000;
63
public const uint MEM_RESERVE = 0x2000;
64
//flProtect
65
public const uint PAGE_READWRITE = 0x04;
66
public const uint PAGE_READONLY = 0x02;
67
public const uint PAGE_NOACCESS = 0x01;
68
69
//This function closes an open object handle[MSDN]
70
[DllImport("kernel32.dll", SetLastError = true)]
71
public static extern bool CloseHandle(IntPtr hObject);
72
73
[DllImport("kernel32.dll", SetLastError = true)]
74
public static extern IntPtr CreateFile(
75
string lpFileName,
76
uint desiredAccess,
77
uint shareMode,
78
uint lpSecurityAttributes,
79
dwCreationDisposition creationDisposition,
80
uint flagsAndAttributes,
81
int hTemplateFile);
82
83
[DllImport("kernel32.dll", SetLastError = true)]
84
public static extern bool ReadFile(
85
IntPtr hFile, //Handle to the file to be read.
86
byte[] lpBuffer, //Pointer to the buffer that receives the data read from the file
87
int nNumberOfBytesToRead, //Number of bytes to be read from the file
88
ref int lpNumberOfBytesRead, //Pointer to the number of bytes read.
89
ref OVERLAPPED overlapped);
90
91
//Return: Nonzero indicates success. Zero indicates failure
92
[DllImport("kernel32.dll", SetLastError = true)]
93
public static extern bool WriteFile(
94
IntPtr hFile, //Handle to the file to be written to
95
byte[] lpBuffer, //Pointer to the buffer containing the data to write to the file
96
int nNumberOfBytesToWrite, //Number of bytes to write to the file
97
ref int lpNumberOfBytesWritten, //Pointer to the number of bytes written by this function call
98
ref OVERLAPPED overlapped);
99
100
//The GetDiskFreeSpace function retrieves information about the specified disk, including the amount of free space on the disk
101
[DllImport("kernel32.dll", SetLastError = true)]
102
public static extern bool GetDiskFreeSpace(
103
string lpRootPathName, //Pointer to a null-terminated string that specifies the root directory of the disk for which information is to be returned.
104
ref int lpSectorsPerCluster, //Pointer to a variable that receives the number of sectors per cluster
105
ref int lpBytesPerSector, //Pointer to a variable that receives the number of bytes per sector
106
ref int lpNumberOfFreeClusters, //Pointer to a variable for the total number of free clusters on the disk that are available to the user who is associated with the calling thread.
107
ref int lpTotalNumberOfClusters); //Pointer to a variable for the total number of clusters on the disk that are available
108
109
//Reserves or commits a region of pages in the virtual address space of the calling process
110
[DllImport("kernel32.dll", SetLastError = true)]
111
public static extern IntPtr VirtualAlloc(
112
IntPtr lpAddress,
113
uint dwSize,
114
uint flAllocationType,
115
uint flProtect);
116
117
[DllImport("kernel32.dll", SetLastError = true)]
118
public static extern bool VirtualFree(
119
IntPtr lpAddress,
120
uint dwSize,
121
uint dwFreeType);
122
123
[DllImport("kernel32.dll", SetLastError = true)]
124
public static extern uint GetTickCount();
125
}
126
127
class quickFileSys
128
{
129
//读取文件长度为 2M
130
public static readonly int length = 1024 * 1024 * 2;
131
132
//返回实际读取的字节数
133
public static int ReadFrom(string sourceFileName, byte[] sourceBytes, uint mode)
134
{
135
int count = 0;
136
OVERLAPPED overlap = new OVERLAPPED();
137
138
IntPtr fHandle = Win32Invoke.CreateFile(sourceFileName, Win32Invoke.GENERIC_READ, Win32Invoke.FILE_SHARE_READ, 0, dwCreationDisposition.OPEN_EXISTING, mode, 0);
139
140
Win32Invoke.ReadFile(fHandle, sourceBytes, length, ref count, ref overlap);
141
142
return count;
143
}
144
145
//返回实际写入的字节数
146
public static int WriteTo(string destiFileName, byte[] destiBytes, uint mode)
147
{
148
int count = 0;
149
OVERLAPPED overlap = new OVERLAPPED();
150
151
IntPtr fHandle = Win32Invoke.CreateFile(destiFileName, Win32Invoke.GENERIC_WRITE, Win32Invoke.FILE_NOSHARE, 0, dwCreationDisposition.CREATE_ALWAYS, mode, 0);
152
153
Win32Invoke.WriteFile(fHandle, destiBytes, length, ref count, ref overlap);
154
155
return count;
156
}
157
158
public static uint filter(string sourceFileName, string destiFileName, uint mode)
159
{
160
byte[] data = new byte[length];
161
uint dwStartTime = Win32Invoke.GetTickCount();
162
ReadFrom(sourceFileName, data, mode);
163
WriteTo(destiFileName, data, mode);
164
uint dwEndTime = Win32Invoke.GetTickCount();
165
166
return dwEndTime - dwStartTime;
167
}
168
169
public static void display(uint mode, string displayStr)
170
{
171
int loop = 10;
172
uint dwTimeElapsed = 0;
173
uint total_nobuffering = 0;
174
for (int i = 0; i < loop; i++)
175
{
176
dwTimeElapsed = filter("test.txt", string.Format(displayStr + "{0}.txt", i), mode);
177
total_nobuffering += dwTimeElapsed;
178
Console.WriteLine(string.Format(displayStr + "{0}: {1}ms", i, dwTimeElapsed));
179
}
180
Console.WriteLine(string.Format(displayStr + "[Total]: {0}ms", total_nobuffering));
181
Console.WriteLine(string.Format(displayStr + "[Average]: {0}ms", total_nobuffering / loop));
182
Console.WriteLine("**************************************************************************");
183
}
184
185
//public static void Main()
186
//{
187
// display(Win32Invoke.FILE_FLAG_NO_BUFFERING, "file_flag_no_buffering");
188
// display(Win32Invoke.FILE_FLAG_SEQUENTIAL_SCAN, "file_flag_sequential_scan");
189
// display(Win32Invoke.FILE_FLAG_OVERLAPPED, "file_flag_overlapped");
190
// Console.Read();
191
//}
192
}
193
}
194
195

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

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128



129

130

131

132

133

134



135

136

137

138

139

140

141

142

143

144

145

146

147



148

149

150

151

152

153

154

155

156

157

158

159



160

161

162

163

164

165

166

167

168

169

170



171

172

173

174

175



176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195
