欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Linux进程间通信 --- 消息队列

程序员文章站 2022-07-02 14:18:29
消息队列 IPC 原理 消息队列是消息的链式队列,如下图为消息队列的模型。整个消息队列有两种类型的数据结构。 ~~~~ 1.msqid_ds 消息队列数据结构:描述整个消息队列的属性,主要包括整个消息队列的权限、拥有者、两个重要的指针(分别指向消息队列的第一个消息和最后一个消息)。 2.msg 消息 ......
消息队列 IPC 原理

消息队列是消息的链式队列,如下图为消息队列的模型。整个消息队列有两种类型的数据结构。
Linux进程间通信 --- 消息队列

1.msqid_ds 消息队列数据结构:描述整个消息队列的属性,主要包括整个消息队列的权限、拥有者、两个重要的指针(分别指向消息队列的第一个消息和最后一个消息)。

2.msg 消息队列数据结构:整个消息队列的主体,一个消息队列有若干个消息,每个消息数据结构的基本成员包括消息类型、消息大小、消息内容指针和下一个消息数据结构的位置。

消息队列还可以基于类型处理,但是,消息队列的 FIFO 原则仅仅适用于同类型的消息。在 Linux 中,对消息队列进行了以下规定(不同 Linux 版本的话值可能会不同):

1.默认情况下,整个系统最多允许有16个消息队列。
2.每个消息队列最大为16384字节。
3.消息队列中的每个消息最大为8192字节。

这些内容在 /usr/include/linux/msg.h 中进行定义:

#define MSGMNI    16   /* <= IPCMNI */     /* max # of msg queue identifiers */
#define MSGMAX  8192   /* <= INT_MAX */   /* max size of message (bytes) */
#define MSGMNB 16384   /* <= INT_MAX */   /* default max size of a message queue */
消息队列的基本属性

下图出于 /usr/include/linux/msg.h 文件
Linux进程间通信 --- 消息队列

消息队列管理

1.创建消息队列:

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

/* 第一个参数为key值,一般由ftok()函数获得;第二个参数为访问权限 */
int msgget(key_t key, int msgflg);

2.消息队列属性控制

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

/* 
 * 第一个参数为消息队列ID,由msgget获得
 * 第二个参数为控制指令
 * 第三个参数为数据传递的载体
 */
int msgctl(int msqid, int cmd, struct msqid_ds *buf);

控制指令如下:
Linux进程间通信 --- 消息队列

3.发送消息队列

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

/*
 * 第一个参数为消息队列ID
 * 第二个参数 msgp 指向定义的缓冲区
 * 第三个参数为发送消息的大小
 * 第四个参数一般高为0,阻塞调用进程
 */
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

4.从消息队列接收消息

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>

/*
 * 第一个参数为消息队列ID
 * 第二个参数为临时消息数据结构,用于储存消息
 * 第三个参数为接收消息的大小
 * 第四个参数用于指定请求的消息类型
 * 第五个参数一般设置为0,阻塞调用进程 
 */
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

其中消息数据结构应定义如下:

/* From /usr/include/linux/msg.h */

struct msgbuf {
    long mtype;         /* 消息类型 */
    char mtext[1];      /* 存储消息位置,需要重新定义 */
};
消息队列应用实例

创建两个进程,使用消息队列进行通信,一个进程发送消息,另一个进程接收消息。

发送端:

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

struct msgbuf {
    long mtype;       
    char mtext[50];    
};

int main()
{
    int key, msg_id;
    static struct msgbuf buf;

    key = ftok(".", 1);

    msg_id = msgget(key, IPC_CREAT | 0600);

    /* 设置消息的类型 */
    buf.mtype = 1;

    while(1){

        fgets(buf.mtext, 50, stdin);

        /* 输入quit退出进程,并删除队列 */
        if(!strncmp(buf.mtext, "quit", 4)){
            msgctl(msg_id, IPC_RMID, 0);
            exit(0);
        }

        /* 将消息发送到队列 */
        msgsnd(msg_id, (void *)&buf, sizeof(buf), 0);
    }

    return 0;
}

接收端:

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

struct msgbuf {
    long mtype;       
    char mtext[50];    
};

int main()
{
    int key, msg_id;
    static struct msgbuf buf;

    key = ftok(".", 1);

    msg_id = msgget(key, IPC_CREAT | 0600);

    /* 设置消息类型 */
    buf.mtype = 1;

    while(1){

        /* 从消息队列接收消息 */
        msgrcv(msg_id, (void*)&buf, sizeof(buf), buf.mtype, 0);
        
        printf("Recv msg : %s \n", buf.mtext);
    }

    return 0;
}

运行结果:

Linux进程间通信 --- 消息队列