linux IPC之POSIX消息队列

35 篇文章 0 订阅
1 篇文章 0 订阅

1.POSIX概述

        前面已经学习了LINUX进程通信方式的进程和FIFO两种方式,但是POSIX是与之前两种不同的方式,主要区别呢,在于使用管道和FIFO的时候,在写入管道之前,应该有一个进程已经做好了读的准备,它呢是以无格式的字节流的方式进行通信的,如果有另外的进程进行干扰的话,很有可能会造成错误的信息交换,而POSIX消息队列则不会出现这种问题,POSIX消息内容主要有以下几个属性,一个是优先级,一个是消息内容的最大长度,最后一个则是消息内容了,以这种方式进行进程间的通信,我们相信,会有较高的稳定性。POSIX的优先级,主要是两种方式,如果是POSIX那么返回的就是最大优先级的消息,如果是SYstem V那么可以返回特定优先级的消息

2.POSIX的特性

        POSIX的最大特性在于其内核持续性,是不是可以这样理解,只要不进行消息队列的删除操作,那么,在该消息队列中,就一定会一直存在,也就是说,我们不需要进行提前等待消息的写入,只要OS不进行重新自举,那么消息队列就一定会一直存在。

3.POSIX消息的创建

      

#include<mqueue.h>
mqd_t mq_open(const char* name,int flag,/*mode_t mode,struct mq_attr *attr  */);
//打开或者创建一个消息队列,成功则返回一个消息队列描述符,失败,则返回-1
mqd_close(mqd_t mqd);//根据消息队列描述符,关闭指定的消息队列
mqd_unlink(const char* name);//成功返回0,失败返回-1

主要说几个参数:

name:表示的是消息的名称,我们可以这样认为,这是一个路径名称类似于"/tmp/123"等等

flag:表示打开的方式,可以有这样的O_CREAT  O_WRONLY  或者O_RDONLY,创建,可写,可读权限

mode:则是可选参数 ,在flag中含有O_CREAT参数,并且消息队列不存在的时候,才需要提供该参数,如果不提供,则是默认权限

attr:也是一个可选参数,同上,在flag中含有O_CREAT,并且消息队列不存在http://write.blog.csdn.net/postedit/38843637的时候,才需要该参数,设定该消息队列的属性,如果不提供,则表示默认属性

mq_close:关闭一个消息队列,关闭之后该消息队列并不删除,一个进程结束,自动调用关闭打开的消息队列

mq_unlink:用于删除一个消息队列,消息队列创建之后只有通过调用该函数或者内核自举的时候,才会进行消息队列的删除,每个消息队列都有一个保存当前打开该消息队列的引用计数器

main.c文件如下“http://write.blog.csdn.net/postedit/38843637

#include<stdio.h>
#include<mqueue.h>
#include<errno.h>
int  main()
{
    #define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
    int flag=O_CREAT|O_RDONLY;
    mqd_t  mqd=mq_open("/tmp.321",flag,FILE_MODE,NULL);
    if(mqd==-1)
    {
        printf("对不起,消息队列创建失败%s",strerror(errno));
        return;
    }
     printf("恭喜您,消息队列创建成功\n");
     mq_close(mqd);
}
makefile

test:main.o
        cc -o test main.o   -lrt
main.o:main.c
       cc -c main.c

这里需要注意的是,FILE_MODE允许用户读写,组成员只读,其他成员也是只读,这些权限位会被当前进程的文件模式创建掩码修正但是FILE_MODE也是有着限制的,不可能是0777,用户的权限可以是读写执行,但是组用户最高是只读可执行。

就是这样还是会出现permission denied,所需要做的就是(如果不出现,当然就不用管了阿)

sudo mkdir /dev/mqueue

mount -t mqueue none /dev/mqueeu

然后执行 ./test就可以了!这样,消息队列就创建成功了,但是,总是出现错误代码13  ,也就是说,permission denied出错,我们需要使用管理员权限才行...,今天就暂时,写到这里吧

接下来说说,mqueue属性的设置和获取把

#include<errno.h>
#include<mqueue.h>
#include<stdio.h>
int main()
{
    int flag=O_CREAT|O_RDWR;
    mqd_t mqd=mq_open("/temp.124",flag,0766,NULL);
    if(mqd==-1)
    {
       printf("sorry create mq failed:%s\n",strerror(errno));
       return;
    }
    printf("# mq create successfully\n");
    // get the attribute of the mqueue
    struct mq_attr myAttr;
    mq_getattr(mqd,&myAttr);
    printf("队列的最大长度是%d\n",myAttr.mq_maxmsg);
    printf("单个消息的最大长度是%d\n",myAttr.mq_msgsize);
    printf("当前队列中消息的个数%d\n",myAttr.mq_curmsgs);
    printf("开始设置新的属性队列中长度是13,\n");
    struct mq_attr newAttr;
    newAttr.mq_maxmsg=13;
    mq_close(mqd);
    mq_open("temp.124",flag,0766,&newAttr); 
/*
    int result=mq_setattr(mqd,&newAttr,&myAttr);
    if(result==-1)
    {
        printf("设置出错%s\n",strerror(errno));

    } 
*/
    mq_getattr(mqd,&newAttr);
    printf("新的长度是%d\n",newAttr.mq_maxmsg);
    mq_close(mqd); 
    return;
}
不知为何mq_setattr总是出错,提示结果是Invalid Argument ,但是如果关闭一下,然后填入相应的属性的时候,mqueue的属性就能正常了,,,很是诡异,也可能是我才疏学浅吧...

消息队列的发送和接收:mg_send.c

#include<string.h>
#include<stdio.h>
#include<mqueue.h>
#include<errno.h>
/****************************************************
***************该函数主要是进行进程对消息队列的注册
*****************************************************/

int main()
{
    int flag =O_CREAT|O_RDWR;
    mqd_t mqd=mq_open("/temp.123",flag,0644,NULL);
    if(mqd==-1)
    {
       printf("i am sorry create the mqueue error%s\n",strerror(errno));
       return 0;
    }
    char *but="send test";
    if(-1==mq_send(mqd,but,strlen(but),300))
    {
       printf("send failed %s\n",strerror(errno));
       goto error_proc;
    }
    else{
    printf("send sucessfully\n");
    }
    error_proc:
    mq_close(mqd);
}

mq_receive.c文件如下:

#include<stdio.h>
#include<mqueue.h>
#include<errno.h>
#include<string.h>
int main()
{
    int flag=O_CREAT|O_RDWR;
    mqd_t mqd=mq_open("/temp.123",flag,0644,NULL);
    if(mqd==-1)
    {
       printf("congratulations mqueue created successfully\n");
       return -1;
    }
    // we got the maxsize of the sigle msg
    struct mq_attr old_attr={0};
    mq_getattr(mqd,&old_attr);
    char* buf=malloc(old_attr.mq_msgsize);

    int pri=0;
    if(-1!=mq_receive(mqd,buf,old_attr.mq_msgsize,&pri))
    {
       printf("what we got is %s\n",buf);
    }
    else
    {
       printf("receive error :%s\n",strerror(errno));
    } 
    free(buf);
    mq_close(mqd);

}

这样就能成功了,PS:

开始的时候,我一直在使用堆栈变量,char buf[256],但是一直提示错误 msg  too long  ,所以变幻了方式,自动获取该消息队列的单个消息的对大长度,然后使用该长度即可



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

世纪殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值