共享内存操作类:
using
System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ShareMemLib
{
public class ShareMem
{
[DllImport( " user32.dll " , CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
[DllImport( " Kernel32.dll " , CharSet = CharSet.Auto)]
public static extern IntPtr CreateFileMapping( int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);
[DllImport( " Kernel32.dll " , CharSet = CharSet.Auto)]
public static extern IntPtr OpenFileMapping( int dwDesiredAccess,[MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);
[DllImport( " Kernel32.dll " , CharSet = CharSet.Auto)]
public static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
[DllImport( " Kernel32.dll " , CharSet = CharSet.Auto)]
public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);
[DllImport( " Kernel32.dll " , CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
[DllImport( " kernel32 " , EntryPoint = " GetLastError " )]
public static extern int GetLastError ();
const int ERROR_ALREADY_EXISTS = 183 ;
const int FILE_MAP_COPY = 0x0001 ;
const int FILE_MAP_WRITE = 0x0002 ;
const int FILE_MAP_READ = 0x0004 ;
const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004 ;
const int PAGE_READONLY = 0x02 ;
const int PAGE_READWRITE = 0x04 ;
const int PAGE_WRITECOPY = 0x08 ;
const int PAGE_EXECUTE = 0x10 ;
const int PAGE_EXECUTE_READ = 0x20 ;
const int PAGE_EXECUTE_READWRITE = 0x40 ;
const int SEC_COMMIT = 0x8000000 ;
const int SEC_IMAGE = 0x1000000 ;
const int SEC_NOCACHE = 0x10000000 ;
const int SEC_RESERVE = 0x4000000 ;
const int INVALID_HANDLE_VALUE = - 1 ;
IntPtr m_hSharedMemoryFile = IntPtr.Zero;
IntPtr m_pwData = IntPtr.Zero;
bool m_bAlreadyExist = false ;
bool m_bInit = false ;
long m_MemSize = 0 ;
public ShareMem()
{
}
~ ShareMem()
{
Close();
}
/// <summary>
/// 初始化共享内存
/// </summary>
/// <param name="strName"> 共享内存名称 </param>
/// <param name="lngSize"> 共享内存大小 </param>
/// <returns></returns>
public int Init( string strName, long lngSize)
{
if (lngSize <= 0 || lngSize > 0x00800000 ) lngSize = 0x00800000 ;
m_MemSize = lngSize;
if (strName.Length > 0 )
{
// 创建内存共享体(INVALID_HANDLE_VALUE)
m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, ( uint )PAGE_READWRITE, 0 , ( uint )lngSize, strName);
if (m_hSharedMemoryFile == IntPtr.Zero)
{
m_bAlreadyExist = false ;
m_bInit = false ;
return 2 ; // 创建共享体失败
}
else
{
if (GetLastError() == ERROR_ALREADY_EXISTS) // 已经创建
{
m_bAlreadyExist = true ;
}
else // 新创建
{
m_bAlreadyExist = false ;
}
}
// ---------------------------------------
// 创建内存映射
m_pwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_WRITE, 0 , 0 , ( uint )lngSize);
if (m_pwData == IntPtr.Zero)
{
m_bInit = false ;
CloseHandle(m_hSharedMemoryFile);
return 3 ; // 创建内存映射失败
}
else
{
m_bInit = true ;
if (m_bAlreadyExist == false )
{
// 初始化
}
}
// ----------------------------------------
}
else
{
return 1 ; // 参数错误
}
return 0 ; // 创建成功
}
/// <summary>
/// 关闭共享内存
/// </summary>
public void Close()
{
if (m_bInit)
{
UnmapViewOfFile(m_pwData);
CloseHandle(m_hSharedMemoryFile);
}
}
/// <summary>
/// 读数据
/// </summary>
/// <param name="bytData"> 数据 </param>
/// <param name="lngAddr"> 起始地址 </param>
/// <param name="lngSize"> 个数 </param>
/// <returns></returns>
public int Read( ref byte [] bytData, int lngAddr, int lngSize)
{
if (lngAddr + lngSize > m_MemSize) return 2 ; // 超出数据区
if (m_bInit)
{
Marshal.Copy(m_pwData, bytData, lngAddr, lngSize);
}
else
{
return 1 ; // 共享内存未初始化
}
return 0 ; // 读成功
}
/// <summary>
/// 写数据
/// </summary>
/// <param name="bytData"> 数据 </param>
/// <param name="lngAddr"> 起始地址 </param>
/// <param name="lngSize"> 个数 </param>
/// <returns></returns>
public int Write( byte [] bytData, int lngAddr, int lngSize)
{
if (lngAddr + lngSize > m_MemSize) return 2 ; // 超出数据区
if (m_bInit)
{
Marshal.Copy(bytData, lngAddr, m_pwData, lngSize);
}
else
{
return 1 ; // 共享内存未初始化
}
return 0 ; // 写成功
}
}
}
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
namespace ShareMemLib
{
public class ShareMem
{
[DllImport( " user32.dll " , CharSet = CharSet.Auto)]
public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, int wParam, IntPtr lParam);
[DllImport( " Kernel32.dll " , CharSet = CharSet.Auto)]
public static extern IntPtr CreateFileMapping( int hFile, IntPtr lpAttributes, uint flProtect, uint dwMaxSizeHi, uint dwMaxSizeLow, string lpName);
[DllImport( " Kernel32.dll " , CharSet = CharSet.Auto)]
public static extern IntPtr OpenFileMapping( int dwDesiredAccess,[MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, string lpName);
[DllImport( " Kernel32.dll " , CharSet = CharSet.Auto)]
public static extern IntPtr MapViewOfFile(IntPtr hFileMapping, uint dwDesiredAccess, uint dwFileOffsetHigh, uint dwFileOffsetLow, uint dwNumberOfBytesToMap);
[DllImport( " Kernel32.dll " , CharSet = CharSet.Auto)]
public static extern bool UnmapViewOfFile(IntPtr pvBaseAddress);
[DllImport( " Kernel32.dll " , CharSet = CharSet.Auto)]
public static extern bool CloseHandle(IntPtr handle);
[DllImport( " kernel32 " , EntryPoint = " GetLastError " )]
public static extern int GetLastError ();
const int ERROR_ALREADY_EXISTS = 183 ;
const int FILE_MAP_COPY = 0x0001 ;
const int FILE_MAP_WRITE = 0x0002 ;
const int FILE_MAP_READ = 0x0004 ;
const int FILE_MAP_ALL_ACCESS = 0x0002 | 0x0004 ;
const int PAGE_READONLY = 0x02 ;
const int PAGE_READWRITE = 0x04 ;
const int PAGE_WRITECOPY = 0x08 ;
const int PAGE_EXECUTE = 0x10 ;
const int PAGE_EXECUTE_READ = 0x20 ;
const int PAGE_EXECUTE_READWRITE = 0x40 ;
const int SEC_COMMIT = 0x8000000 ;
const int SEC_IMAGE = 0x1000000 ;
const int SEC_NOCACHE = 0x10000000 ;
const int SEC_RESERVE = 0x4000000 ;
const int INVALID_HANDLE_VALUE = - 1 ;
IntPtr m_hSharedMemoryFile = IntPtr.Zero;
IntPtr m_pwData = IntPtr.Zero;
bool m_bAlreadyExist = false ;
bool m_bInit = false ;
long m_MemSize = 0 ;
public ShareMem()
{
}
~ ShareMem()
{
Close();
}
/// <summary>
/// 初始化共享内存
/// </summary>
/// <param name="strName"> 共享内存名称 </param>
/// <param name="lngSize"> 共享内存大小 </param>
/// <returns></returns>
public int Init( string strName, long lngSize)
{
if (lngSize <= 0 || lngSize > 0x00800000 ) lngSize = 0x00800000 ;
m_MemSize = lngSize;
if (strName.Length > 0 )
{
// 创建内存共享体(INVALID_HANDLE_VALUE)
m_hSharedMemoryFile = CreateFileMapping(INVALID_HANDLE_VALUE, IntPtr.Zero, ( uint )PAGE_READWRITE, 0 , ( uint )lngSize, strName);
if (m_hSharedMemoryFile == IntPtr.Zero)
{
m_bAlreadyExist = false ;
m_bInit = false ;
return 2 ; // 创建共享体失败
}
else
{
if (GetLastError() == ERROR_ALREADY_EXISTS) // 已经创建
{
m_bAlreadyExist = true ;
}
else // 新创建
{
m_bAlreadyExist = false ;
}
}
// ---------------------------------------
// 创建内存映射
m_pwData = MapViewOfFile(m_hSharedMemoryFile, FILE_MAP_WRITE, 0 , 0 , ( uint )lngSize);
if (m_pwData == IntPtr.Zero)
{
m_bInit = false ;
CloseHandle(m_hSharedMemoryFile);
return 3 ; // 创建内存映射失败
}
else
{
m_bInit = true ;
if (m_bAlreadyExist == false )
{
// 初始化
}
}
// ----------------------------------------
}
else
{
return 1 ; // 参数错误
}
return 0 ; // 创建成功
}
/// <summary>
/// 关闭共享内存
/// </summary>
public void Close()
{
if (m_bInit)
{
UnmapViewOfFile(m_pwData);
CloseHandle(m_hSharedMemoryFile);
}
}
/// <summary>
/// 读数据
/// </summary>
/// <param name="bytData"> 数据 </param>
/// <param name="lngAddr"> 起始地址 </param>
/// <param name="lngSize"> 个数 </param>
/// <returns></returns>
public int Read( ref byte [] bytData, int lngAddr, int lngSize)
{
if (lngAddr + lngSize > m_MemSize) return 2 ; // 超出数据区
if (m_bInit)
{
Marshal.Copy(m_pwData, bytData, lngAddr, lngSize);
}
else
{
return 1 ; // 共享内存未初始化
}
return 0 ; // 读成功
}
/// <summary>
/// 写数据
/// </summary>
/// <param name="bytData"> 数据 </param>
/// <param name="lngAddr"> 起始地址 </param>
/// <param name="lngSize"> 个数 </param>
/// <returns></returns>
public int Write( byte [] bytData, int lngAddr, int lngSize)
{
if (lngAddr + lngSize > m_MemSize) return 2 ; // 超出数据区
if (m_bInit)
{
Marshal.Copy(bytData, lngAddr, m_pwData, lngSize);
}
else
{
return 1 ; // 共享内存未初始化
}
return 0 ; // 写成功
}
}
}
测试例程:
using
System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ShareMemLib;
namespace YFShareMem
{
public partial class frmShareMem : Form
{
ShareMem MemDB = new ShareMem();
public frmShareMem()
{
InitializeComponent();
}
private void btnOpen_Click( object sender, EventArgs e)
{
if (MemDB.Init( " YFMemTest " , 10240 ) != 0 )
{
// 初始化失败
MessageBox.Show( " 初始化失败 " );
}
else
{
btnOpen.Enabled = false ;
chkWrite.Enabled = true ;
tmrTime.Enabled = true ;
}
}
private void tmrTime_Tick( object sender, EventArgs e)
{
byte [] bytData = new byte [ 16 ];
int intRet = MemDB.Read( ref bytData, 0 , 16 );
lstData.Items.Clear();
if (intRet == 0 )
{
for ( int i = 0 ; i < 16 ; i ++ )
{
lstData.Items.Add(bytData[i].ToString());
}
if (chkWrite.Checked)
{
bytData[ 0 ] ++ ;
bytData[ 1 ] += 2 ;
if (bytData[ 0 ] > 200 ) bytData[ 0 ] = 0 ;
if (bytData[ 1 ] > 200 ) bytData[ 1 ] = 0 ;
MemDB.Write(bytData, 0 , 16 );
}
}
}
}
}
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ShareMemLib;
namespace YFShareMem
{
public partial class frmShareMem : Form
{
ShareMem MemDB = new ShareMem();
public frmShareMem()
{
InitializeComponent();
}
private void btnOpen_Click( object sender, EventArgs e)
{
if (MemDB.Init( " YFMemTest " , 10240 ) != 0 )
{
// 初始化失败
MessageBox.Show( " 初始化失败 " );
}
else
{
btnOpen.Enabled = false ;
chkWrite.Enabled = true ;
tmrTime.Enabled = true ;
}
}
private void tmrTime_Tick( object sender, EventArgs e)
{
byte [] bytData = new byte [ 16 ];
int intRet = MemDB.Read( ref bytData, 0 , 16 );
lstData.Items.Clear();
if (intRet == 0 )
{
for ( int i = 0 ; i < 16 ; i ++ )
{
lstData.Items.Add(bytData[i].ToString());
}
if (chkWrite.Checked)
{
bytData[ 0 ] ++ ;
bytData[ 1 ] += 2 ;
if (bytData[ 0 ] > 200 ) bytData[ 0 ] = 0 ;
if (bytData[ 1 ] > 200 ) bytData[ 1 ] = 0 ;
MemDB.Write(bytData, 0 , 16 );
}
}
}
}
}
首先还是定义非托管调用,如下:
const int INVALID_HANDLE_VALUE = - 1 ;
const int PAGE_READWRITE = 0x04 ;
//共享内存
[ DllImport ( "Kernel32.dll" , EntryPoint = "CreateFileMapping" )]
private static extern IntPtr CreateFileMapping ( IntPtr hFile , //HANDLE hFile,
UInt32 lpAttributes , //LPSECURITY_ATTRIBUTES lpAttributes, //0
UInt32 flProtect , //DWORD flProtect
UInt32 dwMaximumSizeHigh , //DWORD dwMaximumSizeHigh,
UInt32 dwMaximumSizeLow , //DWORD dwMaximumSizeLow,
string lpName //LPCTSTR lpName
);
[ DllImport ( "Kernel32.dll" , EntryPoint = "OpenFileMapping" )]
private static extern IntPtr OpenFileMapping (
UInt32 dwDesiredAccess , //DWORD dwDesiredAccess,
int bInheritHandle , //BOOL bInheritHandle,
string lpName //LPCTSTR lpName
);
const int FILE_MAP_ALL_ACCESS = 0x0002 ;
const int FILE_MAP_WRITE = 0x0002 ;
[ DllImport ( "Kernel32.dll" , EntryPoint = "MapViewOfFile" )]
private static extern IntPtr MapViewOfFile (
IntPtr hFileMappingObject , //HANDLE hFileMappingObject,
UInt32 dwDesiredAccess , //DWORD dwDesiredAccess
UInt32 dwFileOffsetHight , //DWORD dwFileOffsetHigh,
UInt32 dwFileOffsetLow , //DWORD dwFileOffsetLow,
UInt32 dwNumberOfBytesToMap //SIZE_T dwNumberOfBytesToMap
);
[ DllImport ( "Kernel32.dll" , EntryPoint = "UnmapViewOfFile" )]
private static extern int UnmapViewOfFile ( IntPtr lpBaseAddress );
[ DllImport ( "Kernel32.dll" , EntryPoint = "CloseHandle" )]
private static extern int CloseHandle ( IntPtr hObject );
然后分别在AB两个进程中定义如下两个信号量及相关变量;
private
Semaphore
m_Write
;
//可写的信号
private Semaphore m_Read ; //可读的信号
private IntPtr handle ; //文件句柄
private IntPtr addr ; //共享内存地址
uint mapLength ; //共享内存长
private Semaphore m_Read ; //可读的信号
private IntPtr handle ; //文件句柄
private IntPtr addr ; //共享内存地址
uint mapLength ; //共享内存长
定义这两个信号量是为读写互斥用的。
在A进程中创建共享内存:
m_Write
=
new
Semaphore
(
1
,
1
,
"WriteMap"
);
m_Read = new Semaphore ( 0 , 1 , "ReadMap" );
mapLength = 1024 ;
IntPtr hFile = new IntPtr ( INVALID_HANDLE_VALUE );
handle = CreateFileMapping ( hFile , 0 , PAGE_READWRITE , 0 , mapLength , "shareMemory" );
addr = MapViewOfFile ( handle , FILE_MAP_ALL_ACCESS , 0 , 0 , 0 );
m_Read = new Semaphore ( 0 , 1 , "ReadMap" );
mapLength = 1024 ;
IntPtr hFile = new IntPtr ( INVALID_HANDLE_VALUE );
handle = CreateFileMapping ( hFile , 0 , PAGE_READWRITE , 0 , mapLength , "shareMemory" );
addr = MapViewOfFile ( handle , FILE_MAP_ALL_ACCESS , 0 , 0 , 0 );
然后再向共享内存中写入数据:
m_Write
.
WaitOne
();
byte [] sendStr = Encoding . Default . GetBytes ( txtMsg . Text + '\0' );
//如果要是超长的话,应另外处理,最好是分配足够的内存
if ( sendStr . Length < mapLength )
Copy ( sendStr , addr );
m_Read . Release ();
byte [] sendStr = Encoding . Default . GetBytes ( txtMsg . Text + '\0' );
//如果要是超长的话,应另外处理,最好是分配足够的内存
if ( sendStr . Length < mapLength )
Copy ( sendStr , addr );
m_Read . Release ();
这是在一个单独的方法中实现的,可多次调用,但受信号量的控制。其中txtMsg是一个文本框控件,实际中可用任意字符串,加最后的'\0'是为了让在共享内存中的字符串有一个结束符,否则在内存中取出时是以'\0'为准的,就会出现取多的情况。
Copy方法的实现如下:
static
unsafe
void
Copy
(
byte
[]
byteSrc
,
IntPtr
dst
)
{
fixed ( byte * pSrc = byteSrc )
{
byte * pDst = ( byte *) dst ;
byte * psrc = pSrc ;
for ( int i = 0 ; i < byteSrc . Length ; i ++)
{
* pDst = * psrc ;
pDst ++;
psrc ++;
}
}
}
{
fixed ( byte * pSrc = byteSrc )
{
byte * pDst = ( byte *) dst ;
byte * psrc = pSrc ;
for ( int i = 0 ; i < byteSrc . Length ; i ++)
{
* pDst = * psrc ;
pDst ++;
psrc ++;
}
}
}
注意unsafe 关键字,在编译时一定要打开非安全代码开关。
最后不要忘了在A进程中关闭共享内存对象,以免内存泄露。
UnmapViewOfFile
(
addr
);
CloseHandle ( handle );
CloseHandle ( handle );
要在B进程中读取共享内存中的数据,首先要打开共享内存对象:
m_Write
=
Semaphore
.
OpenExisting
(
"WriteMap"
);
m_Read = Semaphore . OpenExisting ( "ReadMap" );
handle = OpenFileMapping ( 0x0002 , 0 , "shareMemory" );
m_Read = Semaphore . OpenExisting ( "ReadMap" );
handle = OpenFileMapping ( 0x0002 , 0 , "shareMemory" );
读取共享内存中的数据:
m_Read
.
WaitOne
();
string str = MapViewOfFile ( handle , FILE_MAP_ALL_ACCESS , 0 , 0 , 0 );
txtMsg . Text = str ;
m_Write . Release ();
string str = MapViewOfFile ( handle , FILE_MAP_ALL_ACCESS , 0 , 0 , 0 );
txtMsg . Text = str ;
m_Write . Release ();