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

应用级代码说话。操作共享内存,就和操作已知的内存一样(可以想象直接读写一个可知的结构体)。

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


 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值