欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 文旅 > 美景 > Linux下消息队列详解

Linux下消息队列详解

2025/5/10 16:52:55 来源:https://blog.csdn.net/m0_74091159/article/details/142470690  浏览:    关键词:Linux下消息队列详解

在Linux下,消息队列(Message Queues)是进程间通信(IPC)的一种重要机制,它允许进程以异步的方式进行数据交换。消息队列通过内核来存储消息,当一个进程发送消息时,消息将被放入队列中,另一个进程则可以从队列中取出消息。相比于管道,消息队列支持有序、带类型的消息传递,并且不会像管道一样覆盖之前的消息。

消息队列的特点

  • 异步通信:消息队列提供进程之间的异步通信,一个进程可以将消息发送到队列中而不需要等待接收进程。
  • 消息类型:每个消息都带有一个类型,接收进程可以根据消息类型选择性地接收消息。
  • 有序性:消息队列按照FIFO的顺序存储消息,即先发送的消息会先被接收,除非明确指定接收某种类型的消息。
  • 持久性:消息队列存储在内核中,并且在消息队列被显式删除之前,队列中的消息可以持久存在,跨越多个进程的生命周期。

常用的消息队列相关函数

  1. msgget
    msgget用于创建新的消息队列或获取一个现有的消息队列标识符(ID)。它的原型如下:

    int msgget(key_t key, int msgflg);

    • key:消息队列的键值,可通过ftok生成。
    • msgflg:控制消息队列的创建行为。常用的标志位包括:
      • IPC_CREAT:如果消息队列不存在,则创建一个新队列。
      • IPC_EXCL:与IPC_CREAT一起使用时,如果队列已存在则返回错误。

    示例

    int msgid = msgget(IPC_PRIVATE, IPC_CREAT | 0666); if (msgid == -1) { perror("msgget failed"); }

  2. msgsnd
    msgsnd函数用于向消息队列发送消息。它的原型如下:

    int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);

    • msqid:消息队列的ID。
    • msgp:指向消息的指针,消息通常需要包含消息类型。
    • msgsz:消息数据的大小(不包括类型部分)。
    • msgflg:控制发送行为。常用的标志位包括:
      • IPC_NOWAIT:如果消息队列已满,函数立即返回而不是阻塞。

    示例

    struct msgbuf {long mtype; // 消息类型char mtext[100]; // 消息内容
    };struct msgbuf msg;
    msg.mtype = 1; // 设置消息类型
    strcpy(msg.mtext, "Hello, World!");if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) == -1) {perror("msgsnd failed");
    }
    

  3. msgrcv
    msgrcv函数用于从消息队列接收消息。它的原型如下:

    ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);

    • msgtyp:指定接收的消息类型。如果msgtyp为0,接收队列中的第一个消息;如果msgtyp为正,接收指定类型的消息。
    • msgflg:控制接收行为,IPC_NOWAIT表示如果没有可用消息则立即返回。

    示例

    if (msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0) == -1)
    { perror("msgrcv failed"); 
    } else { printf("Received message: %s\n", msg.mtext);
    }
  4. msgctl
    msgctl函数用于控制消息队列,比如删除队列、获取队列信息等。它的原型如下:

    int msgctl(int msqid, int cmd, struct msqid_ds *buf);

    • cmd:控制命令,常用的有:
    • IPC_RMID:删除消息队列。IPC_STAT:获取消息队列的状态信息。IPC_SET:设置消息队列的属性。buf:用于保存或设置消息队列的状态信息。

    示例

    if (msgctl(msgid, IPC_RMID, NULL) == -1) { perror("msgctl failed"); }

错误处理

在使用消息队列相关函数时,经常会遇到一些典型的错误码,如:

EACCES:权限不足,无法访问消息队列。 EEXIST:当使用IPC_EXCL标志时,队列已存在。 ENOENT:当没有IPC_CREAT标志时,队列不存在。 ENOMSG:没有匹配类型的消息可接收。

使用示例

下面是一个简单的消息队列示例,展示了如何在两个进程之间进行消息发送与接收:

发送进程

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>
#include <string.h>struct msgbuf {long mtype;char mtext[100];
};int main() {key_t key = ftok("progfile", 65);int msgid = msgget(key, 0666 | IPC_CREAT);struct msgbuf msg;msg.mtype = 1;strcpy(msg.mtext, "Hello from sender!");msgsnd(msgid, &msg, sizeof(msg.mtext), 0);printf("Message sent: %s\n", msg.mtext);return 0;
}

接收进程

#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <stdio.h>struct msgbuf {long mtype;char mtext[100];
};int main() {key_t key = ftok("progfile", 65);int msgid = msgget(key, 0666 | IPC_CREAT);struct msgbuf msg;msgrcv(msgid, &msg, sizeof(msg.mtext), 1, 0);printf("Message received: %s\n", msg.mtext);msgctl(msgid, IPC_RMID, NULL); // 删除消息队列return 0;
}

关键标志和选项

  • IPC_CREAT:如果消息队列不存在,创建新队列。
  • IPC_EXCL:和IPC_CREAT一起使用时,如果消息队列已存在,返回错误。
  • IPC_RMID:删除消息队列。

总结

消息队列是Linux下进程间通信的重要工具,适用于异步、有序和带类型的数据传递。通过使用msggetmsgsndmsgrcvmsgctl等函数,开发者可以方便地在不同进程之间交换数据。使用时需要特别注意权限、错误处理,以及在适当的时候删除消息队列,以避免资源泄漏。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词