共享内存的使用
共享内存定义—-摘自百度百科
共享内存指 (shared memory)在多处理器的计算机系统中,可以被不同中央处理器(CPU)访问的大容量内存。由于多个CPU需要快速访问存储器,这样就要对存储器进行缓存(Cache)。任何一个缓存的数据被更新后,由于其他处理器也可能要存取,共享内存就需要立即更新,否则不同的处理器可能用到不同的数据。共享内存是 Unix下的多进程之间的通信方法 ,这种方法通常用于一个程序的多进程间通信,实际上多个程序间也可以通过共享内存来传递信息。
共享内存的实现机制
共享内存主要是通过映射机制实现的。
Windows 下进程的地址空间在逻辑上是相互隔离的,但在物理上却是重叠的。所谓的重叠是指同一块内存区域可能被多个进程同时使用。当调用 CreateFileMapping 创建命名的内存映射文件对象时,Windows 即在物理内存申请一块指定大小的内存区域,返回文件映射对象的句柄 hMap。为了能够访问这块内存区域必须调用 MapViewOfFile 函数,促使 Windows 将此内存空间映射到进程的地址空间中。当在其他进程访问这块内存区域时,则必须使用OpenFileMapping 函数取得对象句柄 hMap,并调用 MapViewOfFile 函数得到此内存空间的一个映射。这样一来,系统就把同一块内存区域映射到了不同进程的地址空间中,从而达到共享内存的目的。
代码块
头文件SkyRamDrive.h
// SkyRamDrive.h: interface for the SkyRamDrive class.
#if !defined(SKY_RAM_DRIVE_H)
#define SKY_RAM_DRIVE_H
#include <stdio.h>
#define MAX_DATA_SIZE 50000 // Buffer size Settings for real-time data areas
#define MAX_STRUCT_NUM 25 // Buffer size Settings for ascending structure variables
#define MAX_STRUCT_NUM_DOWN 20 // The buffer size of the descending structure variable is set
#define SHM_SIZE 250000 // The size of the Shared memory area
struct StructDrive
{
int iVersion;
char chExistGetCmd;
char chGetCmd[ 200 ];
int iValue[MAX_DATA_SIZE] ;
double dValue[MAX_DATA_SIZE];
int iStructNum ;
char chStruct[ MAX_STRUCT_NUM ][ 200 ];
int iStructNumDown ;
char chStructDown[ MAX_STRUCT_NUM_DOWN ][ 200 ];
};
class SkyRamDrive
{
public:
SkyRamDrive() ;
virtual ~SkyRamDrive( );
bool CreateRam( int ramid );
bool bRam ;
int iRamid;
HANDLE hMapFile;
LPVOID lpMapAddress;
StructDrive * drive ;
void SetExit( );
void SetCmd( char * chCmd );
void GetCmd( char * chCmd );
bool GetExistCmd( ){
if( drive == NULL )
return false;
else
return ( drive->chExistGetCmd != 0 );
}
void SetValue( int id, int iValue ){ // Set the value of the data_area
if( drive == NULL ) return ;
drive->iValue[ id ] = iValue ;
}
void SetDoubleValue(int id, double dValue) { // Set the value of the float data_area
if (drive == NULL) return;
drive->dValue[id] = dValue;
}
int GetValue( int id ){ // Get the value of the data_area
if( drive == NULL ) return 0;
return drive->iValue[ id ];
}
double GetDoubleValue(int id) { // Get the value of the float data_area
if (drive == NULL) return 0;
return drive->dValue[id];
}
void SetStructNum( int iStructNum ){ // Set the number of ascending structure variables
if( drive == NULL ) return ;
drive->iStructNum = iStructNum ;
}
int GetStructNum( ){ // Get the number of ascending structure variables
if( drive == NULL ) return 0 ;
return drive->iStructNum;
}
void SetStruct( int iNum , char * chMsg );// Set the value of ascending structure variables
char * GetStruct( int iNum ){ return *( drive->chStruct + iNum ) ; }// Get the number of ascending structure variables
int GetStructNumDown( ){ return drive->iStructNumDown ; }// Get the number of structural variables
void SetStructNumDown( int iNum ){ drive->iStructNumDown = iNum ; }// Set the number of structural variables
char * GetStructDown( int iNum ){ return *( drive->chStructDown + iNum ); } // Get the value of structural variables
void SetStructDown( int iNum , char * chMsgDown ) // Set the value of structural variables
{
memset( drive->chStructDown[iNum], 0, 200 );
strcpy( *( drive->chStructDown + iNum ), chMsgDown );
}
void ClearCmdMark( ){ // The flag of the Clear command
if( drive == NULL )
return ;
else
drive->chExistGetCmd = 0 ;
}
char * GetCmdWithoutClearMark( ){ return drive->chGetCmd ;}
};
#endif
实现文件SkyRamDrive.h
/*
* SkyRamDrive.cpp: implementation of the SkyRamDrive class.
*/
#include "stdafx.h"
#include "SkyRamDrive.h"
/*
* Construction/Destruction
*/
SkyRamDrive::SkyRamDrive( )
{
int isize;
isize = sizeof( StructDrive );
drive = NULL ;
bRam = false ;
lpMapAddress = NULL ;
hMapFile = NULL ;
}
SkyRamDrive::~SkyRamDrive( )
{
if (lpMapAddress) UnmapViewOfFile(lpMapAddress);
if (hMapFile) CloseHandle(hMapFile);
}
bool SkyRamDrive::CreateRam( int ramid )
{
char chRamName[30] ;
sprintf( chRamName, "RAM%03d", ramid );
CString strRam;
strRam.Format(_T("RAM%03d"),ramid);
if ( lpMapAddress ) UnmapViewOfFile( lpMapAddress );
if ( hMapFile ) CloseHandle( hMapFile );
HANDLE hFile = (HANDLE) 0xFFFFFFFF ;
hMapFile = CreateFileMapping( hFile, NULL, PAGE_READWRITE, 0, SHM_SIZE, strRam );
if ( hMapFile == NULL ){
char chMsg[100];
strcpy( chMsg, "Shared memory mapping error, please contact the program supplier " );
::MessageBox( NULL, (LPCTSTR)chMsg , NULL, MB_OK );
lpMapAddress = NULL;
bRam = false ;
return false;
}
lpMapAddress = MapViewOfFile( hMapFile,FILE_MAP_ALL_ACCESS,0,0,0 );
drive = ( StructDrive * )lpMapAddress ;
bRam = true ;
drive->iVersion = 1 ;
iRamid = ramid ;
return true ;
}
void SkyRamDrive::SetCmd( char * chCmd )
{
memset( drive->chGetCmd, 0, 200 );
strcpy( drive->chGetCmd, chCmd );
drive->chExistGetCmd = 1 ;
}
void SkyRamDrive::GetCmd( char * chCmd )
{
strcpy( chCmd, drive->chGetCmd );
drive->chExistGetCmd = 0 ;
}
void SkyRamDrive::SetStruct( int iNum , char * chMsg )
{
if( drive == NULL ) return ;
memset( drive->chStruct[iNum], 0, 200 );
strcpy( drive->chStruct[iNum], chMsg );
}
void SkyRamDrive::SetExit( )
{
strcpy( drive->chGetCmd, "EXIT" );
drive->chExistGetCmd = 1 ;
}
该类的用法:
进程A:
1、首先定义一个类
SkyRamDrive ram;
2、创建共享内存
ram.CreateRam( 1 ); //创建1号共享内存
3、在指定偏移量上设置值
ram.SetValue( OFF_SET, VALUE ) ; // OFF_SET是1号共享内存的偏移量,VALUE是在1号共享内存区的OFF_SET偏移量上设置的值
进程B:
1、首先定义一个类
SkyRamDrive ram;
2、创建共享内存
ram.CreateRam( 1 ); //创建1号共享内存
3、在指定偏移量上设置值
VALUE=ram.GetValue( OFF_SET) ; // OFF_SET是1号共享内存的偏移量,VALUE是在1号共享内存区的OFF_SET偏移量上设置的值