MSGQueue 使用介绍


一、MSGQueue 消息队列简介

消息队列提供了一种在两个不相关的进程之间传递数据的简单高效的方法,其特点如下:

  • 消息队列存储在内存中由内核维护,只有内核重启或人工删除消息队列时,该消息队列才会被删除
  • 消息队列可以实现消息按照类型随机读取,不一定要以先进先出的次序读取
  • 消息队列允许一个或多个进程向它写入或者读取消息
  • 与无名管道、命名管道一样,从消息队列中读出消息,消息队列中对应的数据都会被删除
  • 每个消息队列都有消息队列标识符,消息队列的标识符在整个系统中是唯一的

二、MSGQueue 基本函数

1. key_t ftok(const char *pathname, int proj_id);

进程间通信机制需要一个 key 值,通过 key 值可在系统内获得一个唯一的消息队列标识符
key 值可以是人为指定的,也可以通过 ftok() 函数获得
proj_id: 项目ID,非 0 整数(只有低 8 位有效)

2. int msgget(key_t key, int msgflg);

创建一个新的或打开一个已经存在的消息队列。不同的进程调用此函数,只要用相同的 key 值就能得到同一个消息队列的标识符

3. int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

将新消息添加到消息队列
msgsz:消息正文的字节数,不包括消息类型长度
msgflg = 0:阻塞到条件满足
msgflg = IPC_NOWAIT: 非阻塞,若消息没有立即发送则调用该函数的进程会立即返回

4. ssize_t msgrcv( int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg );

从标识符为 msqid 的消息队列中取出一个消息,一旦取出消息成功则消息在消息队列中被删除
msgtyp = 0:返回队列中的第一个消息
msgtyp > 0:返回队列中消息类型为 msgtyp 的消息(常用),若队列中有多条此类型的消息,则获取最先添加的消息,即先进先出原则
msgtyp < 0:返回队列中消息类型值小于或等于 msgtyp 绝对值的消息,如果这种消息有若干个,则取类型值最小的消息
msgflg = 0:阻塞直到接收消息成功为止
msgflg = IPC_NOWAIT: 调用进程会立即返回,若没有收到消息则立即返回 -1
msgflg = MSG_NOERROR: 若返回的消息字节数比 nbytes 字节数多,则消息就会截短到 nbytes 字节

5. int msgctl(int msqid, int cmd, struct msqid_ds *buf);

cmd = IPC_RMID:删除由 msqid 指示的消息队列,将它从系统中删除并破坏相关数据结构
cmd = IPC_STAT:将 msqid 相关的数据结构中各个元素的当前值存入到由 buf 指向的结构中,相当于把消息队列备份到 buf 里
cmd = IPC_SET:将 msqid 相关的数据结构中的元素设置为由 buf 指向的结构中的对应值,相当于消息队列原来的属性值清空再由 buf 来替换

6. 消息格式:

消息类型必须是长整型的,而且必须是结构体类型的第一个成员,类型下面是消息正文,正文可以有多个成员(正文成员可以是任意数据类型的)。至于这个结构体类型叫什么名字,里面成员叫什么名字,自行定义没有规定

typedef struct _msg
{
    long mtype;      // 消息类型
    char mtext[100]; // 消息正文
    // …… ……         // 消息正文可有多个成员
}MSG;

三、MSGQueue 代码示例

// 写消息队列
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

typedef struct _msg
{
    long mtype;
    char mtext[128];
}MSG;

int main(int argc, char *argv[])
{
    key_t key;
    int  msgqid;
    MSG msg;

    key = ftok("./", 128);
    msgqid = msgget(key, IPC_CREAT|0666);
    memset(&msg, 0, sizeof(MSG));
    msg.mtype = 10;
    strcpy(msg.mtext, "hello world");
    msgsnd(msgqid, &msg, sizeof(MSG)-sizeof(long), 0);
    return 0;
}


// 读消息队列
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>

typedef struct _msg
{
    long mtype;
    char mtext[128];
}MSG;

int main(int argc, char *argv[])
{
    key_t key;
    int  msgqid;
    MSG msg;
    long mtype = 10;

    key = ftok("./", 128);
    msgqid = msgget(key, IPC_CREAT|0666);
    memset(&msg, 0, sizeof(MSG));
    msgrcv(msgqid, &msg, sizeof(msg)-sizeof(long), mtype, 0);
    printf("msg.mtext=%s\n", msg.mtext);
    msgctl(msgqid, IPC_RMID, NULL);
    return 0;
}

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值