进程通信之消息队列
消息队列
消息队列是一种进程间通信(IPC)机制,允许进程以消息的形式传递数据。它通过在内核中维护的队列实现,提供了异步通信的能力。消息队列由键值唯一标识,支持一个或多个进程之间的数据传输。
相关函数
msgget
- 功能:创建或获取一个消息队列
- 函数原型:
int msgget(key_t key, int msgflg);
- 参数:
- key:消息队列的键即标识,可以通过- ftok生成
- msgflg:访问权限。- IPC_CREAT—— 如果 key 不存在,则创建
- IPC_EXCL—— 如果 key 存在,则返回失败
 
 
- 返回值:成功返回消息队列标识符(非负整数),失败返回 -1
msgsnd
- 功能:向消息队列发送消息
- 原型:
int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
- 参数:
- msqid:消息队列标识符,也就是上述创建的返回值
- msgp:指向消息的指针,是个结构体,但需要自己手动定义(放下面了)
- msgsz:消息正文的大小(不包括消息类型)
- msgflg:操作标志(如- IPC_NOWAIT非阻塞发送,即如果包含此选项,则消息队列满时,不发送该消息,立即返回 -1。反之,如果不包含此选项,则消息队列满时,挂起本进程,直到消息队列由空间可用。)
 
// 结构体的定义
struct message {
    long msg_type;       // 消息类型,必须为 long 类型即 long int
    char msg_text[100];  // 消息正文,数组大小自定义
};
- 返回值:成功返回 0,失败返回-1
msgrcv
- 功能:从消息队列接收消息
- 函数原型:
ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
- 参数:
- msqid:消息队列标识符,即创建消息队列时候的函数返回值
- msgp:存储接收到的消息的指针(上面- msgsnd已介绍)
- msgsz:期望接收的消息正文大小
- msgtyp:消息类型(- 0表示接收任意类型)- 0:忽略消息类型,从消息队列中接收队列中的第一条消息(按照队列的 FIFO 顺序)
- 大于 0:从消息队列中接收类型为msg_type的第一条消息,如果队列中没有匹配的消息,进程会阻塞,直到符合条件的消息到达(或设置了非阻塞标志)
- 小于 0:从消息队列中接收类型值小于等于|msg_type|(绝对值)的消息,选择类型值小于等于|msg_type|且优先级最高的消息(类型值越小,优先级越高)
 
- msgflg:操作标志(如- IPC_NOWAIT非阻塞接收,上述- msgsnd已经介绍)
 
- 返回值:成功返回消息队列标识符(非负整数),失败返回 -1
msgctl
- 功能:控制和管理消息队列
- 原型:
int msgctl(int msqid, int cmd, struct msqid_ds *buf);`
- 参数:
- msqid:消息队列标识符,即创建消息队列时候的函数返回值
- cmd:控制命令,指定要对消息队列执行的操作- IPC_STAT:获取消息队列的当前状态
- IPC_SET:设置消息队列的属性
- IPC_RMID:从系统中删除消息队列
 
- buf:指向一个- msqid_ds结构的指针,用于传递或接收消息队列的信息- IPC_STAT:由内核填充- buf,包含消息队列的当前状态,然后作为传出参数,用户可以进行读取数据查看消息队列状态
- IPC_SET:用户手动填充- buf中的部分字段,将其作为传入参数,修改消息队列的属性
- IPC_RMID:此参数可以为- NULL,因为该操作不需要- buf
 
 
- 返回值:成功返回 0,失败返回-1
示例
发送方
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// 定义消息结构
struct msgbuf {
    long msg_type;       // 消息类型
    char msg_text[256];  // 消息内容
};
int main() 
{
    key_t key;
    int msqid;
    struct msgbuf msg;
    // 生成唯一键值
    key = ftok(".", 123);
    if (key == -1) {
        perror("ftok");
        exit(EXIT_FAILURE);
    }
    // 创建或获取消息队列
    msqid = msgget(key, IPC_CREAT | 0666);
    if (msqid == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }
	printf("Message queue created with ID: %d\n", msqid);
    // 循环发送消息
    for (int i = 1; i <= 5; ++i) 
    {
        msg.msg_type = 1; // 消息类型为 1
        snprintf(msg.msg_text, sizeof(msg.msg_text), "Message %d from sender", i);
        if (msgsnd(msqid, &msg, strlen(msg.msg_text) + 1, 0) == -1) {
            perror("msgsnd");
            exit(EXIT_FAILURE);
        }
        printf("Sent: %s\n", msg.msg_text);
        sleep(1); // 模拟延时
    }
    return 0;
}
接收方
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
// 定义消息结构
struct msgbuf {
    long msg_type;       // 消息类型
    char msg_text[256];  // 消息内容
};
int main()
{
    key_t key;
    int msqid;
    struct msgbuf msg;
    // 生成唯一键值
    key = ftok(".", 123);
    if (key == -1) {
        perror("ftok");
        exit(EXIT_FAILURE);
    }
    // 获取消息队列
    msqid = msgget(key, 0666);
    if (msqid == -1) {
        perror("msgget");
        exit(EXIT_FAILURE);
    }
	printf("Message queue opened with ID: %d\n", msqid);
	
    // 循环接收消息
    while (1) 
    {
        if (msgrcv(msqid, &msg, sizeof(msg.msg_text), 1, 0) == -1) {
            perror("msgrcv");
            exit(EXIT_FAILURE);
        }
        printf("Received: %s\n", msg.msg_text);
        // 接收到特定内容时退出
        if (strcmp(msg.msg_text, "exit") == 0) {
            printf("Received exit signal. Exiting...\n");
            break;
        }
    }
    return 0;
}
输出
// 发送方
Message queue created with ID: 12345
Sent: Message 1 from sender
Sent: Message 2 from sender
Sent: Message 3 from sender
Sent: Message 4 from sender
Sent: Message 5 from sender
// 接收方
Message queue opened with ID: 12345
Received: Message 1 from sender
Received: Message 2 from sender
Received: Message 3 from sender
Received: Message 4 from sender
Received: Message 5 from sender

 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号