'<接上>
Public Sub GetFromMap(S As String) 
If MapAddress <> 0 Then 
Call lstrcpyn(ByVal S, ByVal MapAddress, LenBuffer + 1) 
End If 
End Sub 
   
Public Sub CloseMap() 
If MapAddress <> 0 Then 
Call UnmapViewOfFile(ByVal MapAddress) 
MapAddress = 0 
End If 
If MapHandle <> 0 Then 
Call CloseHandle(MapHandle) 
MapHandle = 0 
End If 
If FileHandle <> 0 Then 
Call CloseHandle(FileHandle) 
FileHandle = 0 
End If 
End Sub 'CloseMap 
   
#If Sampling Then 
   
Public Sub CreateMap() 
Dim w As Long 
   
Call InitVar 
FileHandle = CreateFile(DiskFileName, _ 
GENERIC_WRITE Or GENERIC_READ, _ 
FILE_SHARE_READ Or FILE_SHARE_WRITE, _ 
0, _ 
CREATE_ALWAYS, _ 
FILE_ATTRIBUTE_NORMAL, _ 
0) 
Call WriteFile(FileHandle, ByVal strBuffer, LenBuffer + 1, w, 0) 
Call FlushFileBuffers(FileHandle) 
   
MapHandle = CreateFileMapping(FileHandle, _ 
0, _ 
PAGE_READWRITE, _ 
0, _ 
0, _ 
MapFileName) 
MapAddress = MapViewOfFile(MapHandle, FILE_MAP_WRITE, 0, 0, 0) 
End Sub 'CreateMap 
   
#Else 
   
Public Function OpenMap() As Long 
Call InitVar 
OpenMap = 0 
MapHandle = OpenFileMapping(FILE_MAP_WRITE, False, MapFileName) 
If MapHandle = 0 Then Exit Function 
MapAddress = MapViewOfFile(MapHandle, FILE_MAP_WRITE, 0, 0, 0) 
If MapAddress = 0 Then 
Call CloseHandle(MapHandle) 
MapHandle = 0 
End If 
OpenMap = MapAddress 
End Function 'OpenMap 
   
#End If 'Sampling 
   
Manage.vbp也包含两个文件:Form1.frm,Module1.bas。清单如下: 
Form1.frm: 
VERSION 5.00 
Begin VB.Form Form1  
Caption = "Manage" 
ClientHeight = 1440 
ClientLeft = 48 
ClientTop = 288 
ClientWidth = 4416 
LinkTopic = "Form1" 
ScaleHeight = 1440 
ScaleWidth = 4416 
StartUpPosition = 3 '窗口缺省 
Begin VB.CommandButton cmdStart  
Caption = "Start" 
Height = 372 
Left = 1560 
TabIndex = 1 
Top = 240 
Width = 972 
End 
Begin VB.TextBox Text1  
Height = 372 
Left = 120 
TabIndex = 0 
Text = "Text1" 
Top = 840 
Width = 4092 
End 
Begin VB.Timer Timer1  
Enabled = 0 'False 
Interval = 60 
Left = 0 
Top = 0 
End 
End 
Attribute VB_Name = "Form1" 
Attribute VB_GlobalNameSpace = False 
Attribute VB_Creatable = False 
Attribute VB_PredeclaredId = True 
Attribute VB_Exposed = False 
Option Explicit 
   
Private Sub cmdStart_Click() 
If OpenMap() = 0 Then 
MsgBox "采样程序未运行!", vbOKOnly, "" 
Exit Sub 
End If 
   
Pub_Timer1Run = False 
Timer1.Enabled = True 
cmdStart.Enabled = False 
End Sub 
   
Private Sub Form_Unload(Cancel As Integer) 
Call CloseMap 
End Sub 
   
Private Sub Timer1_Timer() 
Static tm As Single, Dlt As Single 
Static i As Integer 
Static dtNow As Date 
Static S As String 
Static v(1 To Pub_LoopN) As Single 
   
If Pub_Timer1Run Then Exit Sub 
Pub_Timer1Run = True 
   
Call GetFromMap(strBuffer) 
If Left(strBuffer, 1) = " " Then 
strBuffer = "*" & Mid(strBuffer, 2) 
Call CopyToMap(strBuffer) 
Text1.Text = strBuffer 
End If 
   
Pub_Timer1Run = False 
End Sub 'Timer1_Timer  
   
Module1.bas:与Sampling.vbp之Module1.bas几乎完全相同,只是其中编译常数Sampling= False。 
三. 函数描述 
在Module1.bas中用到几个与文件映射有关的API函数,分述如下: 
1.CreateFileMapping:创建文件映射对象 
参数: 
hFile:Long——欲在其中创建映射的一个已经打开的磁盘文件句柄; 
LpFileMappingAttributes:Long——通常用0表示使用默认安全对象; 
FlProtect:Long——打开映射的方式(用API常数表示的读/写或其它); 
DwMaximumSizeHigh,dwMaximumSizeLow:Long——共同表示文件映射的最大长度(前者为高32位,后者为低32位),通常均设为0表示磁盘文件的实际长度; 
LpName: String——指定文件映射对象的名称。 
返回值:Long——新建文件映射对象的句柄。 
2.OpenFileMapping:打开一个现成的文件映射对象 
参数: 
dwDesiredAccess:Long——用API常数表示的对文件映射的访问方式; 
bInheritHandle:Long——返回值对与子进程的继承属性,常设为False; 
lpName:String——准备打开的文件映射对象的名称。 
返回值:Long——指定的文件映射对象的句柄。 
3.MapViewOfFile:将一个文件映射对象映射到当前应用程序空间 
参数: 
hFileMappingObject:Long——文件映射对象的句柄; 
dwDesiredAccess:Long——用API常数表示的对文件映射的访问方式; 
dwFileOffsetHigh,dwFileOffsetLow:Long——共同表示文件中的映射起点(前者为高32位,后者为低32位),通常均设为0表示从文件的起始处开始映射; 
dwNumberOfBytesToMap:Long——要映射的字节数,通常设为0表示映射整个文件映射对象。 
返回值:Long——文件映射在内存中的起始地址。 
4.UnmapViewOfFile:解除当前应用程序中的一个文件映射对象的映射地址空间 
参数: 
lpBaseAddress:要解除映射的文件映射起始地址。 
返回值:Long——非零表示成功,零表示失败。 
Sampling.vbp的启动窗体Form1.frm在装载时创建一个文件映射(CreateMap),这个创建过程分三步:首先,通过CreateFile,WriteFile,FlushFileBuffers建立一个具有指定长度(LenBuffer + 1)的磁盘文件DiskFileName;然后,由CreateFileMapping创建一个对应于磁盘文件DiskFileName的文件映射对象MapFileName;最后,用MapViewOfFile将文件映射对象映射到应用程序地址MapAddress。在本例中,磁盘文件建立后便不再与之打交道,以后的操作均针对其映射地址空间。 
采样通过触发定时器Timer1周期性的进行(采样周期Pub_Period)。每次采样首先通过GetV取得原始样本并放入数组v(本例的样本用随机数替代,实际应用中是从RS232或其他设备取得),然后将其存入映射地址空间以便“管理程序”取用。样本在映射地址空间的存放形式为:“x 采样时间 样本值1 样本值2”。其中x是一个标记,当它为空格时表示新样本,为“*”时表示已取用。 为了方便程序处理,设置了一个样本缓冲strBuffer,由它与映射地址空间交换数据,CopyToMap和GetFromMap也是用于这个目的,CopyToMap(S)是复制S到映射地址空间,而GetFromMap(S)是从映射地址空间取值送到S。 
在“采样程序”运行过程中,“管理程序”由于某种原因(如维护程序)可能长时间不取用样本(超过一个采样周期),这时,“采样程序”应当把样本存放到另外的磁盘文件,以免丢失样本。考虑到本文主题和文章篇幅,本例未做处理。 
Manage.vbp启动窗体Form1.frm很简单,仅仅从演示的角度将映射地址空间的数据取出并显示。 
试验时先运行“采样”, 再运行“管理”,观察两个窗体中的样本数据,我们会发现他们几乎是同步的。感谢文件映射!