我爱编程

Linux系统编程4:IPC消息队列

2018-04-14  本文已影响149人  jdzhangxin

0. 消息队列

1. POSIX 消息队列

1.1 查看

1.2 接口

1.3 结构体

No. 成员 含义 说明
1 mq_flags 标志 mq_open时被初始化,在mq_setattr设置,其值为0或者O_NONBLOCK
2 mq_maxmsg 队列的消息个数最大值 只能在mq_open时被初始化
3 mq_msgsize 队列每个消息长度的最大值 只能在mq_open时被初始化
4 mq_curmsgs 当前队列消息个数 mq_getattr获取

1.4 函数

POSIX 消息队列主要有八个操作

No. 操作 函数
1 创建消息队列 mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr)
2 删除消息队列 int mq_unlink(const char *name)
3 打开消息队列 mqd_t mq_open(const char *name, int oflag)
4 关闭消息队列 int mq_close(mqd_t mqdes)
5 发送消息 int mq_send(mqd_t mqdes, const char *msg_ptr,size_t msg_len, unsigned msg_prio)
6 接收消息 ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,size_t msg_len, unsigned *msg_prio)
7 设置消息队列属性 int mq_setattr(mqd_t mqdes, struct mq_attr *newattr,struct mq_attr *oldattr)
8 获取消息队列属性 int mq_getattr(mqd_t mqdes, struct mq_attr *attr)

*消息队列操作非常相似文件读写操作。

1.4.1 创建消息队列

mqd_t mq_open(const char *name, int oflag, mode_t mode, struct mq_attr *attr)
No. 参数 含义
1 name posix IPC名字,格式为/somename
2 oflag 标志
3 mode 权限
4 attr 队列属性,阻塞attr.mq_flag = 0;非阻塞attr.mq_flag = NONBLOCK
No. 标志 作用
1 O_CREAT 没有该对象则创建
2 O_EXCL 如果O_CREAT指定,但name不存在,就返回错误
3 O_NONBLOCK 以非阻塞方式打开消息队列
4 O_RDONLY 只读
5 O_RDWR 读写
6 O_WRONLY 只写
No. 权限 作用
1 S_IWUSR 用户/属主写
2 S_IRUSR 用户/属主读
3 S_IWGRP 组成员写
4 S_IRGRP 组成员读
5 S_IWOTH 其他用户写
6 S_IROTH 其他用户读
No. 返回值 含义
1 -1 出错
2 其他 消息队列描述符
#include <stdio.h> // perror()
#include <mqueue.h> // mq_open()
#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) //0644
int main(){
    struct mq_attr attr;
    attr.mq_maxmsg = 100;
    attr.mq_msgsize = 100;
    mqd_t mqd = mq_open("/tmp.test",O_CREAT,FILE_MODE,&attr);
    if(-1 == mqd){
        perror("mq_open error");
        return 1;
    }
}

注意编译时可能需要加上 -lrt

  1. 是否会创建/tmp.test这个文件?
  2. 执行命令ll /dev/mqueue会发现什么?
  3. 执行命令cat /dev/mqueue/tmp.test会发现什么?
  4. Posix IPC名字可以是abc/abc/abc.def/abc/def
  5. 系统限制是否可以修改?

1.4.2 删除消息队列

int mq_unlink(const char *name)
No. 参数 含义
1 name posix IPC名字
No. 返回值 含义
1 -1 出错
2 0 成功
#include <mqueue.h> // mq_unlink()
int main(){
    mq_unlink("/tmp.test");
}
  1. 如何验证是否删除?

1.4.3 打开消息队列

mqd_t mq_open(const char *name, int oflag)
No. 参数 含义
1 name posix IPC名字
2 oflag 标志,O_RDONLY只读;O_RDWR读写;O_WRONLY只写
No. 返回值 含义
1 -1 出错
2 其他 描述符
#include <stdio.h> // perror()
#include <mqueue.h> // mq_open()
int main(){
    mqd_t mqd = mq_open("/tmp.test",O_RDONLY);
    if(-1 == mqd){
        perror("mq_open error");
        return 1;
    }
    return 0;
}
  1. 如果消息队列不存在,会发生什么情况?

1.4.4 关闭消息队列

int mq_close(mqd_t mqdes)
No. 参数 含义
1 mqdes 消息队列描述符
No. 返回值 含义
1 -1 出错
2 0 成功
#include <stdio.h> // perror()
#include <mqueue.h> // mq_open() mq_close()
int main(){
    mqd_t mqd = mq_open("/tmp.test",O_RDONLY);
    if(-1 == mqd){
        perror("mq_open error");
        return 1;
    }
    // ...
    mq_close(mqd);
}

1.4.5 发送消息

int mq_send(mqd_t mqdes, const char *msg_ptr,size_t msg_len, unsigned msg_prio)
No. 参数 含义
1 msg_ptr 消息的指针。
2 msg_len 消息长度,不能大于属性值mq_msgsize的值
3 msg_prio 优先级,小于MQ_PRIO_MAX,数值越大,优先级越高
#include <stdio.h> // perror()
#include <mqueue.h> // mq_open() mq_send() mq_close()
int main(int argc,char* argv[]){
    mqd_t mqd = mq_open("/tmp.test",O_WRONLY); // 可以设置O_NONBLOCK
    if(-1 == mqd){
        perror("mq_open error");
        return 1;
    }
    const char* msg = "HelloWorld";
    if(-1 == mq_send(mqd,msg,sizeof(msg),1)){
        perror("mq_send error");
        mq_close(mqd);
        return 1;
    }
    mq_close(mqd);
    return 0;
}

1.4.6 接收消息

ssize_t mq_receive(mqd_t mqdes, char *msg_ptr,size_t msg_len, unsigned *msg_prio)
No. 参数 含义
1 msg_ptr 消息的指针。
2 msg_len 消息长度,不能大于属性值mq_msgsize的值
3 msg_prio 优先级,消息在队列中将按照优先级大小顺序来排列消息
No. 返回值 含义
1 -1 出错
2 正数 接收到的消息长度
#include <stdio.h> // perror()
#include <mqueue.h> // mq_open() mq_receive() mq_close()
#define FILE_MODE (S_IWUSR|S_IRUSR|S_IRGRP|S_IROTH) //0644
int main(int argc,char* argv[]){
    mqd_t mqd = mq_open("/tmp.test",O_RDONLY);
    if(-1 == mqd){
        perror("mq_open error");
        return 1;
    }
    char buf[BUFSIZ];
    unsigned int prio;
    if(-1 == mq_receive(mqd,buf,BUFSIZ,&prio)){
        perror("mq_send error");
        mq_close(mqd);
        return 1;
    }
    printf("msg:%s\nprio:%d\n",buf,prio);
    mq_close(mqd);
    return 0;
}

1.4.7 设置消息队列属性

int mq_setattr(mqd_t mqdes, struct mq_attr *newattr,struct mq_attr *oldattr);
No. 参数 含义
1 mqdes 消息队列描述符
2 newattr 新属性,只能设置mq_flags:0:NONBLOCK
3 oldattr 旧属性
No. 返回值 含义
1 -1 出错
2 0 成功
#include <stdio.h> // perror()
#include <string.h> // bzero()
#include <mqueue.h> // mq_open() mq_setattr() mq_close()
int main(){
    mqd_t mqd = mq_open("/tmp.test",O_RDWR);
    if(-1 == mqd){
        perror("mq_open error");
        return 1;
    }
    struct mq_attr new_attr;
    bzero(&new_attr,sizeof(new_attr));
 
    new_attr.mq_flags = O_NONBLOCK;
    struct mq_attr attr;
    if(-1 == mq_setattr(mqd,&new_attr,&attr)){
        perror("mq_setattr error");
        mq_close(mqd);
        return 1;
    }
    printf("flag:%ld,Max msg:%ld,Max msgsize:%ld,Cur msgnun:%ld\n",attr.mq_flags,attr.mq_maxmsg,attr.mq_msgsize,attr.mq_curmsgs);
    mq_close(mqd);
}

1.4.8 获取消息队列属性

int mq_getattr(mqd_t mqdes, struct mq_attr *attr)
No. 参数 含义
1 mqdes 消息队列描述符
2 attr 属性
No. 返回值 含义
1 -1 出错
2 0 成功
#include <stdio.h> // perror()
#include <mqueue.h> // mq_open() mq_getattr() mq_close()
int main(){
    mqd_t mqd = mq_open("/tmp.test",O_RDONLY);
    if(-1 == mqd){
        perror("mq_open error");
        mq_close(mqd);
        return 1;
    }
    struct mq_attr attr;
    mq_getattr(mqd,&attr);
    printf("flag:%ld,Max msg:%ld,Max msgsize:%ld,Cur msgnun:%ld\n",attr.mq_flags,attr.mq_maxmsg,attr.mq_msgsize,attr.mq_curmsgs);
   mq_close(mqd);
    return 0;
}
上一篇 下一篇

猜你喜欢

热点阅读