消息队列 (msgget, msgsnd, msgrcv, msgctl)的使用

news2025/1/8 6:20:11

如何使用 ftok 函数生成消息队列、共享内存或信号量所需的唯一标识符(键值) 

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

int main()
{
//声明两个 key_t 类型的变量 key1 和 key2。key_t 是一个整数类型,用于表示键值。
	key_t key1,key2;
//ftok 函数用于根据文件路径和项目标识符生成一个唯一的键值。
//ftok(".", 10) 和 ftok(".", 20) 分别生成了两个不同的键值,
//"." 表示当前目录,10 和 20 是项目标识符,保证生成不同的键值。
	key1 = ftok(".",10);
	key2 = ftok(".",20);
	printf("key1 = %d\n",key1);
	printf("key2 = %d\n",key2);
}

ftok 函数详解:

ftok 函数的作用是根据给定的文件路径和项目标识符生成一个唯一的 key_t 值,这个键值在创建消息队列、共享内存、信号量时作为标识符。该键值确保在同一系统中,不同的程序能够通过该键值来识别同一个资源。

key_t ftok(const char *pathname, int proj_id); 
  • pathname:指定用于生成 key_t 的文件路径。一般来说,我们可以选择现有的文件路径。为了避免影响文件系统,通常选择当前目录 "." 或某个特定的路径。
  • proj_id:一个项目标识符,用于区分不同的资源。它通常是一个整数值(如 1020)。即使文件路径相同,只要 proj_id 不同,ftok 生成的键值也会不同。

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

int main()
{
	key_t key1,key2;
	int msgid1,msgid2;
	
	//1. 申请消息队列的key值
	key1 = ftok(".",10);
	key2 = ftok(".",20);
	printf("key1 = %d\n",key1);
	printf("key2 = %d\n",key2);
	
	//2. 根据key值申请ID号
	msgid1 = msgget(key1,IPC_CREAT|0666);
	printf("msgid1 = %d\n",msgid1);
	
	msgid2 = msgget(key2,IPC_CREAT|0666);
	printf("msgid2 = %d\n",msgid2);
	
	return 0;
}

  1. msgid1 = msgget(key1, IPC_CREAT | 0666);

    • msgget 函数用于获取或创建一个消息队列。如果消息队列已经存在,它会返回一个消息队列的 ID。如果消息队列不存在,它会根据 key1 创建一个新的消息队列。
    • IPC_CREAT 是一个标志,表示如果消息队列不存在,则创建一个新的消息队列。0666 是权限位,表示消息队列的访问权限。0666 表示所有用户均可读写消息队列。
    • msgid1 保存创建或获取的消息队列 ID。msgid2 = msgget(key2, IPC_CREAT | 0666);
    • 同上,根据 key2 创建或获取第二个消息队列,msgid2 保存第二个消息队列的 ID。
  • msgget该函数用于创建或访问一个消息队列,返回一个消息队列的标识符(ID)。

    int msgget(key_t key, int msgflg);
    
    • key:消息队列的键值(由 ftok 函数生成)。
    • msgflg:控制消息队列创建或访问的标志,常用标志包括:
      • IPC_CREAT:如果消息队列不存在,则创建一个新的消息队列。
      • IPC_EXCL:和 IPC_CREAT 一起使用,表示如果消息队列已存在则返回错误。
      • 0666:指定消息队列的访问权限。

利用消息队列 (msgget, msgsnd, msgrcv, msgctl) 实现进程间通信(IPC)的基本操作

发送消息程序 (msgsend.c

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

// 定义消息的结构体
struct msgbuf {
    long mtype;       // 消息类型(必须为正整数)
    char mtext[50];   // 消息内容
};

int main() {
    key_t key;
    int msgid, ret;
    
    // 0. 定义消息变量,并赋值
    struct msgbuf buf;
    buf.mtype = 10;  // 设置消息类型为10
    bzero(&(buf.mtext), 50);  // 清空消息内容
    strcpy(buf.mtext, "hello"); // 设置消息内容为 "hello"
    
    // 1. 获取消息队列的 key 值
    key = ftok(".", 10);  // 使用当前目录和项目标识符10生成key
    printf("key = %d\n", key);
    
    // 2. 根据 key 值获取消息队列的 ID
    msgid = msgget(key, IPC_CREAT | 0666);  // 创建消息队列并设置权限
    printf("msgid : %d\n", msgid);
    
    // 3. 将数据发送到消息队列中
    ret = msgsnd(msgid, &buf, strlen(buf.mtext), 0);  // 发送消息
    if (ret == -1) {
        printf("msgsnd error!\n");
        exit(1);
    }
    
    return 0;
}

msgsnd(msgid, &buf, strlen(buf.mtext), 0): 向消息队列发送一条消息,mtype 是消息类型,mtext 是消息内容。strlen(buf.mtext) 用于传递消息内容的长度。

接收消息程序 (msgrcv.c)

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

// 定义消息的结构体
struct msgbuf {
    long mtype;       // 消息类型(必须为正整数)
    char mtext[50];   // 消息内容
};

int main() {
    key_t key;
    int msgid;
    int ret;
    struct msgbuf buf;
    bzero(&(buf.mtext), 50);
    
    // 1. 获取消息队列的 key 值
    key = ftok(".", 10);  // 使用当前目录和项目标识符10生成key
    printf("key = %d\n", key);
    
    // 2. 根据 key 值获取消息队列的 ID
    msgid = msgget(key, IPC_CREAT | 0666);  // 获取消息队列ID
    printf("msgid : %d\n", msgid);
    
    // 3. 从消息队列接收数据
    ret = msgrcv(msgid, &buf, sizeof(buf.mtext), 10, 0);  // 接收指定类型的消息
    if (ret < 0) {
        printf("msgrcv error!\n");
    }
    
    // 打印接收到的消息内容
    printf("buf.mtext = %s\n", buf.mtext);
    
    // 4. 删除消息队列
    msgctl(msgid, IPC_RMID, NULL);  // 删除消息队列
    return 0;
}
  • msgrcv(msgid, &buf, sizeof(buf.mtext), 10, 0): 从消息队列接收消息,指定接收类型为 10并将接收到的消息存储在 buf.mtextsizeof(buf.mtext) 表示接收消息的最大长度。msgrcv 会阻塞等待消息,直到接收到指定类型的消息。
  • msgctl(msgid, IPC_RMID, NULL): 删除消息队列。

关键点总结:

  1. 消息队列的创建与访问

    • 通过 ftok() 获取一个唯一的键值(key)。
    • 通过 msgget() 使用 key 获取或创建消息队列。
  2. 发送消息

    • 使用 msgsnd() 将消息发送到消息队列。消息由 mtype(类型)和 mtext(内容)组成。
  3. 接收消息

    • 使用 msgrcv() 从消息队列中接收消息,消息根据 mtype 被选取。
  4. 删除消息队列

    • 使用 msgctl() 删除消息队列。

注意事项:

  • 消息队列通过 mtype 字段区分消息类型,这样接收方可以根据需要接收特定类型的消息。
  • msgsnd()msgrcv() 都会返回 -1 表示出错,需检查返回值进行错误处理。
  • msgctl() 中的 IPC_RMID 用来删除消息队列,但通常在使用完消息队列之后执行。

这样,父子进程之间可以通过消息队列实现数据传输。

 

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

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

相关文章

四、对象图

对象图 、对象图概述 含义&#xff1a; 对象图显示了某一时刻的一组对象及它们之间的关系。 作用&#xff1a; 对象图可以看做是类图的实例&#xff0c;用来表达各个对象在某一时刻的状态。 组成&#xff1a; 对象图中的建模元素主要有对象和链&#xff0c;对象是类的实…

2025/1/4期末复习 密码学 按老师指点大纲复习

我们都要坚信&#xff0c;道路越是曲折&#xff0c;前途越是光明。 --------------------------------------------------------------------------------------------------------------------------------- 现代密码学 第五版 杨波 第一章 引言 1.1三大主动攻击 1.中断…

【已解决】Django连接mysql报错Did you install mysqlclient?

解决报错&#xff1a;from err django.core.exceptions.ImproperlyConfigured: Error loading MySQLdb module. Did you install mysqlclient&#xff1f; 在终端执行python manage.py makemigrations报错问题汇总 错误1&#xff1a;已安装mysqlclient&#xff0c;提示Did yo…

【C语言】可移植性陷阱与缺陷(七): 除法运算时发生的截断

在C语言编程中&#xff0c;除法运算可能会引发一些与可移植性相关的问题&#xff0c;特别是当涉及到整数除法时发生的截断&#xff08;truncation&#xff09;。不同平台对于整数除法的行为和处理方式可能会有所不同&#xff0c;这可能导致代码在不同编译器或硬件平台上的行为不…

有限元分析学习——Anasys Workbanch第一阶段笔记(7)对称问题预备水杯案例分析

目录 1 序言 2 水杯案例 2.1 添加新材料 2.2 水压设置 2.3 约束边界条件设置及其结果 2.3.1 全约束固定(压缩桌面、Fixed support固定水杯底面) 2.3.2 单方面位移约束(压缩桌面、Displacement约束软弹簧) 2.3.3 接触约束(不压缩桌面、Fixed support 固定桌面、Frictional…

Spring Boot(4)使用 IDEA 搭建 Spring Boot+MyBatis 项目全流程实战

文章目录 一、⚡搞个引言二、⚡开始搭建 Spring Boot 项目吧&#xff01;2.1 启动 IDEA 并创建新项目2.2 选择项目依赖2.3 完成项目创建 三、&#x1f4d8;项目结构剖析四、✍配置数据库连接五、✍ 创建 MyBatis 相关组件5.1 实体类&#xff08;Entity&#xff09;5.2 Mapper 接…

[服务器][教程]Ubuntu24.04 Server开机自动挂载硬盘教程

1. 查看硬盘ID ls -l /dev/disk/by-uuid可以看到对应的UUID所对应的分区 2. 创建挂载文件夹 创建好文件夹即可 3. 修改配置文件 sudo vim /etc/fstab把对应的UUID和创建的挂载目录对应即可 其中# Personal mount points下面的是自己新添加的 &#xff1a;分区定位&#xff…

抢先体验:人大金仓数据库管理系统KingbaseES V9 最新版本 CentOS 7.9 部署体验

一、简介 KingbaseES 是中国人大金仓信息技术股份有限公司自主研发的一款通用关系型数据库管理系统&#xff08;RDBMS&#xff09;。 作为国产数据库的杰出代表&#xff0c;它专为中国市场设计&#xff0c;广泛应用于政府、金融、能源、电信等关键行业&#xff0c;以高安全性…

家教老师预约平台小程序系统开发方案

家教老师预约平台小程序系统将连接学生/家长与家教老师&#xff0c;提供一站式的家教服务预约体验。 一、用户需求分析1、家教老师&#xff1a;希望获得更多的学生资源&#xff0c;通过平台展示自己的教学特长和经验&#xff0c;管理个人日程&#xff0c;接收并确认预约请求&a…

基于Python的音乐播放器 毕业设计-附源码73733

摘 要 本项目基于Python开发了一款简单而功能强大的音乐播放器。通过该音乐播放器&#xff0c;用户可以轻松管理自己的音乐库&#xff0c;播放喜爱的音乐&#xff0c;并享受音乐带来的愉悦体验。 首先&#xff0c;我们使用Python语言结合相关库开发了这款音乐播放器。利用Tkin…

云架构Web端的工业MES系统设计之区分工业过程

云架构Web端的工业MES系统设计之区分工业过程 在当今数字化浪潮席卷全球的背景下,制造业作为国家经济发展的重要支柱产业,正面临着前所未有的机遇与挑战。市场需求的快速变化、客户个性化定制要求的日益提高以及全球竞争的愈发激烈,都促使制造企业必须寻求更加高效、智能的生产…

TCP协议:三次握手、四次挥手

文章目录 三次握手1. 什么是三次握手&#xff1f;2. 为什么是三次握手&#xff1f; 四次挥手1. 什么是四次挥手&#xff1f;2. 为什么是四次挥手&#xff1f; 引用 三次握手 1. 什么是三次握手&#xff1f; 三次握手是TCP协议中用于建立连接的过程。 第一次&#xff0c;表示请…

guestfish/libguestfs镜像管理工具简介

文章目录 简介guestfishlibguestfs项目 例子原理代码libguestfs架构参考 简介 guestfish Guestfish 是libguestfs项目中的一个工具软件&#xff0c;提供修改虚机镜像内部配置的功能。它不需要把虚机镜像挂接到本地&#xff0c;而是为你提供一个shell接口&#xff0c;你可以查…

详解GPT-信息抽取任务 (GPT-3 FAMILY LARGE LANGUAGE MODELS)

GPT-3 FAMILY LARGE LANGUAGE MODELS Information Extraction 自然语言处理信息提取任务&#xff08;NLP-IE&#xff09;&#xff1a;从非结构化文本数据中提取结构化数据&#xff0c;例如提取实体、关系和事件 [164]。将非结构化文本数据转换为结构化数据可以实现高效的数据处…

云备份项目--服务端编写

文章目录 7. 数据管理模块7.1 如何设计7.2 完整的类 8. 热点管理8.1 如何设计8.2 完整的类 9. 业务处理模块9.1 如何设计9.2 完整的类9.3 测试9.3.1 测试展示功能 完整的代码–gitee链接 7. 数据管理模块 TODO: 读写锁&#xff1f;普通锁&#xff1f; 7.1 如何设计 需要管理…

Flink operator实现自动扩缩容

官网文档位置&#xff1a; 1.Autoscaler | Apache Flink Kubernetes Operator 2.Configuration | Apache Flink Kubernetes Operator 1.部署K8S集群 可参照我之前的文章k8s集群搭建 2.Helm安装Flink-Operator helm repo add flink-operator-repo https://downloads.apach…

使用LINUX的dd命令制作自己的img镜像

为了避免重复安装同一镜像&#xff0c;配置环境&#xff0c;首先我准备一个正常使用的完整系统。 使用Gparted软件先将母盘&#xff08;如U盘&#xff0c;TF卡&#xff09;分区调整为只有数据的大小。如&#xff1a;60G的TF卡&#xff0c;只用了3.5G&#xff0c;将未使用的空间…

【Unity3D】LOD Group 多细节层次(CrossFade淡出淡入效果)

新建一个空物体挂载LOD Group脚本 LOD0&#xff08;球体&#xff09; LOD1&#xff08;立方体&#xff09; LOD2&#xff08;单面板Quad&#xff09; 可发现我勾选了Cross Fade并没有渐隐效果&#xff0c;是因为Shader是不透明的&#xff0c;不支持。 经过如下修改后支持Cros…

【2025年最新】OpenWrt 更换国内源的指南(图形界面版)

在上一篇文章中我们讲解了如何使用命令行更换国内源&#xff0c;如果你没有终端工具&#xff0c;或者不喜欢命令行&#xff0c;那么图形界面方式将会是更简单有效的方式。 命令行版本&#xff1a;【2025年最新】OpenWrt 更换国内源的指南(命令行)-CSDN博客 为什么选择通过图形…

Jdk动态代理源码缓存优化比较(JDK17比JDK8)

目录 JDK 8的缓存实现 JDK 17的缓存实现 优化比较 总结实际应用影响 JDK 8的缓存实现 // JDK 8 private static final WeakCache<ClassLoader, Class<?>[], Class<?>> proxyClassCache new WeakCache<>(new KeyFactory(), new ProxyClassFact…