应用级代码说话。操作共享内存,就和操作已知的内存一样(可以想象直接读写一个可知的结构体)。
本demo参考了lgui中内存共享的代码。在lgui中,画笔/画板之类需要全局共用的都放在共享区。
在共享区内,每个结构体有自己的index方便读写。
demo分为server/client,直接在Linux下运行即可。
1 共同的代码
semaphore.h
#ifndef __SEMAPHORE_H__
#define __SEMAPHORE_H__
#include <sys/sem.h>
#ifdef __cplusplus
extern "C" {
#endif
union semun{
int val;
struct semid_ds* buf;
unsigned short int *array;
};
int sem_create(key_t sem_id);
void sem_lock(int sem_set_id);
void sem_unlock(int sem_set_id);
void sem_remove(int sem_set_id);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
semaphore.cpp
#include <sys/types.h>
#include "semaphore.h"
//create semaphore
int sem_create(key_t sem_id)
{
union semun sem_val;
int sem_set_id;
int rc;
sem_set_id=semget(sem_id,1,IPC_CREAT | 0600);
if(sem_set_id==-1)
{
return -1;
}
sem_val.val=1;
rc=semctl(sem_set_id,0,SETVAL,sem_val);
if(rc==-1)
{
return -1;
}
else
{
return sem_set_id;
}
}
//Lock
void sem_lock(int sem_set_id)
{
struct sembuf sem_op;
sem_op.sem_num =0;
sem_op.sem_op =-1;
sem_op.sem_flg =0;
semop(sem_set_id,&sem_op,1);
}
//unlock
void sem_unlock(int sem_set_id)
{
struct sembuf sem_op;
sem_op.sem_num =0;
sem_op.sem_op =1;
sem_op.sem_flg =0;
semop(sem_set_id,&sem_op,1);
}
//destroy
void sem_remove(int sem_set_id)
{
semctl(sem_set_id,0,IPC_RMID);
}
shmem.h
#ifndef __SHMEM_H__
#define __SHMEM_H__
#ifdef __cplusplus
extern "C" {
#endif
#define SHMEM_SIZE 1024*1024
#define SHMEM_CGI_SIZE 4*1024
//index 4k
#define SHMEM_CGI_OFFSET_INDEX 0
#define SHMEM_CGI_OFFSET_0 SHMEM_CGI_SIZE
#define SHMEM_CGI_OFFSET_1 SHMEM_CGI_SIZE + SHMEM_CGI_SIZE
//cgi为client
#define SHMEM_SERVER 1
#define SHMEM_CLIENT 0
#define SHMEM_CS SHMEM_SERVER
typedef int BOOL;
typedef void *PVOID,*LPVOID;
typedef PVOID HVODIOBJ;
typedef PVOID HCGI;
typedef struct _CgiCmdTag
{
int cmdindex;
int cmd0;
int cmd1;
int cmd2;
int cmd3;
int cmdsize;
char cmdname[20];
}CgiCmdTag,*pCgiCmdTag;
BOOL InitShareMemServer();
BOOL InitShareMemClient();
void UnInitShareMem(int cs);
int shm_read(char* pDest, int iOffset, int iLen);
int shm_write(char* pSource, int iOffset, int iLen);
char* GetShmAddr();
void LockShMem();
void UnLockShMem();
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif
shmem.cpp
#include "semaphore.h"
#include "shmem.h"
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <sys/shm.h>
#define SEM_ID 250
#define SHMEM_ID 100
//#define SHMEM_FLAG IPC_CREAT | 0600
#define SHMEM_FLAG IPC_CREAT | 0666
int sem_set_id;
int shm_id;
char* pShmCgi;
char* GetShmAddr()
{
return pShmCgi;
}
int shm_read(char* pDest, int iOffset, int iLen)
{
memcpy(pDest,pShmCgi+iOffset,iLen);
return 0;
}
int shm_write(char* pSource, int iOffset, int iLen)
{
memcpy(pShmCgi+iOffset,pSource,iLen);
return 0;
}
BOOL InitShareMemServer()
{
struct shmid_ds shm_desc;
sem_set_id=sem_create(SEM_ID);
if(sem_set_id == -1)
{
return false;
}
shm_id = shmget(SHMEM_ID,SHMEM_SIZE,SHMEM_FLAG);
if(shm_id == -1)
{
sem_remove(sem_set_id);
return false;
}
pShmCgi = (char*)shmat(shm_id,NULL,0);
if(!pShmCgi)
{
sem_remove(sem_set_id);
shmctl(shm_id,IPC_RMID,&shm_desc);
return false;
}
return true;
}
BOOL InitShareMemClient()
{
struct shmid_ds shm_desc;
shm_id = shmget(SHMEM_ID,SHMEM_SIZE,SHMEM_FLAG);
if(shm_id == -1)
{
sem_remove(sem_set_id);
return false;
}
pShmCgi = (char*)shmat(shm_id,NULL,0);
if(!pShmCgi)
{
sem_remove(sem_set_id);
shmctl(shm_id,IPC_RMID,&shm_desc);
return false;
}
return true;
}
void UnInitShareMem(int cs)
{
struct shmid_ds shm_desc;
if(cs)
{
sem_remove(sem_set_id);
shmdt(pShmCgi);
shmctl(shm_id,IPC_RMID,&shm_desc);
}
else
{
shmdt(pShmCgi);
}
}
void LockShMem()
{
sem_lock(sem_set_id);
}
void UnLockShMem()
{
sem_unlock(sem_set_id);
}
2 client端
//cgi client
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <malloc.h>
#include "semaphore.h"
#include "shmem.h"
//g++ cgibin_client.cpp semaphore.cpp shmem.cpp -o client.bin
//HCGI :CreateCgiObject()中的shm可能存储不同的数据结构
HCGI GetCgiObject(int index)
{
int CgiOffset;
int CgiIndex;
char *pname;
char* pShmAddr;
CgiCmdTag *pCgiCmd;
pShmAddr = GetShmAddr();
if(!pShmAddr)
{
return NULL;
}
CgiOffset = *(((int*)(pShmAddr+SHMEM_CGI_OFFSET_INDEX))+index);
//get cgi index
shm_read((char*)(&CgiIndex),CgiOffset,sizeof(int));
pCgiCmd = (CgiCmdTag*)malloc(sizeof(CgiCmdTag));
if(!pCgiCmd)
{
return NULL;
}
shm_read((char*)pCgiCmd,CgiOffset,sizeof(CgiCmdTag));
return (HCGI)pCgiCmd;
}
int main(int argc, char **argv)
{
CgiCmdTag *pCgiCmd = NULL;
InitShareMemClient();
while(1)
{
for(int i=0;i<2;i++)
{
pCgiCmd = (CgiCmdTag*)GetCgiObject(i);
printf("cgicmd[%d]:\n",i);
printf("cmdindex :0x%04x\n",pCgiCmd->cmdindex);
printf("cmd0 :0x%04x\n",pCgiCmd->cmd0);
printf("cmd1 :0x%04x\n",pCgiCmd->cmd1);
printf("cmd2 :0x%04x\n",pCgiCmd->cmd2);
printf("cmd3 :0x%04x\n",pCgiCmd->cmd3);
printf("cmdsize :0x%04x\n",pCgiCmd->cmdsize);
printf("cmdname :%s\n",pCgiCmd->cmdname);
printf("cgicmd[%d] print ok:\n\n",i);
sleep(1);
}
}
UnInitShareMem(SHMEM_CLIENT);
printf( "UnInitShareMem ok\n" );
return 0;
}
3 server端
//cgi server
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <malloc.h>
#include "semaphore.h"
#include "shmem.h"
//g++ cgibin_server.cpp semaphore.cpp shmem.cpp -o server.bin
BOOL CreateCgiObject()
{
char* pShmAddr;
int* pIdxAddr;
int CgiOffset;
CgiCmdTag CgiCmd0;
CgiCmdTag CgiCmd1;
pShmAddr = GetShmAddr();
if(!pShmAddr)
{
return false;
}
pIdxAddr = (int*)(pShmAddr+SHMEM_CGI_OFFSET_INDEX);
//CgiCmd0
CgiOffset = SHMEM_CGI_OFFSET_0;
CgiCmd0.cmdindex = 0x0000;
CgiCmd0.cmd0 = 0x8000;
CgiCmd0.cmd1 = 0x8001;
CgiCmd0.cmd2 = 0x8002;
CgiCmd0.cmd3 = 0x8003;
CgiCmd0.cmdsize = 0x8004;
memcpy(CgiCmd0.cmdname,"CgiCmd0",sizeof(CgiCmd0.cmdname));
memcpy((void*)(pShmAddr+CgiOffset),&CgiCmd0,sizeof(CgiCmd0));
*(pIdxAddr+CgiCmd0.cmdindex) = CgiOffset;
//CgiCmd1
CgiOffset = SHMEM_CGI_OFFSET_1;
CgiCmd1.cmdindex = 0x0001;
CgiCmd1.cmd0 = 0x9000;
CgiCmd1.cmd1 = 0x9001;
CgiCmd1.cmd2 = 0x9002;
CgiCmd1.cmd3 = 0x9003;
CgiCmd1.cmdsize = 0x9004;
memcpy(CgiCmd1.cmdname,"CgiCmd1",sizeof(CgiCmd0.cmdname));
memcpy((void*)(pShmAddr+CgiOffset),&CgiCmd1,sizeof(CgiCmd1));
*(pIdxAddr+CgiCmd1.cmdindex) = CgiOffset;
CgiOffset = CgiOffset + SHMEM_CGI_SIZE;
return true;
}
//HCGI :CreateCgiObject()中的shm可能存储不同的数据结构
HCGI GetCgiObject(int index)
{
int CgiOffset;
int CgiIndex;
char *pname;
char* pShmAddr;
CgiCmdTag *pCgiCmd;
pShmAddr = GetShmAddr();
if(!pShmAddr)
{
return NULL;
}
CgiOffset = *(((int*)(pShmAddr+SHMEM_CGI_OFFSET_INDEX))+index);
//get cgi index
shm_read((char*)(&CgiIndex),CgiOffset,sizeof(int));
pCgiCmd = (CgiCmdTag*)malloc(sizeof(CgiCmdTag));
if(!pCgiCmd)
{
return NULL;
}
shm_read((char*)pCgiCmd,CgiOffset,sizeof(CgiCmdTag));
return (HCGI)pCgiCmd;
}
int SetCgiObject(int index)
{
CgiCmdTag *pCgiCmd = NULL;
pCgiCmd = (CgiCmdTag*)GetCgiObject(index);
char* pShmAddr;
pShmAddr = GetShmAddr();
if(index==0)
{
pCgiCmd->cmdindex = 0;
pCgiCmd->cmd0 = 0xa000;
pCgiCmd->cmd1 = 0xa001;
pCgiCmd->cmd2 = 0xa002;
pCgiCmd->cmd3 = 0xa003;
//pCgiCmd->cmdsize = 0xa000 + 1<<(index+1)+4;
shm_write((char*)pCgiCmd,SHMEM_CGI_OFFSET_0,sizeof(CgiCmdTag));
}
if(index==1)
{
pCgiCmd->cmdindex = 1;
pCgiCmd->cmd0 = 0xb000;
pCgiCmd->cmd1 = 0xb001;
pCgiCmd->cmd2 = 0xb002;
pCgiCmd->cmd3 = 0xb003;
//pCgiCmd->cmdsize = 0xb000 + 1<<(index+1)+4;
memcpy(pCgiCmd->cmdname,"CgiCmd1_Modify",sizeof(pCgiCmd->cmdname));
shm_write((char*)pCgiCmd,SHMEM_CGI_OFFSET_1,sizeof(CgiCmdTag));
}
}
int main(int argc, char **argv)
{
InitShareMemServer();
CreateCgiObject();
printf("CreateCgiObject ok\n");
sleep(10);
SetCgiObject(0);
SetCgiObject(1);
printf("SetCgiObject ok\n");
sleep(20);
UnInitShareMem(SHMEM_SERVER);
printf( "UnInitShareMem ok\n" );
return 0;
}