您的位置:首页 > 运维架构 > Linux

Linux进程通讯之一:共享内存

2013-12-16 18:30 330 查看
应用级代码说话。操作共享内存,就和操作已知的内存一样(可以想象直接读写一个可知的结构体)。

本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;
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: