Windows 的這個 File Mapping 的方法,是可以用在 file 及 memory 的。
用了這個方法,不同的 process 就可以共用一個 memory 區域,達到 share memory 的功能。
要 share memory ,其步驟是
1 CreateFileMapping, 請求開啟一個區域,並且給該區域一個名字。之後,可以得到該區域的 handle,
2 MapViewOfFile, 要對已開啟的區域做動作,必須要建立一個 view 才行。之後,會得到 memory 的 address。
3 讀寫 view,在VB裡,可以使用 copy memory 來做讀寫的動作
4 UnmapViewOfFile 把 view 給關起來。當程式要結束的時候該做的事。
5 CloseHandle 把 FileMapping 給釋放掉,也是當程式結束,或不需要 share memory 的時候該做的事。免得系統的memory被吃光了也找不到兇手。

按照 MSDN 的介紹,寫了一個程式,可以CreateFileMapping,也可以OpenFileMapping。
我定義,執行 CreateFileMapping 那一個叫做 Server,執行OpenFileMapping 的叫做 Client。
當程式執行之後,可以執行兩次,就會有兩個程式。
兩個都可以當 Server (CreateFileMapping),而且名字可以一樣,這樣就可以溝通了。
當然也可以一個當 Server,一個當 Client。可以兩個都當 Server 的原因,我推測是因為只 share memory 的關係。
Share file 可能就不可以兩個都當 server。這個就不去實驗了,因為目前只關心 share memory。
同時兩個程式以上溝通也可以。只要多開幾次程式,而且有一個人當 Server 即可。感覺很方便。

這個程式只 share 32 byte 的 memory,所以只能傳遞比這個小的 message。
若是想要實作一個新的 protocol 來傳遞大 message 也行。
這個樣子的特性,讓我想到電路傳輸的特性,應該可以用來模擬CDMA, TDMA, 網路上的 CSMA/CA, CSMA/CD 的行為。
也可以用來模擬SECS I 或 HSMS 的傳送,對於學習上有相當幫助。
但是更有幫助的,當然是在這一層上面,支援更高一點的 protocol,做異質轉換。
或是建立新的 protocol,為自己的程式量身打造一個小而快的溝通管道。

雖然這種方式,已經不是新聞了,也一定有一堆的研究,但是如此就可以讓位在同樣 server 的 EAP 有個免費、簡單的管道互相溝通。
接下來的工作,是設計一個新的 protocol 來研究通訊模式嗎?
還是當做 adapter 接收現有的 protocol 如 SECS2呢?
都是一個學習的方向。
還有,若是對於在 hub 內資料如何傳送有了解的話,就可以設計一個比較複雜的 protocol 以提供穩定的溝通環境。
當然,不是只有這個 file mapping 可以用而已,還有其他的方式,也需多了解。例如 platform independent 的方法,
或是跨電腦的溝通,也是將來應該要學習的方向。

[1] http://msdn.microsoft.com/library/default.asp?url=/library/en-us/memory/base/sharing_files_and_memory.asp

本文授權為 CC

code in Module1.bas
==================================================
Attribute VB_Name = "Module1"
Public Declare Function CreateFileMapping Lib "kernel32" Alias "CreateFileMappingA" _
(ByVal hFile As Long, _
       lpFileMappingAttributes As Any, _
ByVal flProtect As Long, _
ByVal dwMaximumSizeHigh As Long, _
ByVal dwMaximumSizeLow As Long, _
ByVal lpName As String) As Long

Public Const INVALID_HANDLE_VALUE As Long = -1

Public Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type

Public Const PAGE_READ_WRITE As Long = 4

'===========================================================================================
Public Declare Function MapViewOfFile Lib "kernel32" _
(ByVal hFileMappingObject As Long, _
ByVal dwDesiredAccess As Long, _
ByVal dwFileOffsetHigh As Long, _
ByVal dwFileOffsetLow As Long, _
ByVal dwNumberOfByteToMap As Long) As Long

Public Const FILE_MAP_ALL_ACCESS = 983071
'==========================================================================================
Public Declare Function UnmapViewOfFile Lib "kernel32" (lpBaseAddress As Any) As Long


'==========================================================================================
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(pvDst As Any, pvSrc As Any, ByVal LengthInByte As Long)

'==========================================================================================
Public Declare Function GetLastError Lib "kernel32" () As Long
'==========================================================================================
Public Declare Function OpenFileMapping Lib "kernel32" Alias "OpenFileMappingA" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal lpName As String) As Long
'==========================================================================================
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
'==========================================================================================
Public Const ERROR_ALREADY_EXISTS = 183&
'==========================================================================================
'Public Const FILE_MAP_ALL_ACCESS = SECTION_ALL_ACCESS
'Public Const SECTION_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED Or SECTION_QUERY Or SECTION_MAP_WRITE Or SECTION_MAP_READ Or SECTION_MAP_EXECUTE Or SECTION_EXTEND_SIZE
'Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
'Public Const SECTION_QUERY = &H1
'Public Const SECTION_MAP_WRITE = &H2
'Public Const SECTION_MAP_READ = &H4
'Public Const SECTION_MAP_EXECUTE = &H8
'Public Const SECTION_EXTEND_SIZE = &H10

==================================================
code in Module1.bas complete


code in form1.frm
==================================================
VERSION 5.00
Begin VB.Form Form1
   Caption         =   "Server"
   ClientHeight    =   3090
   ClientLeft      =   60
   ClientTop       =   450
   ClientWidth     =   4680
   LinkTopic       =   "Form1"
   ScaleHeight     =   3090
   ScaleWidth      =   4680
   StartUpPosition =   3  'Windows Default
   Begin VB.CommandButton Command4
      Caption         =   "Connect Share"
      Height          =   495
      Left            =   3480
      TabIndex        =   4
      Top             =   720
      Width           =   1095
   End
   Begin VB.CommandButton Command3
      Caption         =   "change value"
      Height          =   495
      Left            =   3480
      TabIndex        =   3
      Top             =   1920
      Width           =   1095
   End
   Begin VB.TextBox Text1
      Height          =   1215
      Left            =   360
      MultiLine       =   -1  'True
      TabIndex        =   2
      Text            =   "Form1.frx":0000
      Top             =   360
      Width           =   2535
   End
   Begin VB.CommandButton Command2
      Caption         =   "stop monitor"
      Height          =   495
      Left            =   3480
      TabIndex        =   1
      Top             =   1320
      Width           =   1095
   End
   Begin VB.Timer Timer1
      Left            =   1680
      Top             =   2160
   End
   Begin VB.CommandButton Command1
      Caption         =   "Create Share"
      Height          =   495
      Left            =   3480
      TabIndex        =   0
      Top             =   120
      Width           =   1095
   End
End
Attribute VB_Name = "Form1"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Dim m_handle As Long
Dim BaseAddress As Long
Dim ShareMemoID As String



Private Sub Command1_Click()
    Form1.Caption = "Server"
    Dim ERROR_CODE As Long
    Dim ATTS As SECURITY_ATTRIBUTES
   
    If ShareMemoID = "" Then
        ShareMemoID = "ShareMemoTest"
    End If
    ShareMemoID = InputBox("Input ShareMemoryID", "ShareMemoryID", ShareMemoID)
    If ShareMemoID = "" Then
        MsgBox "share memory id can't be null string"
        Exit Sub
    End If
   
    m_handle = CreateFileMapping(INVALID_HANDLE_VALUE, ATTS, PAGE_READ_WRITE, 0, 64, ShareMemoID)

    ERROR_CODE = GetLastError()
    If ERROR_CODE <> 0 Then
        MsgBox "some error"
        Exit Sub
    End If

    If m_handle = 0 Then
        MsgBox "create share memory failed"
    Else
        BaseAddress = MapViewOfFile(m_handle, FILE_MAP_ALL_ACCESS, 0, 0, 0)
        If GetLastError() <> 0 Then
            MsgBox "some error"
            Exit Sub
        End If
    End If
   
    Timer1.Enabled = True
    Timer1.Interval = 500
   
    Text1.Text = ""
End Sub

Private Sub Command2_Click()
Timer1.Enabled = False
End Sub

Private Sub Command3_Click()
    Dim s(31) As Byte
    Dim i As Integer
    Message = InputBox("message")
    If Len(Message) = 0 Then
        MsgBox "input is not valid"
        Exit Sub
    End If
    For i = 0 To Len(Message) - 1
        s(i) = Asc(Mid(Message, i + 1, 1))
    Next
    CopyMemory ByVal BaseAddress, s(0), 32
End Sub

Private Sub Command4_Click()
    Form1.Caption = "client"
    If ShareMemoID = "" Then
        ShareMemoID = "ShareMemoTest"
    End If

    ShareMemoID = InputBox("Input ShareMemoryID", "ShareMemoryID", ShareMemoID)
    If ShareMemoID = "" Then
        MsgBox "share memory id can't be null string"
        Exit Sub
    End If
   
    m_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, 0, ShareMemoID)

    If GetLastError() <> 0 Then
        MsgBox "some error"
    End If

    If m_handle = 0 Then
        MsgBox "open share memory failed"
        Timer1.Enabled = False
    Else
        BaseAddress = MapViewOfFile(m_handle, FILE_MAP_ALL_ACCESS, 0, 0, 0)
        'MsgBox "m_handle=" & m_handle & " Server_map=" & Server_map
        If GetLastError() <> 0 Then
            MsgBox "some error"
            Exit Sub
        End If
        If BaseAddress = 0 Then
            MsgBox "BaseAddress can't get"
            Exit Sub
        End If
        Timer1.Enabled = True
        Timer1.Interval = 500
       
        Text1.Text = ""
    End If

End Sub

Private Sub Form_Load()
Message = ""
Form1.Caption = "Not connected"
End Sub

Private Sub Form_Unload(Cancel As Integer)
    Timer1.Enabled = False
    If BaseAddress <> 0 Then
        UnmapViewOfFile BaseAddress
    End If
    If m_handle <> 0 Then
        CloseHandle m_handle
    End If
End Sub

Private Sub Timer1_Timer()
    Dim m(31) As Byte
    Dim i As Integer
    Dim msg As String

    Text1.Text = ShareMemoID & " : " & BaseAddress
    CopyMemory m(0), ByVal BaseAddress, 32
   
    For i = 0 To 31
        msg = msg & Chr(m(i))
    Next
    Text1.Text = Text1.Text & vbNewLine & msg
End Sub
==================================================
code in form1.frm complete
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 betaparticle 的頭像
    betaparticle

    betaparticle的部落格

    betaparticle 發表在 痞客邦 留言(0) 人氣()