进程间通信之共享内存技术

共享内存的使用

共享内存定义—-摘自百度百科

共享内存指 (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偏移量上设置的值

猜你喜欢

转载自blog.csdn.net/sky619351517/article/details/77417617