进程间通信笔记(4)—SystemV 消息队列
2016-09-11 11:55
211 查看
1.概述
SystemV 消息队列使用消息队列标识符标识,这个标识好像链表中的头节点,包含了许多信息,当然最主要的还是指向数据节点的两个指针msg_first和
msg_last,分别表示消息队列中的第一个和最后一个消息节点。
2.消息队列函数
操作SystemV消息队列的函数。2.1 msgget函数
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgget(key_t key, int msgflg);
其中
key既可以是
IPC_PRIVATE,也可以是
ftok函数的返回值。当
key的值为
IPC_PRIVATE或者当前没有消息队列与给定
key相关联时,将创建一个新的消息队列。
msgflg指定获取消息队列时的权限组合:当它被指定
IPC_CREAT和
IPC_EXCL时且跟
key关联的消息队列已经存在,则
msgget调用失败且设置
errno=EEXIST
2.2 msgsnd函数
msgget打开一个消息队列后,我们使用msgsnd往其放一个消息,好像链表插入新节点。
#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
msqid是msgget返回的标识符
msgp是一个结构指针,它有一个模板:
struct msgbuf { long mtype; /* message type, must be > 0 */ char mtext[1]; /* message data */ };
不过一般情况下,应用通常使用自己定义的消息类型,消息内容也不仅仅局限于文本,因为对于
msgp来说,它只是一个指针而已。
2.3 msgrcv函数
从消息队列中读出一个消息。#include <sys/types.h> #include <sys/ipc.h> #include <sys/msg.h> ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
其中
msgp参数指定接收消息的存放位置,与
msgsnd一样,该指针指向紧挨在真正的消息数据之前返回的长整数类型字段。
msgsz指定了数据大小,不包含类型字段。
msgtyp指定读出消息的类型。
msgflg指定请求类型消息不在队列时怎么处理。
成功返回时,将返回接收消息中数据的字节数,不含消息类型的那几个字节。
3. System V消息队列编程
依然是实现简单生产者消费者模型,不同管道,某个进程往一个队列中写入一个消息之前,不求另一个某个进程正在等待该队列上的一个消息到达。数据结构定义
//msg.h #ifndef __MSG_H__ #define __MSG_H__ #define MAXSIZE 256 struct Message_ { long mtype; unsigned int mlength; char buff[MAXSIZE]; }; typedef struct Message_ Message; #endif
发送方(生产者)
//sysV_send.c #include <stdio.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #include <assert.h> #include <string.h> #include "msg.h" int main(int argc,char **argv) { const char * const pathname="/home/zhangxiao/zxtest/systemV/";//ftok所需的pathname int msqid; key_t key; int mflag; Message msg; //0600 拥有者拥有读写权限。 mflag=IPC_EXCL|IPC_CREAT|0600; key = ftok(pathname,1);//ftok 获取 key if(key<0) { fprintf(stderr, "ftok: %s\n", strerror(errno)); return -1; } msqid=msgget(key,mflag);//msgget函数调用 if((msqid < 0) && (errno!=EEXIST))//msgget失败且不是因为消息队列已经存在 { fprintf(stderr, "msgget: %s\n", strerror(errno)); return -1; } if(msqid < 0)//消息队列已经存在 { printf("debug...\r\n");//说明打开的消息队列已经存在 msqid=msgget(key,IPC_CREAT|0600);//将忽视IPC_CREAT关键字 if (msqid < 0) { fprintf(stderr, "msgget: %s\n", strerror(errno)); return -1; } } memset(&msg,0x00,sizeof(Message)); strcpy(msg.buff,"HelloWorld666"); msg.mlength=strlen(msg.buff); int i; for(i = 0;i < 3;i++ ) { msg.mtype=(i+1)*100; if(msgsnd(msqid,(void *)&msg,sizeof(Message),0)<0)//发送消息 { fprintf(stderr, "msgsnd: %s\n", strerror(errno)); return -1; } } return 0; }
接收方(消费者)
#include <stdio.h> #include <sys/ipc.h> #include <sys/msg.h> #include <errno.h> #include <assert.h> #include <string.h> #include "msg.h" int main(int argc,char **argv) { const char * const pathname="/home/zhangxiao/zxtest/systemV/"; int msqid; key_t key; key = ftok(pathname,1);//ftok 获取 key Message msg; ssize_t n; if(key<0) { fprintf(stderr, "ftok: %s\n", strerror(errno)); return -1; } msqid=msgget(key,IPC_CREAT);//将忽视IPC_CREAT关键字 if (msqid < 0) { fprintf(stderr, "msgget: %s\n", strerror(errno)); return -1; } memset(&msg,0x00,sizeof(Message)); int i; for(i=2;i>=0;i--) { n=msgrcv(msqid,&msg,sizeof(Message),(i+1)*100,0); printf("msgtype=%ld,message=%s\r\n",msg.mtype,msg.buff); } msgctl(msqid,IPC_RMID,0);//删除消息队列 return 0; }
Makefile
# Makefile PROGS =Send Recv CLEANFILES = core core.* *.core *.o temp.* *.out typescript* \ *.lc *.lh *.bsdi *.sparc *.uw all :${PROGS} CFLAGS+=-g LIBS+= Recv: sysV_recv.o @${CC} ${CFLAGS} ${LIBPATH} $^ -o $@ ${LIBS} @rm *.o Send: sysV_send.o @${CC} ${CFLAGS} ${LIBPATH} $^ -o $@ ${LIBS} @rm *.o clean: rm -f ${PROGS} ${CLEANFILES}
4.补充
终端可以使用ipcs等命令查看和操作systemV IPC对象。
相关文章推荐
- Linux进程间通信IPC学习笔记之消息队列(Posix)
- 笔记:进程间通信——消息传递(管道、FIFO、posix消息队列)
- 进程间通信学习笔记四(消息队列)
- linux 系统编程-学习笔记10--进程间通信--管道/FIFO/消息队列/
- Linux进程IPC浅析[进程间通信SystemV消息队列]
- LINUX学习笔记15——进程间通信4消息队列
- uc笔记09---进程通信,管道,进程间通信,共享内存,消息队列,信号量,IPC 命令
- 进程间通信笔记(3)—POSIX消息队列
- Linux进程间通信IPC学习笔记之消息队列(SVR4)
- 进程间通信学习笔记四(消息队列)
- Unix学习笔记——进程间通信之消息队列
- Linux进程间通信: 消息队列
- WM里蓝牙AVRCP的消息队列研究分析(研究ing,笔记)
- 使用微软消息队列实现C#进程间通信(一)
- Linux环境进程间通信(三)——消息队列
- [转]使用微软消息队列实现C#进程间通信
- IPC之 - 使用微软消息队列实现C#进程间通信
- 进程间通信--消息队列
- 使用微软消息队列实现C#进程间通信(转)
- UNIX环境下如何应用消息队列实现进程间通信