消息队列的介绍

1. 相关概念

消息队列是IPC对象的一种

消息队列由消息队列ID来唯一标识

消息队列就是一个消息的列表。用户可以在消息队列中添加消息、读取消息等。

消息队列可以按照类型来发送/接收消息

2. 相关函数

1 -- msgget
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

int msgget(key_t key, int msgflg);
功能:
创建或者打开一个消息队列,得到消息队列id
参数:
key:
键值,唯一的键值确定唯一的消息队列
如何设置键值:
自己直接定义一个键值
使用ftok函数获取键值
msgflg:
标志位
一般设置为 IPC_CREAT | 0777
返回值:
成功:
消息队列id
失败:
-1

2 -- ftok  
#include <sys/types.h>
#include <sys/ipc.h>
key_t ftok(const char *pathname, int proj_id);
功能:获取键值
参数:
pathname:
路径名
proj_id:
自定义的值,只取前八位
返回值:
成功:
键值
失败:
-1

3 -- msgctl 
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgctl(int msqid, int cmd, struct msqid_ds *buf);
功能:
控制一个消息队列
参数:
msqid:
消息队列id
cmd:
具体控制
IPC_STAT 获取消息队列属性信息
IPC_SET 设置消息队列属性信息
IPC_RMID 删除一个消息队列
msqid_ds:消息队列属性结构体
返回值:
成功:
0
失败:
-1

4 -- msgsnd
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
功能:
向一个消息队列中写入数据
参数:
msqid:
消息队列id
msgp:
要写入的数据,需要自己定义一个结构体
struct msg_buf{
    long type; //消息类型,必须有且类型也不能变
    用于读取数据时,可以指定消息的类型来读取
    char mtext[32]; //消息正文具体要写入的数据,大小自己定义,类型也可以自定义
};
msgsz:
消息正文的大小,就是mtext的大小,一定不是第二个参数的大小
msgflg:
标志位
0   阻塞
IPC_NOWAIT  非阻塞
返回值:
成功:
0
失败:
-1

5 -- msgrcv
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, 
long msgtyp, int msgflg);
功能:
从消息队列中读取数据
参数:
msqid:
消息队列id
msgp:
保存读取的数据
msgsz:
消息正文大小
msgtyp:
消息类型
0    按照顺序读取一个消息
>0   按照顺序读取第一个消息类型为当前参数的消息
<0   按照顺序读取第一个消息类型小于等于这个参数的绝对值的类型的消息
msgflg:
标志位
0   阻塞
IPC_NOWAIT  非阻塞
返回值:
成功:
接收到的数据的大小
失败:
-1

3. 创建和删除消息队列

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>


int main(int argc, char const *argv[])
{
    //使用ftok函数获取键值
    key_t key;
    if((key = ftok(".", 1000)) == -1)
    {
        perror("ftok error");
        exit(1);
    }

    //ftok函数获取的健值就是这个函数的第二个参数的后8位、第一个参数
    //对应文件的设备好的后8位以及这个文件inode号的后16位,共同组成键值
    // printf("key = %#x\n", key);
    // struct stat mystat;
    // stat(".", &mystat);
    // printf("dev_num = %x\n", mystat.st_dev);
    // printf("inode = %x\n", mystat.st_ino);
    // printf("1000 = %#x\n", 1000);

    //创建一个消息队列
    int msgid;
    if((msgid = msgget(key, IPC_CREAT | 0777)) == -1)
    {
        perror("msgget error");
        exit(1);
    }

    puts("--------------------------------------------");
    system("ipcs -q");
    puts("--------------------------------------------");

    //删除消息队列
    if(msgctl(msgid, IPC_RMID, NULL) == -1)
    {
        perror("msgctl error");
        exit(1);
    }

    puts("--------------------------------------------");
    system("ipcs -q");
    puts("--------------------------------------------");

    return 0;
}

4. 将数据写入消息队列

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

typedef struct{
    long type;
    int id;
    char name[32];
    int score;
}MSG;

#define DATASIZE (sizeof(MSG) - sizeof(long))

int main(int argc, char const *argv[])
{
    //使用ftok函数获取键值
    key_t key;
    if((key = ftok(".", 1000)) == -1)
    {
        perror("ftok error");
        exit(1);
    }

    //创建一个消息队列
    int msgid;
    if((msgid = msgget(key, IPC_CREAT | 0777)) == -1)
    {
        perror("msgget error");
        exit(1);
    }

    puts("--------------------------------------------");
    system("ipcs -q");
    puts("--------------------------------------------");

    MSG msg1 = {1, 1001, "zhangsan", 90};
    MSG msg2 = {2, 1002, "lisi", 100};
    MSG msg3 = {3, 1003, "wangwu", 92};
    MSG msg4 = {4, 1004, "zhaoliu", 88};
    msgsnd(msgid, &msg1, DATASIZE, 0);
    msgsnd(msgid, &msg2, DATASIZE, 0);
    msgsnd(msgid, &msg3, DATASIZE, 0);
    msgsnd(msgid, &msg4, DATASIZE, 0);

    puts("--------------------------------------------");
    system("ipcs -q");
    puts("--------------------------------------------");

    return 0;
}

5. 从消息队列中读取数据

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>

typedef struct{
    long type;
    int id;
    char name[32];
    int score;
}MSG;

#define DATASIZE (sizeof(MSG) - sizeof(long))

int main(int argc, char const *argv[])
{
    //使用ftok函数获取键值
    key_t key;
    if((key = ftok(".", 1000)) == -1)
    {
        perror("ftok error");
        exit(1);
    }

    //创建一个消息队列
    int msgid;
    if((msgid = msgget(key, IPC_CREAT | 0777)) == -1)
    {
        perror("msgget error");
        exit(1);
    }

    puts("--------------------------------------------");
    system("ipcs -q");
    puts("--------------------------------------------");

    MSG msg;
    ssize_t bytes;
    if((bytes = msgrcv(msgid, &msg, DATASIZE, -3, 0)) == -1)
    {
        perror("msgrcv error");
        exit(1);
    }

    printf("bytes = %ld, id:%d,name:%s,score:%d\n", bytes, msg.id, msg.name, msg.score);

    puts("--------------------------------------------");
    system("ipcs -q");
    puts("--------------------------------------------");

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小徐的记事本

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

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

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

打赏作者

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

抵扣说明:

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

余额充值