Linux IPC共享内存(多进程通信)

1. ShareMem.h

#ifndef SHARE_MEM_H
#define SHARE_MEM_H

#include <sys/shm.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>


class CShareMem{
private:
	key_t m_key; //共享内存键值
	int m_iShmId; //共享内存ID
	void *m_pvAddr;	//共享内存的起始地址
	int m_iTotalSize; //共享内存总大小
	int m_iUsageSize; //共享内存已使用
	
	//描述:共享内存初始化
	int ShmInit();
	
	//描述:附加到共享内存指定地址
	//返回:成功返回附加的地址,否则为NULL
	void *ShmAtt(); 
	
	//描述:分离到共享内存指定地址
	//返回:成功返回0,否则为-1
	int ShmDat();
	
public:
	CShareMem(int iTotalSize);	
	
	~CShareMem();
	
	//描述:申请共享内存地址
	const char *NewShmAddr(int iAddrSize);
	
	//描述:删除共享内存地址
	int DelShmAddr();
};

//描述:共享内存初始化
//参数:@iTotalSize 共享内存大小
//返回:成功返回0,反之失败返回-1
int ShmInit(int iTotalSize);

//描述:分配共享内存
//参数:@iAddrSize 请求分配的共享内存大小
//返回:成功返回新内存地址,否则为NULL
const char *NewShmAddr(int iAddrSize);

//描述:释放共享内存
//返回:成功返回0,反之返回-1
int DelShmAddr();

#endif

2. ShareMem.cpp

#include <string.h>
#include "ShareMem.h"


CShareMem::CShareMem(int iTotalSize)
{
	m_iTotalSize = iTotalSize;
	m_iUsageSize = 0;
	m_key = 0x78746B6D; //"系统库映射"缩写字符,xtkm=0x78746B6D
	ShmInit();
	ShmAtt();
}	
	
CShareMem::~CShareMem()
{
	shmdt(m_pvAddr);
}

int CShareMem::ShmInit()
{
	//long page_size = sysconf(_SC_PAGESIZE);
	//int data_size =  (m_iMemTol + page_size - 1) & (~(page_size - 1));
	
    //printf("CShareMem::ShmInit(): System page size=%d, iMemTolSize=%d, Adjust iMemTolSize=%d.\n", page_size, m_iMemTol, page_size);
	//m_iMemTol = page_size;
	
	printf("ShmInit: m_iTotalSize(dec)=%d.\n", m_iTotalSize);
	
	if ((m_iShmId=shmget(m_key, m_iTotalSize, IPC_CREAT)) < 0)
	{
		if ((m_iShmId=shmget(m_key, m_iTotalSize, IPC_CREAT|IPC_EXCL|0666)) < 0)
			printf("CShareMem::ShmInit:shmget() %s\n", strerror(m_iShmId));
	}
	
	if (m_iShmId > 0)
		printf("CShareMem::ShmInit:shmget() key=0x%08x, ShmId=0x%08x\n", m_key, m_iShmId);
	
	return m_iShmId;  
}
}

//描述:附加到共享内存指定地址
//返回:成功返回附加的地址,否则为NULL
void *CShareMem::ShmAtt()
{
	m_pvAddr = shmat(m_iShmId, NULL, 0);
	if (m_pvAddr == NULL)
		printf("CShareMem::ShmAtt() m_pvAddr=NULL!\n");
	return m_pvAddr;
}

//描述:分离共享内存指定地址
//参数:@pvShmAddr 附加的共享内层地址
//返回:成功返回0,否则为-1
int CShareMem::ShmDat()
{
	return shmdt(m_pvAddr);
}
}

const char *CShareMem::NewShmAddr(int iNewSize)
{
	const char *pAddr = NULL;
	
	if (m_iUsageSize+iNewSize > m_iTotalSize)
	{
		printf("NewShmAddr: The length is too large, pAddr=%p, Offset=%d, iNewSize=%d!!!\n", pAddr, m_iUsageSize, iNewSize);
		return NULL;
	}
	
	pAddr = (char*)m_pvAddr + m_iUsageSize;
	printf("NewShmAddr: pAddr=%p, Offset=%d, iNewSize=%d\n", pAddr, m_iUsageSize, iNewSize);
	m_iUsageSize += iNewSize;
	return pAddr;
}


//描述:删除共享内存地址
int CShareMem::DelShmAddr()
{
	return shmctl(m_iShmId, IPC_RMID, 0);
}

//定义共享内存对象
static CShareMem *g_pCSM=NULL;

//描述:共享内存初始化
//参数:@iTotalSize 共享内存大小
//返回:成功返回0,反之失败返回-1
int ShmInit(int iTotalSize)
{
	if (g_pCSM == NULL)
	{
		if ((g_pCSM=new CShareMem(iTotalSize)) == NULL)
			return -1;
	}
	return 0;
}

//描述:分配共享内存
//参数:@iAddrSize 请求分配的共享内存大小
//返回:成功返回新内存地址,否则为NULL
const char *NewShmAddr(int iAddrSize)
{
	if (g_pCSM != NULL)
		return g_pCSM->NewShmAddr(iAddrSize);
	return NULL;
}

//描述:释放共享内存
//返回:成功返回0,反之返回-1
int DelShmAddr()
{
	if (g_pCSM != NULL)
	{
		if (g_pCSM->DelShmAddr() > 0)
		{
			delete g_pCSM;
			return 0;
		}
	}
	return -1;
}

3. main.cpp

#include <string.h>
#include "ShareMem.h"

#define SHARE_MEM_SIZE		(20*1024*1024)	//20M
#define SHARE_MEM_USAGE		(10*1024)		//10K

int main(int argc, char *argv[])
{
	const char *pvAddr0, *pvAddr1, *pvAddr2;
	int iCnt;
	int iRdWr;
	
	if (argc != 2)
		exit(0);
	
	iRdWr = atoi(argv[1]);
	printf("iRdWr = %d.\n", iRdWr);
	
	//1.共享内存初始化
	ShmInit(SHARE_MEM_SIZE);

	//2.申请共享内存1
	pvAddr0 = NewShmAddr(SHARE_MEM_USAGE);
	if (pvAddr0 == NULL)
		printf("pvAddr0=%p\n", pvAddr0);
	
	//3.申请共享内存2
	pvAddr1 = NewShmAddr(SHARE_MEM_USAGE);
	if (pvAddr1 == NULL)
		printf("pvAddr1=%p\n", pvAddr1);
	
	//4.申请共享内存3
	pvAddr2 = NewShmAddr(SHARE_MEM_USAGE);
	if (pvAddr2 == NULL)
		printf("pvAddr2=%p\n", pvAddr2);
	
	iCnt = 0;
	while(1)
	{
		if (iRdWr == 0)
		{
			sprintf((char*)pvAddr0, "hello world! iCnt=%d", iCnt++);
			printf("Write pvAddr0=%p, %s\n", pvAddr0, pvAddr0);
			
			sprintf((char*)pvAddr1, "hello world! iCnt=%d", iCnt++);
			printf("Write pvAddr1=%p, %s\n", pvAddr1, pvAddr1);
	
			sprintf((char*)pvAddr2, "hello world! iCnt=%d", iCnt++);
			printf("Write pvAddr2=%p, %s\n", pvAddr2, pvAddr2);
			
			sleep(1); //1s
		}
		else
		{
			printf("Read pvAddr0=%p, %s\n", pvAddr0, pvAddr0);
			
			printf("Read pvAddr1=%p, %s\n", pvAddr1, pvAddr1);
			
			printf("Read pvAddr2=%p, %s\n", pvAddr2, pvAddr2);
			
			usleep(500*1000); //500ms
		}
	}
	
	//4.释放共享内存
	DelShmAddr();
}

4. 编译

arm-linux-gnueabi-g++ ShareMem.cpp -o ShareMem

5. 测试

编译的可执行程序ShareMem通过传入不同的参数0(写)或1(读)控制;

进程1(写)

root@NXBB:/mnt/# ./ShareMem 0
iRdWr = 0.
ShmInit: m_iTotalSize(dec)=20971520.
NewShmAddr: pAddr=0xb5887000, Offset=0, iNewSize=10240
NewShmAddr: pAddr=0xb5889800, Offset=10240, iNewSize=10240
NewShmAddr: pAddr=0xb588c000, Offset=20480, iNewSize=10240
Write pvAddr0=0xb5887000, hello world! iCnt=0
Write pvAddr1=0xb5889800, hello world! iCnt=1
Write pvAddr2=0xb588c000, hello world! iCnt=2
Write pvAddr0=0xb5887000, hello world! iCnt=3
Write pvAddr1=0xb5889800, hello world! iCnt=4
Write pvAddr2=0xb588c000, hello world! iCnt=5

进程2(读)

root@NXBB:/mnt/# ./ShareMem 1
iRdWr = 1.
ShmInit: m_iTotalSize(dec)=20971520.
NewShmAddr: pAddr=0xb5832000, Offset=0, iNewSize=10240
NewShmAddr: pAddr=0xb5834800, Offset=10240, iNewSize=10240
NewShmAddr: pAddr=0xb5837000, Offset=20480, iNewSize=10240
Read pvAddr0=0xb5832000, hello world! iCnt=3
Read pvAddr1=0xb5834800, hello world! iCnt=4
Read pvAddr2=0xb5837000, hello world! iCnt=5
Read pvAddr0=0xb5832000, hello world! iCnt=3
Read pvAddr1=0xb5834800, hello world! iCnt=4
Read pvAddr2=0xb5837000, hello world! iCnt=5
Read pvAddr0=0xb5832000, hello world! iCnt=3
Read pvAddr1=0xb5834800, hello world! iCnt=4
Read pvAddr2=0xb5837000, hello world! iCnt=5

进程3(读)

root@NXBB:/mnt/# ./ShareMem 1
iRdWr = 1.
ShmInit: m_iTotalSize(dec)=20971520.
NewShmAddr: pAddr=0xb5832000, Offset=0, iNewSize=10240
NewShmAddr: pAddr=0xb5834800, Offset=10240, iNewSize=10240
NewShmAddr: pAddr=0xb5837000, Offset=20480, iNewSize=10240
Read pvAddr0=0xb5832000, hello world! iCnt=3
Read pvAddr1=0xb5834800, hello world! iCnt=4
Read pvAddr2=0xb5837000, hello world! iCnt=5
Read pvAddr0=0xb5832000, hello world! iCnt=3
Read pvAddr1=0xb5834800, hello world! iCnt=4
Read pvAddr2=0xb5837000, hello world! iCnt=5
Read pvAddr0=0xb5832000, hello world! iCnt=3
Read pvAddr1=0xb5834800, hello world! iCnt=4
Read pvAddr2=0xb5837000, hello world! iCnt=5

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值