首页 > 系统相关 >【Linux】进线程间通信之消息队列

【Linux】进线程间通信之消息队列

时间:2024-10-17 14:49:19浏览次数:9  
标签:IPC return 队列 间通信 int 线程 消息 Linux include

二、消息队列

1.什是消息队列

​ 在 Linux 中,进程间通信(IPC)的消息队列是一种在进程之间传递数据的机制。它允许不同的进程以异步的方式发送和接收消息。

在这里插入图片描述

2.消息队列的特点
  1. 消息队列可以实现多个进程之间的通信,一个进程可以向消息队列发送消息,而另一个进程可以从消息队列中接收消息。
  2. 消息队列中的消息是有类型的,可以根据消息的类型进行选择性接收。
  3. 消息队列具有一定的缓存能力,可以在发送方和接收方处理速度不匹配时起到缓冲作用。
3.使用消息队列的步骤
(1)包含头文件

代码示例

   #include <sys/types.h>
   #include <sys/ipc.h>
   #include <sys/msg.h>
(2)创建或获取消息队列

ftok函数

key_t ftok(const char *pathname, int proj_id);
  • 作用:生成一个唯一的键值,通常用于创建消息队列、共享内存等 IPC 对象的标识。
  • 参数:
    • pathname:一个已存在的文件路径名。
    • proj_id:一个字符,用于生成唯一的键值。
  • 返回值:成功时返回一个唯一的键值,失败时返回 -1。

msgget函数

int msgget(key_t key, int msgflg);
  • 作用:创建或获取一个消息队列。
  • 参数:
    • key:由ftok函数生成的键值。
    • msgflg:标志位,可以是IPC_CREAT(如果消息队列不存在则创建)、IPC_EXCL(如果消息队列已存在则出错)以及权限标志(如0666)的组合。
  • 返回值:成功时返回消息队列的标识符,失败时返回 -1。

代码示例

    key_t key = ftok(".", 'a');
    int msgid = msgget(key, IPC_CREAT | 0666);
    if (msgid == -1) {
       perror("msgget");
       return -1;
    }
(3)发送消息

定义一个消息结构体,然后使用msgsnd函数向消息队列发送消息

代码示例

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

msgsnd函数

int msgsnd(int msqid, const void *msgp, size_t msgsz, int msgflg);
  • 作用:向消息队列发送消息。
  • 参数:
    • msgid:消息队列的标识符。
    • msgp:指向要发送的消息结构体的指针。
    • msgsz:消息正文的长度。
    • msgflg:标志位,通常为 0 或IPC_NOWAIT(如果消息队列已满则不阻塞立即返回错误)。
  • 返回值:成功时返回 0,失败时返回 -1。

代码示例

//定义消息结构体
struct msgbuf msg;
   msg.mtype = 1;
   strcpy(msg.mtext, "Hello, message queue!");
   if (msgsnd(msgid, &msg, sizeof(msg.mtext), 0) == -1) {
       perror("msgsnd");
       return -1;
   }
(4)接收消息

msgrcv函数

ssize_t msgrcv(int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg);
  • 作用:从消息队列中接收消息。
  • 参数:
    • msgid:消息队列的标识符。
    • msgp:指向接收消息的缓冲区结构体的指针。
    • msgsz:消息正文的最大长度。
    • msgtyp:要接收的消息类型。
    • msgflg:标志位,可以是IPC_NOWAIT(如果没有满足条件的消息则不阻塞立即返回错误)等。
  • 返回值:成功时返回实际读取的字节数,失败时返回 -1。

代码示例

   struct msgbuf rcv_msg;
   if (msgrcv(msgid, &rcv_msg, sizeof(rcv_msg.mtext), 1, 0) == -1) {
       perror("msgrcv");
       return -1;
   }
   printf("Received message: %s\n", rcv_msg.mtext);
(5)删除消息队列

msgctl函数

int msgctl(int msqid, int cmd, struct msqid_ds *buf);
  • 作用:对消息队列进行控制操作,如删除消息队列、获取消息队列的状态信息等。
  • 参数:
    • msgid:消息队列的标识符。
    • cmd:控制命令,可以是IPC_STAT(获取消息队列的状态信息并存入buf指向的结构体中)、IPC_SET(设置消息队列的属性)、IPC_RMID(删除消息队列)等。
    • buf:指向一个缓冲区,用于存储或设置消息队列的状态信息,具体取决于cmd的值。
  • 返回值:成功时返回相应的状态信息或 0,失败时返回 -1。

代码示例

   if (msgctl(msgid, IPC_RMID, NULL) == -1) {
       perror("msgctl");
       return -1;
4.用消息队列的方式完成进线程间的简单通信:
(1)发送消息

代码示例

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

//创建消息结构体
typedef struct msgbuf{
    long mtype;
    char mtext[32];
}MSG;

int main(int argc, char *argv[])
{ 
    //创建key值
    key_t mykey = ftok(".",'b');
    if(mykey < 0)
    {
        perror("ftok");
        return -1;
    }
    //msgget()--创建或获取消息队列
    int msgfd = msgget(mykey, 0664 |IPC_CREAT);
    if(msgfd < 0)
    {
        perror("msgget");
        return -1;
    }
    //准备好需要发送的消息,初始化结构体
    MSG message1 = {1,"hello"};
    MSG message2 = {2,"world"};
    MSG message3 = {3,"niaho"};
    
    //magsnd()--发送消息
    msgsnd(msgfd,&message2,sizeof(MSG)-8,0);
    return 0;
} 
(2)接收消息

代码示例

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

//创建消息结构体
typedef struct msgbuf{
    long mtype;
    char mtext[32];
}MSG;

int main(int argc, char *argv[])
{ 
    //创建key值
    key_t mykey = ftok(".",'b');
    if(mykey < 0)
    {
        perror("ftok");
        return -1;
    }
    //msgget()--创建或获取消息队列
    int msgfd = msgget(mykey, 0664 |IPC_CREAT);
    if(msgfd < 0)
    {
        perror("msgget");
        return -1;
    }
    //magrcv()--接受消息
    MSG message2;
    int ret = msgrcv(msgfd,&message2,sizeof(MSG)-8,2,0);
    if(ret < 0)
    {
        perror("read");
        return -1;
    }
    printf("message = %s\n",message2.mtext);
    return 0;
} 

标签:IPC,return,队列,间通信,int,线程,消息,Linux,include
From: https://blog.csdn.net/2201_75349894/article/details/143018948

相关文章

  • 国产linux系统(银河麒麟,统信uos)使用 PageOffice 在线打开 word文件动态插入图片并设置
    PageOffice国产版:支持信创系统,支持银河麒麟V10和统信UOS,支持X86(intel、兆芯、海光等)、ARM(飞腾、鲲鹏、麒麟等)、龙芯(LoogArch)芯片架构。查看本示例演示效果本示例关键代码的编写位置Vue+Springboot注意本文中展示的代码均为关键代码,复制粘贴到您的项目中,按照实际的情况,例如......
  • Linux grep 命令
    Linux中的grep命令是一个非常强大的文本搜索工具,它能够快速地在文件中搜索包含特定模式的行,并将其输出到标准输出。grep是"GlobalRegularExpressionPrint"的缩写,意味着它会打印出包含全局正则表达式匹配的所有行。基本语法grep[选项]模式[文件...]参数说明-i或--igno......
  • 剖析线程池实现原理
    前置推荐阅读:java并发之线程池使用-CSDN博客自定义实现一个带监控的线程池首先我们继承ThreadPoolExecutor,实现构造函数以及重写beforeExecute和afterExecute两个函数,具体调用我们会在代码实现层面进行详细的分析。importjava.util.concurrent.*;publicclassAsyncTh......
  • Linux网络篇
    1、请描述 TCP/IP协议中主机与主机之间通信的三要素IP地址(IPaddress)子网掩码(subnetmask)IP默认路由(IProuter)2、请描述 A、B、C 三类IP地址的默认子网掩码A类255.0.0.0B类255.255.0.0C类255.255.255.03、请描述预留给企业的私有网络使用的私有IP有哪......
  • Linux系统服务篇
    1、请描述SMTP及POP3分别是什么协议、 作用及端口号SMTP:简单邮件传输协议,用于发送和接收邮件,端口号25POP3:邮局协议版本3,用于客户端接收邮件,端口号1102、请描述http及https分别是什么协议、作用及端口号HTTP:超文本传输协议,用于传输Internet浏览器使用的普通文本、......
  • RockyLinux9,RHEL9修改统一的网卡名称
    使用udev规则配置用户自定义网络接口名称1、识别您要重命名的网络接口:iplinkshow1:lo:<LOOPBACK,UP,LOWER_UP>mtu65536qdiscnoqueuestateUNKNOWNmodeDEFAULTgroupdefaultqlen1000link/loopback00:00:00:00:00:00brd00:00:00:00:00:002:e......
  • 【Linux】<互斥量>解决<抢票问题>——【多线程竞争问题】
    前言大家好吖,欢迎来到YY滴Linux系列,热烈欢迎!本章主要内容面向接触过C++的老铁主要内容含:欢迎订阅YY滴C++专栏!更多干货持续更新!以下是传送门!YY的《C++》专栏YY的《C++11》专栏YY的《Linux》专栏YY的《数据结构》专栏YY的《C语言基础》专栏YY的《初学者易错点》......
  • 常见的Linux面试题及答案解析,哪些你还不会?
    Linux面试题1、绝对路径用什么符号表示?当前目录、上层目录用什么表示?主目录用什么表示?切换目录用什么命令?2、怎么查看当前进程?怎么执行退出?怎么查看当前路径?3、怎么清屏?怎么退出当前命令?怎么执行睡眠?怎么查看当前用户id?查看指定帮助用什么命令?4、Ls命令执行什么功能?可......
  • ACME续签证书在Linux云服务器上安装指南
    环境供应商;阿里云服务器操作系统:LinuxCentosStream9操作系统静态代理:Nginx前言我这边使用https://get.acme.sh方式无法正常使用,会卡在这个页面,无任何进度的信息。最终我使用了gitclone的方式进行安装。正文clone项目下来,并进行install初始安装ACME环境gitcloneht......
  • Android15音频进阶之4种调试线程死锁利器(八十九)
    简介:CSDN博客专家、《Android系统多媒体进阶实战》一书作者新书发布:《Android系统多媒体进阶实战》......