共享内存可以被描述成内存一个区域(段)的映射,这个区域可以被更多的进程所共享。这是IPC机制中最快的一种形式,因为它不需要中间环节,而是把信息直接从一个内存段映射到调用进程的地址空间。 一个段可以直接由一个进程创建,随后,可以有任意多的进程对其读和写。但是,一旦内存被共享之后,对共享内存的访问同步需要由其他 IPC 机制,例如消息队列来实现。
包含文件
1、msg.c
2、msg.h
3、sharemem.c
4、sharemem.h
5、thread.c
本例在上一篇的基础上修改,1和2两个源文件未作任何改动
源文件3 sharemem.c如下:
#include
#include
#include
#include
#include
#include
#include "sharemem.h"
#define __DEBUG
#ifdef __DEBUG
#define DBG(fmt,args...) fprintf(stdout, fmt, ##args)
#else
#define DBG(fmt,args...)
#endif
#define ERR(fmt,args...) fprintf(stderr, fmt, ##args)
static int g_mid;
/*共享内存初始化*/
int ShareMemInit(int key)
{
g_mid = shmget(key,MEM_SIZE,IPC_CREAT | 0660);
if(g_mid < 0 ){
g_mid = shmget(key, 0, 0);
}
DBG("shared memory id:%d\n",g_mid);
if(g_mid < 0 )
return -1;
return 0;
}
/*从共享内存中指定的偏移量处读取数据*/
void ShareMemRead(int offset,void *buf,int length)
{
char *pSrc = shmat(g_mid,0,0);
if(pSrc == NULL)
return;
memcpy(buf,pSrc+offset,length);
shmdt(pSrc);
}
/*从共享内存中指定的偏移量处写数据*/
void ShareMemWrite(int offset,void *buf,int length)
{
char *pDst = shmat(g_mid,0,0);
if(pDst == NULL)
return;
memcpy(pDst+offset,buf,length);
shmdt(pDst);
}
#ifndef _SHARE_MEM_H_
#define _SHARE_MEM_H_
#define MEM_KEY 0x1111
/*共享内存大小*/
#define MEM_SIZE 1024*5
int ShareMemInit(int key);
void ShareMemRead(int offset, void *buf, int length);
void ShareMemWrite(int offset, void *buf, int length);
#endif
/*
共享内存示例,它允许两个不相干的进程共享同一片内存,它是进程通信中传达大量数据的有效方法
但是共享内存并无自动的机制可以阻止第二个进程开始对他进行读取,对共享内存的同步机制必须由程序员来负责
这里通过消息队列来告知对方,可以读内存
本例在上一篇的基础上修改
*/
#include
#include
#include
#include
#include
#include
#include "msg.h"
#include "sharemem.h"
#define __DEBUG
#ifdef __DEBUG
#define DBG(fmt,args...) fprintf(stdout, fmt, ##args)
#else
#define DBG(fmt,args...)
#endif
#define ERR(fmt,args...) fprintf(stderr, fmt, ##args)
static int isThreadQuit = 0;
int gQid;//消息队列id
int gMyProcId = MSG_TYPE_MSG1;
void SetXxThreadQuit()
{
/*quit*/
isThreadQuit = 1;
}
void *XxManageThread(void *arg)
{
char *cmd = (char*)arg;
DBG("arg value=%s\n",cmd);
static int i=0;
while(isThreadQuit==0){
MSG_BUF msg;
char buf[5]={0x01,0x02,0x03,0x04,0x00};
memset(&msg,0,sizeof(MSG_BUF));
msg.Des = MSG_TYPE_MSG1;
msg.Src = gMyProcId;
msg.cmd = sizeof(buf); //消息队列中存放共享内存的可读数据长
buf[4]=i++; //对共享内存做一些修改
ShareMemWrite(0,buf,sizeof(buf));//写共享内存
msgsnd(gQid,(void*)&msg,sizeof(MSG_BUF)-sizeof(long),0);//通知对方读共享内存
DBG("write shm len = %d\n",msg.cmd);
sleep(1);
}
/*arg是将指针带进来,cmd则相反,或者设置 NULL*/
pthread_exit(cmd);
//pthread_exit(NULL);
}
void *XxManageThreadMutex(void *arg)
{
char *cmd = (char*)arg;
DBG("arg value=%s\n",cmd);
while(isThreadQuit==0){
MSG_BUF msg;
char buf[10];
int len;
memset(&msg,0,sizeof(MSG_BUF));
int ret = msgrcv(gQid,(void*)&msg,sizeof(MSG_BUF)-sizeof(long),gMyProcId,0);
if(ret < 0){
ERR("Receive msg fail!!\n");
break;
}
len = msg.cmd;
ShareMemRead(0,buf,len);
DBG("read shm len = %d\n",len);
DBG("%02x %02x %02x %02x %02x\n",buf[0],buf[1],buf[2],buf[3],buf[4]);
}
/*arg是将指针带进来,cmd则相反,或者设置 NULL*/
pthread_exit(cmd);
//pthread_exit(NULL);
}
int XxManageThreadInit()
{
pthread_t tManageThread;
pthread_t tManageThreadMutex;
char *any="any value";
char *retn;
int ret;
/*
第二个参数是设置线程属性,一般很少用到(设置优先级等),第四个参数为传递到线程的指针,
可以为任何类型
*/
ret = pthread_create(&tManageThread,NULL,XxManageThread,"1 thread");
if(ret == -1){
/*成功返回0.失败返回-1*/
ERR("Ctreate Thread ERROR\n");
return -1;
}
ret = pthread_create(&tManageThreadMutex,NULL,XxManageThreadMutex,"2 thread");
if(ret == -1){
/*成功返回0.失败返回-1*/
ERR("Ctreate Thread ERROR\n");
return -1;
}
/*
设置线程退出时资源的清理方式,如果是detach,退出时会自动清理
如果是join,则要等待pthread_join调用时才会清理
*/
pthread_detach(tManageThread);
pthread_detach(tManageThreadMutex);
//pthread_join(tManageThread,retn);
//DBG("retn value=%s\n",retn);
return 0;
}
#define TEST_MAIN
#ifdef TEST_MAIN
int main()
{
printf("hello liuyu\n");
int count=3;
/*初始化消息队列*/
gQid = Msg_Init(MSG_KEY);
if(ShareMemInit(MEM_KEY) < 0)
exit(1);
if(XxManageThreadInit()==-1){
exit(1);
}
while(count--){
DBG("[0] main running\n");
sleep(2);
}
SetXxThreadQuit();
/*等待线程结束*/
sleep(1);
/*清理消息队列*/
Msg_Kill(gQid);
DBG("waitting thread exit...\n");
return 0;
}
#endif