Skip to content

消息队列

IPC(进程间通信) 中的消息队列只能在本机通信,广义的消息队列是网络通信中的一个中间件,一定要把这两个区分开来。

消息队列和我们之前学习的管道非常的相似,只是管道是一种流式的技术,消息队列是包式的,区别在于有没有边界。

在本文中只针对 system V 版本的消息队列进行认识分析

相关函数

创建消息队列

cpp
#include <sys/msg.h>

int msgget(key_t key, int msgflg);

发送消息

cpp
#include <sys/msg.h>

int msgsnd(int msqid, const void msgp[.msgsz], size_t msgsz, int msgflg);

接收消息

cpp
#include <sys/msg.h>

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

示例

在发送或者接收消息之前我们都需要先创建一个消息的结构体struct msgbuf xxx

msgsnd.c

c
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>

// 定义消息结构体
typedef struct msgbuf {
    long mtype;
    char mtext[256];
} myMsg_t;

int main(int argc, char *argv[]) {
    int msqid = msgget(1000, IPC_CREAT | 0600);
    if (msqid == -1) {
        perror("msgget");
        return -1;
    }

    // 创建3个消息
    myMsg_t msg1;//Huangxiaoming
    myMsg_t msg2;//Wuyifan
    myMsg_t msg3;//Caixukun
    msg1.mtype = 1;
    strcpy(msg1.mtext, "Ganenguoqusuoyou,weilairenshijiaren");
    msg2.mtype = 2;
    strcpy(msg2.mtext, "skr skr~");
    msg3.mtype = 3;
    strcpy(msg3.mtext, "jinitaimei");

    // 依次发送3个消息
    msgsnd(msqid, &msg1, strlen(msg1.mtext), 0);
    msgsnd(msqid, &msg2, strlen(msg2.mtext), 0);
    msgsnd(msqid, &msg3, strlen(msg3.mtext), 0);
    puts("send over");

    return 0;
}

msgrcv.c

c
#include <stdio.h>
#include <string.h>
#include <sys/msg.h>

// 定义消息结构体
typedef struct msgbuf {
    long mtype;
    char mtext[256];
} myMsg_t;

int main(int argc, char *argv[]) {
    int msqid = msgget(1000, IPC_CREAT | 0600);
    if (msqid == -1) {
        perror("msgget");
        return -1;
    }

    long type;
    printf("who are you? 1 huangxiaoming 2 wuyifan 3 caixukun\n");
    scanf("%ld", &type);

    myMsg_t msg;
    memset(&msg, 0, sizeof(msg));
    // msgrcv(msqid, &msg, sizeof(msg.mtext), type, 0); // 接收指定的消息
    // msgrcv(msqid, &msg, sizeof(msg.mtext), 0, 0);    // 接收到达的任意一个消息 无消息会阻塞
    int ret = msgrcv(msqid, &msg, sizeof(msg.mtext), 0, IPC_NOWAIT);    // 接收到达的任意一个消息 无消息不会阻塞
    if (ret == -1) {
        perror("msgrcv");
        return -1;
    }

    printf("you are %ld, msg = %s\n", type, msg.mtext);

    return 0;
}

调整系统设置

通过 proc 文件系统修改消息队列的最大消息大小

shell
$ cat /proc/sys/kernel/msgmax   # 查看目前系统中设置的最大消息大小
8192

$ sudo -i   # 切换到 root 用户
echo 4096 > /proc/sys/kernel/msgmax     # 修改最大消息大小
exit        # 退出 root 用户

$ cat /proc/sys/kernel/msgmax   # 查看目前系统中设置的最大消息大小
4096

能通过这种方式修改是因为根目录下的proc文件系统是一个伪文件系统,它是操作系统的运行状态在文件系统的映射。因此我们可以像修改文件一样修改操作系统的属性。

/proc/目录中数字文件夹是正在运行中的进程,/proc/sys/目录中存放的是系统相关的属性