Linux进程通信之消息队列

消息队列简介

进程通信信号量方式传送信息量有限,管道只能传送无格式字节流,无疑给程序开发带来不便,消息队列克服了这些缺点。消息队列就是一个消息链表,可以把消息看做一个记录,具有特定格式,进程可以向其中按照一定规则添加新消息;另一些进程可以从消息队列读走消息。消息队列只有在内核重新启动,或者人工删除才会消失。消息队列内核持续性需要消息队列在系统范围内拥有唯一个键值,所以,要获得一个消息队列的描述字,必须提供该消息队列的键值。键值可以自己指定,也可以用函数自动生成。


键值函数结构

#include <sys/types.h>  
#include <sys/ipc.h>  
key_t ftok(char *pathname,char proj);  

功能:

  • 返回文件名对应的键值

参数:

  • pathname:文件名
  • proj:项目名不为0即可

消息队列打开函数

#include <sys/types.h>  
#include <sys/ipc.h>  
#include <sys/msg.h>  
int msgget(key_t key,int msgflg);

功能:

  • 返回与键值对应的消息队列描述字

参数:

  • key:
    键值,由ftok获得。
  • msgflg:
    标志位
    • 常用标志位:
    • IPC_CREAT
      创建新的消息队列
    • IPC_EXCL
      IPC_CREAT一同使用,表示如果创建的消息队列已经存在,返回错误。
    • IPC_NOWAIT
      读写消息队列无法满足要求时不阻塞。
  • 以下两种情况将创建消息队列:
    • 没有与键值对应的消息队列,并且msgflgIPC_CREAT参数。
    • key参数为IPC_PRIVATE

消息队列发送函数

#include <sys/types.h>  
#include <sys/ipc.h>  
#include <sysmsg.h>  
int megsend(int msgid,struct msgbuf *msgp,int msgsz,int msgflg);

功能:

  • 向消息队列发送一条消息

参数:

  • msgqid
    消息队列描述字。
  • msgp
    存放消息结构的地址。
  • msgsz
    消息数据的长度。
  • msgflag
    发送标志有意义的发送标志为IPC_NOWAIT,指明在消息队列没有足够空间容纳要发送的消息时,是否等待。
  • 消息格式
    struct msgbuf
    {
        long type;    //可理解为消息在队列中编号
        char ext[0];  //消息数据的首地址  
    }

消息队列接收函数

#include <sys/types.h>  
#include <sys/ipc.h>  
#include <sys/msg.h>  
int msgrcv(int msgid,struct msgbuf*msgp,int msgsz,long msgtpy,int msgflg);

功能:
从消息队列中读取消息,并把消息存储在msgp指向的msgbuf结构中,在成功读取一条消息后,消息队列中这条消息将被删除。
参数:

  • msgid
    消息队列描述字
  • msgp
    存放读取消息的消息结构的地址
  • msgsz
    消息的长度
  • msgtpy
    消息描述字(也就是消息锁在消息队列中的标号)
  • msgflg
    与读取相关的参数,常用IPC_NOWAIT,表示没有数据可读的时候,不等待

消息队列删除函数

#include<sys/type.h>
#include<sys/ipc.h>
#Include<sys/msg.h>
int msgctl(int msgid,int cmd,struct msgid_ds *buf);

参数:

  • msgid:
    消息队列标识符
  • cmd:
    所要采取的命令IPC_RMID删除消息队列
  • buf:
    权限信息

消息队列用法举例

    #include <sys/types.h>  
    #include <sys/msg.h>  
    #include <unistd.h>  
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.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();   //消息编号为自身进程ID (只要大于0就可以)  
            strcpy(msgbuf.data,"this is a message");  
            ret=msgsnd(msgid,&msgbuf,sizeof(msgbuf.data),IPC_NOWAIT);  //向消息队列发送 编号为自身ID 内容为 this is a message的消息  
            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);//接收消息队列中编号为自身进程ID的消息  
            if(ret==-1)  
            {  
                    printf("recv message err\n");  
                    return -1;  
            }  
            printf("recv msg =[%s]\n",msgbuf.data); //打印接受的消息  

    }  

程序运行结果:

[root@localhost mesg]# ls  
msg  msg.c  
[root@localhost mesg]# ./msg  
key =[ffffffff]  
recv msg =[this is a message]  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值