进程间通信(2)-消息队列

Linux 中的消息队列是一种进程间通信(IPC)机制,允许不同进程之间通过消息进行通信。
 

消息队列中的相关函数:

msgget:创建或打开一个消息队列。
函数原型:int msgget(key_t key, int msgflg);
参数:
key:消息队列的键值,用于标识消息队列。
msgflg:标志参数,用于指定消息队列的创建方式和权限。
返回值:成功时返回消息队列的标识符(非负整数),失败时返回 -1。


msgctl:对消息队列进行控制。
函数原型:int msgctl(int msqid, int cmd, struct msqid_ds *buf);
参数:
msqid:消息队列的标识符。
cmd:控制命令,用于指定执行的操作。
buf:指向 struct msqid_ds 结构的指针,用于传递或接收消息队列的状态信息。
返回值:成功时返回0,失败时返回 -1。


msgsnd:向消息队列发送消息。
函数原型:int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
参数:
msqid:消息队列的标识符。
msgp:指向要发送的消息的指针。
msgsz:消息的大小(以字节为单位)。
msgflg:标志参数,用于指定发送消息的行为。
返回值:成功时返回0,失败时返回 -1。


msgrcv:从消息队列接收消息。
函数原型:ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
参数:
msqid:消息队列的标识符。
msgp:指向存储接收消息的缓冲区的指针。
msgsz:缓冲区的大小(以字节为单位)。
msgtyp:指定所接收消息的类型。
msgflg:标志参数,用于指定接收消息的行为。
返回值:成功时返回接收到的消息的大小(以字节为单位),失败时返回 -1
对于ftok补充一点,ftok 函数是一个用于生成 System V IPC(Inter-Process Communication,进程间通信)中键值的函数。在 System V IPC 中,诸如消息队列、共享内存和信号量等资源都需要一个唯一的键值来标识。
ftok 函数的原型如下:
key_t ftok(const char *pathname, int proj_id);

它接受两个参数:
pathname:一个指向文件的路径名的指针。通常情况下,你可以选择一个现有的文件,该文件的存在与否对 ftok 函数的结果不会产生影响,因为它只关注文件的索引节点号(inode number)和项目 ID(proj_id)。
proj_id:一个用户定义的整数,用于生成键值的低8位。通常情况下,你可以为不同的 IPC 资源设置不同的项目 ID,以确保它们的键值不冲突。
ftok 函数将 pathname 参数指定的文件的索引节点号和 proj_id 参数合并起来,然后通过一系列位操作生成一个唯一的键值。这个键值将作为 System V IPC 中资源的标识符,用于创建或获取相应的资源。
需要注意的是,ftok 函数的返回值是一个键值 key_t,这个键值会传递给 msgget、shmget 或 semget 等函数,用于创建或获取对应的消息队列、共享内存或信号量。
更多关于ftok函数的解析可见:ftok()函数深度解析
说白了ftok函数就是根据文件生成一个key_t类型的值,key_t一般是一个长整型,那完全可用用一个长整型的数进行替换即可,前提是该长整型数没有作为key_t使用
 

发送消息的程序msg1.c

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

#define MAX_MSG_SIZE 1024
#define MSG_TYPE 1

// 定义消息结构体
struct msg_buffer {
    long msg_type;
    char msg_text[MAX_MSG_SIZE];
};

int main() {
    int i;
    int msg_id;
    key_t key;
    struct msg_buffer message;

    // 生成一个唯一的键值
    if ((key = ftok("lethe1203", 'B')) == -1) {
        perror("ftok");
        exit(EXIT_FAILURE);
    }

    // 创建一个消息队列,如果不存在则创建,否则打开
    if ((msg_id = msgget(key, 0666 | IPC_CREAT)) == -1) {    // 这里完全可用把key替换为12345678等,去掉"生成一个唯一的键值"的步骤
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    printf("Sending multiple messages to the queue...\n");

    // 发送多条消息到队列
    for (i = 1; i <= 5; ++i) {
        // 设置消息的类型为 MSG_TYPE
        message.msg_type = MSG_TYPE;

        // 构造消息内容
        sprintf(message.msg_text, "This is message %d from sender", i);

        // 发送消息
        if (msgsnd(msg_id, &message, sizeof(message.msg_text), 0) == -1) {
            perror("msgsnd");
            exit(EXIT_FAILURE);
        }

        printf("Message %d sent to queue.\n", i);

        // 为了演示,发送完一条消息后暂停五秒
        sleep(5);
    }

    printf("All messages sent to the queue.\n");

    return 0;
}

 

接收消息的程序msg2.c:

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

#define MAX_MSG_SIZE 1024
#define MSG_TYPE 1

// 定义消息结构体
struct msg_buffer {
    long msg_type;
    char msg_text[MAX_MSG_SIZE];
};

int main() {
    int msg_id;
    key_t key;
    struct msg_buffer message;

    // 生成一个唯一的键值
    if ((key = ftok("lethe1203", 'B')) == -1) {
        perror("ftok");
        exit(EXIT_FAILURE);
    }

    // 获取现有的消息队列,如果不存在则创建
    if ((msg_id = msgget(key, 0666 | IPC_CREAT)) == -1) {    // 这里完全可用把key替换为12345678等,去掉"生成一个唯一的键值"的步骤
        perror("msgget");
        exit(EXIT_FAILURE);
    }

    printf("Receiving messages from the queue...\n");

    // 从队列中接收消息
    while (1) {
        // 接收消息
        if (msgrcv(msg_id, &message, sizeof(message.msg_text), MSG_TYPE, 0) == -1) {
            perror("msgrcv");
            exit(EXIT_FAILURE);
        }

        // 打印接收到的消息
        printf("Message received: %s\n", message.msg_text);
    }

    return 0;
}
 

代码执行结果:

0
 
 
 
 
 
 
 
 
posted @ 2024-04-04 06:39  lethe1203  阅读(36)  评论(0编辑  收藏  举报