消息队列

  • 消息队列实质为内核地址空间中的内部链表,在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;

}