Linux笔记_进程通讯——消息队列

来源:互联网 发布:mac无法删除文件 编辑:程序博客网 时间:2024/06/06 00:40
消息队列
1.定义
unix早期通信机制之一的信号能够传送的信息量有限,管道则只能传送无格式的字节流,这无疑会给应用程序开发带来不便。消息队列(也叫做报文队列)则克服了这些缺点。

2.发展
消息队列就是一个消息的链表。可以把消息看做一个记录,具有特定的格式。进程可以向中按照一定的规则添加新消息;另一些进程则可以从消息队列中读走消息。
 
3.分类
目前主要有两种类型的消息队列
POSIX消息队列(可移植操作系统接口)和系统V消息队列(目前被大量使用)

4.持续性
系统V消息队列是随内核持续的,只有在内核重启或者人工删除时,该消息队列才会删除。

5,键值
消息队列的内核持续性要求每个消息队列都在系统范围内对应唯一的键值,所以要获得一个消息队列的描述字必须提供该消息队列的键值
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok (char *pathname,char proj)
功能:返回文件名对应的键值
pathname:文件名
proj:项目名(不为0即可)

6.打开/创建
#include <sys/types.h>
#include <sys/ipc.h>
int msgget(key_t key,int msgflg)
key: 键值,由ftok获得
msgflg:标志位 
          IPC_CREAT:创建新的消息队列
          IPC_EXCL:与IPC_CREAT一同使用,表示如果要创建的消息队列已经存在,则返回错误 
          IPC_NOWAIT:读写消息队列要求无法得到满足时,不阻塞

返回值:与键值key相对应的消息队列描述字。


以下两种情况将创建一个新的消息队列:
1)如果没有与键值key相对应的消息队列,并且msgflg中包含了IPC_CREAT标志位;
2)key参数为IPC_PRIVATE。

6.发送消息
#include <sys/typess.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid,struct msgbuf*msgp,int msgsz,int msgflg)
功能:向消息队列中发送一条消息
msqid:创建的返回值消息队列的id
msgp:存放消息的结构
msgsz:消息数据长度
msgflg:发送标志,有意义的标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,msgsnd是否等待。
消息格式:
struct msgbuf
{
     long mtype;//消息类型>0
     char mtext[1]; //消息数据的首地址
}

7. 接收消息
#include <sys/typess.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgrcv(int msqid, struct msgbuf *msgp,int msgsz,long msgtyp,int msgflg)
功能:
从msqid代表的消息队列中读取一个msgtype类型的消息,并把消息存储在msgp指向的msgbuf结构中。在成功的读取了一条消息以后,队列中的这条消息将会被删除。
************************************************
演示代码:
#include <sys/types.h>
#include <sys/msg.h>
#include <unistd.h>

struct msg_buf
    {
        int mtype;
        char data[255];
    };

int main()
{
        key_t key;
        int msgid;
        int ret;
        struct msg_buf msgbuf;

        key=ftok("/tmp/2",'a');
        printf("key =[%x]\n",key);
        msgid=msgget(key,IPC_CREAT|0666); /*通过文件对应*/

        if(msgid==-1)
        {
                printf("create error\n");
                return -1;
        }

        msgbuf.mtype = getpid();
        strcpy(msgbuf.data,"test haha");
        ret=msgsnd(msgid,&msgbuf,sizeof(msgbuf.data),IPC_NOWAIT);
        if(ret==-1)
        {
                printf("send message err\n");
                return -1;
        }

        memset(&msgbuf,0,sizeof(msgbuf));
        ret=msgrcv(msgid,&msgbuf,sizeof(msgbuf.data),getpid(),IPC_NOWAIT);
        if(ret==-1)
        {
                printf("recv message err\n");
                return -1;
        }
        printf("recv msg =[%s]\n",msgbuf.data);

}

*************************************************************
0 0