Unix消息队列实例

我们创建三个文件,一个recieve.c和pa.c,pb.c 。用recieve.c来监听pa.c和pb.c发送的消息:

 recieve.c代码:

#include<t_stdio.h>#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <errno.h>
#define MSG_TYPE	0
#define MSG_TYPE_A	10
#define MSG_TYPE_B	11//自定义消息类型int main(int argc,char * argv[]){//定义自己的消息数据结构体struct  msgmbuf{long mtype;char mtext[100];int pid;};//创建key值key_t key= ftok(".",1);if(key==-1)E_MSG("ftok",-1);//创建消息队列, 如果内核不存在队列就创建int msg= msgget(key,IPC_CREAT|0666);if(msg==-1)E_MSG("msgget",-1);//定义一个消息变量用来接收消息struct msgmbuf m_msg;//定义一个整数用来获取监听信息的字节数int retval; //开始监听while(1){retval= msgrcv(msg,&m_msg,sizeof(m_msg),MSG_TYPE, IPC_NOWAIT);//IPC_NOWAIT,不等待,即不阻塞if((retval == -1)){if (errno == ENOMSG) { // 没有消息continue; // 跳过本次循环,继续监听} else {perror("msgrcv error");return -1;}}else if(retval>0){printf("[PID:%d], msg type:%ld, msg:%s\n",m_msg.pid,m_msg.mtype,m_msg.mtext);if(strncmp(m_msg.mtext, "exit", 4) == 0)//可以指定长度为4时strlen(msg.mtext)才进行比较,仅仅对exit生效{break;}}} //删除消息队列msgctl(msg,IPC_RMID, NULL);return 0;
}

pa.c

#include <t_stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>#define MSG_TYPE_A	10
struct msgmbuf 
{long mtype;       /* message type, must be > 0 */char mtext[100];    /* message data */int pid;
};int main(void){//创建key值key_t key= ftok(".",1);if(key==-1)E_MSG("ftok",-1);//创建消息队列, 如果内核不存在队列就创建int msg_id = msgget(key, 0);if (msg_id == -1) {// 如果获取失败,尝试创建消息队列msg_id = msgget(key, IPC_CREAT | 0x0666);if (msg_id == -1) E_MSG("msgget", -1);}//定义一个消息变量用来接收消息struct msgmbuf msg;msg.pid=getpid();//获取当前进程pidmsg.mtype=MSG_TYPE_A;//开始循环写入while(1){//写入数据fgets(msg.mtext,sizeof(msg.mtext),stdin);//发送数据msgsnd(msg_id,&msg,sizeof(msg),0);if(strncmp(msg.mtext, "exit", 4) == 0){break;}}msgctl(msg_id, IPC_RMID, NULL);return 0;
}

理解:

监听代码(接收者)

  1. 创建Key值

    • ftok函数用来生成一个唯一的key值,这个值基于一个文件(在这里是当前目录.)和一个项目标识符(这里是1)。
    • 这个key值用于标识消息队列,确保发送者和接收者能够访问同一个队列。
  2. 创建消息队列

    • msgget函数用于创建一个新的消息队列或获取一个已经存在的消息队列的标识符。 -IPC_CREAT标志告诉系统如果队列不存在则创建它,0666是队列的权限。
  3. 定义消息结构体

    • msgmbuf结构体定义了消息的类型(mtype)和消息内容(mtext)以及发送进程的PID。
  4. 消息接收循环

    • msgrcv函数用于从消息队列中接收消息。
    • IPC_NOWAIT标志表示如果队列中没有消息,msgrcv不会阻塞,而是立即返回。
    • 如果msgrcv返回-1,并且错误码是ENOMSG,表示队列中没有消息,程序继续循环监听。
    • 如果接收到消息,程序会打印出消息内容和类型。
    • 如果消息内容是"exit",程序会跳出循环。
  5. 删除消息队列

    • msgctl函数用于控制消息队列,IPC_RMID标志表示删除消息队列。

发送消息代码(发送者)

  1. 创建Key值

    • 和接收者一样,发送者也需要创建一个key值来访问同一个消息队列。
  2. 获取或创建消息队列

    • 发送者尝试获取一个已经存在的消息队列的标识符。
    • 如果获取失败,它会尝试创建一个新的消息队列。
  3. 定义消息结构体并初始化

    • msgmbuf结构体用于存储发送的消息。
    • 进程ID(PID)被存储在消息结构体中,以便接收者知道哪个进程发送了消息。
  4. 消息发送循环

    • 程序从标准输入读取字符串,并将其存储在消息结构体的mtext字段中。
    • msgsnd函数用于将消息发送到消息队列。
    • 如果输入的是"exit",程序会跳出循环。
  5. 删除消息队列

    • 和接收者一样,发送者在结束前也会删除消息队列。

为什么两个代码都要创建Key值和消息队列?

  • 创建Key值

    • 在Unix系统中,每个IPC结构(如消息队列、共享内存、信号量)都有一个与之关联的唯一键(key)。这个键是由ftok生成的,它确保了不同的进程能够通过同一个键访问同一个IPC结构。
    • 发送者和接收者需要使用相同的key值来确保它们能够互相通信。
  • 创建消息队列

    • 消息队列是IPC的一种形式,它允许一个或多个进程写入和读取数据。
    • 在Unix中,消息队列是由操作系统管理的,因此需要使用msgget来创建或访问一个已经存在的消息队列。
    • 发送者和接收者都需要访问消息队列,因此它们都需要创建或获取队列的标识符。

这两个程序通过消息队列进行通信。发送者将消息放入队列,接收者从队列中读取消息。它们通过使用相同的key值来确保它们可以访问同一个消息队列。

扩展:我当时一直不明白两个文件为什么都要创建key值,以及为什么创建相同key值,以及如何实现利用消息队列进行通信:

在Unix-like系统中,ftok函数用于从一个路径名和一个项目标识符(通常是整数)生成一个key值。这个key值用于进程间通信(IPC),比如消息队列、共享内存和信号量。

ftok函数的定义如下:

复制

key_t ftok(const char *pathname, int proj_id);
  • pathname是一个指向现有路径名的指针,通常是文件路径。
  • proj_id是一个整数,用于进一步区分不同的key值。

重要的是要理解,ftok生成的key值不仅取决于pathname,还取决于proj_id。这意味着即使是在相同的路径下,只要proj_id不同,生成的key值也会不同。相反,即使是在不同的路径下,只要pathnameproj_id相同,生成的key值也会相同。

因此,一个文件路径并不限制只能创建一个key值。实际上,你可以使用相同的文件路径和不同的proj_id来生成多个不同的key值,每个key值可以用于创建或访问不同的IPC资源。

例如:

复制

key_t key1 = ftok("/path/to/file", 1);
key_t key2 = ftok("/path/to/file", 2);

在上面的例子中,key1key2将会是不同的,即使它们是基于相同的文件路径生成的。

总结来说,ftok生成的key值是唯一的,只要pathnameproj_id的组合是唯一的。这意味着在不同的文件路径下可以生成相同的key值,只要proj_id相同;同时,在相同的文件路径下也可以生成不同的key值,只要proj_id不同。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/786921.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数据库理论

什么是表空间 表空间是数据库的逻辑划分&#xff0c;一个表空间只能属于一个数据库。所有的数据库对象都存放在指定的表空间中。但主要存放的是表&#xff0c; 所以称作表空间。Oracle数据库中至少存在一个表空间&#xff0c;即SYSTEM的表空间。表空间不足怎么办 先查看Oracle数…

计算机断层扫描采集软件

计算机断层扫描采集软件&#xff0c;通过x采集2D和3D投影&#xff0c;利用投影可以进行体积的重建&#xff0c;软件还集成了CNC和x射线球管控制功能&#xff0c; 用PDM进程数据管理器对数据和进程进行管理&#xff0c;并对外提供与数据通信的接口 PDM通信基于AMQP&#xff0c…

Apple Vision Pro 的组成结构

Apple Vision Pro的组成结构相当复杂且精密,下面我将为您详细介绍其主要组成部分: 3D层压抛光玻璃面板与铝合金框架:Vision Pro的正面设计独特,类似于一副滑雪镜。它采用一块弧形的3D层压抛光玻璃面板,与定制的铝合金框架紧密结合。这个框架在用户的脸周围轻轻弯曲,以更好…

EasyExcel 复杂表头的导出(动态表头和静态表头)

问题&#xff1a;如图&#xff0c;1部分的表头是动态的根据日期变化&#xff0c;2部分是数据库对应的字段&#xff0c;静态不变的&#xff1b; 解决方案&#xff1a;如果不看1的部分&#xff0c;2部分内容可以根据实体类注解的方式导出&#xff0c;那么我们是不是可以先将动态表…

Centos7 安装 Oracle19c

下载oracle预安装包 wget http://yum.oracle.com/repo/OracleLinux/OL7/latest/x86_64/getPackage/oracle-database-preinstall-19c-1.0-1.el7.x86_64.rpm 下载19c安装包 https://www.oracle.com/cn/database/technologies/oracle-database-software-downloads.html#19c 选择…

Oracle 数据库工作中常用知识点:sql语法与常用函数

.to_date()函数 to_date函数是Oracle特有的函数&#xff0c;该函数用来做日期转换。 举例&#xff1a; SELECT TO_DATE(‘2006-05-01 19:25:34’, ‘YYYY-MM-DD HH24:MI:SS’) FROM DUAL   日期格式&#xff1a;     YYYY、YYY、YY 分别代表4位、3位、2位的数字年    …

RESTfull接口访问Elasticsearch

【数据库的健康值】 curl -X GET "ip:9200/_cat/health" 【查看所有索引】 curl -X GET "ip:9200/_cat/indices?v" 【查看索引index_name】 curl -X GET "ip:9200/索引?pretty" 【创建索引/文档】 PUT "ip:9200/索引/文档id" {请…

Java中的原型模式

Java中的原型模式是一种创建型设计模式&#xff0c;它通过复制已有对象来创建新的对象&#xff0c;而不是每次都创建一个新的实例。这个模式适用于那些创建新对象的成本较大或者需要保持对象属性一致性的场景。在Java中&#xff0c;通常通过实现Cloneable接口并重写Object类中的…

计算机网络-HTTP相关知识-HTTPS基础

HTTP与HTTPS的区别&#xff1a; HTTPS在TCP和HTTP网络层之间加入了SSL/TLS安全协议层。这个安全协议层可以对数据进行加密&#xff0c;确保数据在传输过程中的安全。HTTPS在TCP三次握手之后&#xff0c;还需进行SSL/TLS的握手过程。这个握手过程主要是为了在客户端和服务器之间…

超声波清洗机是干什么用的?2024年有用的超声波清洗机推荐

随着科技的不断进步&#xff0c;超声波清洗机已经成为了家庭和专业场所不可或缺的高效清洁工具。它利用超声波波动产生的微小气泡来清洁物品表面及细缝中的污渍&#xff0c;实现深层次的清洁效果。特别是对于眼镜这样的精密物品&#xff0c;定期进行深度清洁不仅能够确保视觉的…

【算法刷题day10】Leetcode:232.用栈实现队列、225. 用队列实现栈

文章目录 Leetcode 232.用栈实现队列解题思路代码总结 Leetcode 225. 用队列实现栈解题思路代码总结 stack、queue和deque对比 草稿图网站 java的Deque Leetcode 232.用栈实现队列 题目&#xff1a;232.用栈实现队列 解析&#xff1a;代码随想录解析 解题思路 一个栈负责进&a…

【C++】每日一题 12 整数转罗马数字

罗马数字包含以下七种字符&#xff1a; I&#xff0c; V&#xff0c; X&#xff0c; L&#xff0c;C&#xff0c;D 和 M。 字符 数值 I 1 V 5 X 10 L 50 C 100 D 500 M 1000 例如&#xff0c; 罗马数字 2 写做 II &#xff0c;即为两个并列的 1。12 写做 XII &#xff0c;即为…

前端二维码生成工具小程序:构建营销神器的技术解析

摘要&#xff1a; 随着数字化营销的不断深入&#xff0c;二维码作为一种快速、便捷的信息传递方式&#xff0c;已经广泛应用于各个领域。本文旨在探讨如何通过前端技术构建一个功能丰富、操作简便的二维码生成工具小程序&#xff0c;为企业和个人提供高效的营销支持。 一、引言…

如何使用 Grep 命令在 Linux 中搜索文件

如何使用 Grep 命令在 Linux 中搜索文件 Grep 命令代表 “全局正则表达式输出” 是 Linux 中最强大和最常用的命令之一。 Grep 在一个或多个输入文件中搜索与给定模式匹配的行&#xff0c;并将每个匹配行写入标准输出。 如果没有指定文件&#xff0c;则 grep 从标准输入读取&…

什么是过载

宇航员相关知识会涉及到过载&#xff0c;导弹相关知识也会涉及到过载&#xff0c;如导弹的过载加速度&#xff0c;什么是过载呢&#xff1f;博主从B站上看到一UP主讲的很好&#xff0c; 该up主视频链接&#xff1a; 过载是什么_哔哩哔哩_bilibili 内容截图如下&#xff1a;

Linux centos7离线搭建FTP

1、下载、安装ftp 下载ftp安装包&#xff0c;可以从rpm下载站搜索合适的版本&#xff0c;使用wget命令下载。 wget https://mirrors.aliyun.com/centos/7/os/x86_64/Packages/vsftpd-3.0.2-28.el7.x86_64.rpm 安装&#xff1a; rpm -ivh vsftpd-3.0.2-28.el7.x86_64.rpm 2…

钉钉服务端API报错 43008 参数需要multipart类型

钉钉服务端API报错 43008 参数需要multipart类型 problem 使用媒体文件上传接口&#xff0c;按照文档输入参数&#xff0c;结果返回报错 # 参数 {"access_token": "xxx""type": "image","media": "/Users/xxx/xxx/s…

《QT实用小工具·二》图片文字转base64编码

1、概述 源码放在文章末尾 base64编码转换类 图片转base64字符串。base64字符串转图片。字符转base64字符串。base64字符串转字符。后期增加数据压缩。Qt6对base64编码转换进行了重写效率提升至少200%。 下面是demo演示&#xff1a; 项目部分代码如下所示&#xff1a; #ifn…

android aosp文件目录详解

目录 1.frameworks 2.packages 3.kernel 4.device 5.vendor 6.build 7.system 8.external 9.hardware 10.u-boot 11.dalvik 12.development 13.developers Android Open Source Project&#xff08;AOSP&#xff09;包含了 Android 平台的所有源代码。在 AOSP 中&…

探索检索增强生成和微调技术在金融服务领域的应用

引言&#xff1a; 在金融服务领域&#xff0c;随着人工智能技术的快速发展&#xff0c;语言模型的应用变得越来越广泛。本文将探讨检索增强生成&#xff08;RAG&#xff09;和微调技术在金融服务领域的应用&#xff0c;以及它们在不同模型大小和应用场景中的适用性。 一、检索…