消息队列
- 消息队列实质为内核地址空间中的内部链表,在Linux中各个进程之间传递内容
- 消息顺序的发送到队列中,以不同的方式从队列中获取,消息队列可以用IPC标识符唯一地进行标识。
- 消息队列由IPC标识符进行区别,队列与队列之间是相互独立的。
- 每个消息队列中的消息,又构成一个独立的链表。
声明
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
/*
用于创建一个新的消息队列,或者访问一个现有的队列。
-key:为键值,由ftok()函数生成。
-msgflg:
IPC_CREAT:内核中不存在该队列,则创建它;
IPC_EXCL:当与IPC_CREAT一起使用时,如果队列早已存在则将出错。
*/
int msgget ( key_t key ,int msgflg);
/*
用于向一个队列传递消息。
-msqid:队列标识符,是由前面调用msgget()获得的返回值。
-msgp:指向消息缓冲区。
-msgsz:消息缓冲区的大小。
-msgflag:
可以设置为0,表示忽略
可以设置为IPC_NOWAIT:如果消息队列已经满了,则不会写入消息队列。若没有写,则调用进程将被中断,直到可以写消息为止。
*/
int msgsnd (int msqid, const void *msgp, size_t msgsz , int msgflag);
/*
用于在消息队列上执行接收操作
-msqid:队列标识符,是由前面调用msgget()获得的返回值。
-msgp:指向消息缓冲区。
-msgsz:消息缓冲区的大小。
-mtype:指定要从队列中获取的消息类型。
-msgflag:
若设置为IPC_NOWAIT作为一个标志传送给该函数,而队列没有消息,则会返回ENOMSG。否则进程将被阻塞。
如果在等待消息的时候队列被删除,则返回EIDRM。
如果进程阻塞并等待消息的到来时捕获到了一个信号,则返回EINTR。
*/
int msgrcv (int msqid, void *msgp, size_t msgsz , long msgtyp ,int msgflag);
/*
向内核发送一个cmd命令,内核根据此来判断进行何种操作。
-msqid:队列标识符,是由前面调用msgget()获得的返回值。
-cmd:
IPC_STAT:把msgid_ds结构中的数据设置为消息队列的当前关联值,即用消息队列的当前关联值覆盖msgid_ds的值。
IPC_SET:把消息列队的当前关联值设置为msgid_ds结构中给出的值
IPC_RMID:删除消息队列
*/
int msgclt (int msqid, int cmd, struct msqid_ds *buf);
struct msgbuf
{
__syscall_slong_t mtype; /* type of received/sent message */
char mtext[1]; /* text of the message */
};
例子
发端:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <cstring>
#include <sys/msg.h>
#include <iostream>
using namespace std;
struct msgbuf{
int mtype;
char mtext[10];
};
int main(){
struct msgbuf data;
string buff ;
int msgid = msgget((key_t)123 ,0666|IPC_CREAT);
if( msgid == -1 ){
printf("msgid error!");
return ;
}
while(true){
cin >> buff;
data.msg_type = 2;
strcpy(data.text ,buff.c_str());
if( msgsnd(msgid , (void *)&data,512,0) != -1)
printf("send succ");
else break;
buff ="";
}
return 0;
}
收端:
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <cstring>
#include <sys/msg.h>
#include <iostream>
using namespace std;
struct msgbuf{
int mtype;
char mtext[10];
};
int main(){
struct msgbuf data;
string buff ;
int msgid = msgget((key_t)123 ,0666|IPC_CREAT);
if( msgid == -1 ){
printf("msgid error!");
return ;
}
while(1){
if(msgrcv(msgid,(void*)&data,512,0)!=-1){
printf("msg type is %d\n",data.msg_type);
printf("content is :%s\n",data.text);
}
}
return 0;
}