Linux 基本语句_13_消息队列

概念:

不同进程能通过消息队列来进行通信,不同进程也能获取或发送特定类型的消息,即选择性的收发消息。

一般一个程序采取子进程发消息,父进程收消息的模式

常用函数功能:

fork(); // 创建子进程

struct msgbuf{ // 数据协议
    long mtype; // 数据类型,由用户自己定义
    char buf[N]; // 数据部分
};

key = ftok(“.”, ‘a’) // 创建键值

第一个参数是路径名,通常是一个已经存在的文件或目录的路径名。在这个例子中,.表示当前目录,也就是代码所在的目录。
第二个参数是一个由用户自定义的字符,用于生成键值。在这里,它是字符 ‘a’。

这个键值的作用即标识一个消息队列,通过键值识别具体的某条消息队列


代码:

SndTp1RcvTp2.c:

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

#define N 128
#define SIZE sizeof(struct msgbuf) - sizeof(long)
#define TYPE1 100
#define TYPE2 200

struct msgbuf{
	long mtype;
	char buf[N];
};

int main(){
	key_t  key;
	if((key = ftok(".", 'a')) < 0){ // 创建键值 
		perror("ftok error");
		return -1;
	}
	
	int msqid;
	struct msgbuf msg_snd, msg_rcv; // 发送端接收端
	if((msqid = msgget(key, IPC_CREAT|IPC_EXCL|0664)) < 0){ // 创建消息队列 存在则报错 出现错误返回-1 
		if(errno != EEXIST){ // 若消息不存在 
			perror("msgget error");
			return -1; 
		}
		else{ // 则消息队列存在 直接打开 
			msqid = msgget(key, 0664); 
		} 
	} 
	
	pid_t pid;
	
	pid = fork(); // 创建子进程
	
	if(pid < 0){
		perror("fork error");
		return -1;
	} 
	else if(pid == 0){ // 若是子进程 
		while(1){
			msg_snd.mtype = TYPE1; // 标识信息的符号
			fgets(msg_snd.buf, N, stdin); // 标准输入 读取用户输入
			msg_snd.buf[strlen(msg_snd.buf) - 1] = '\0'; // 方便读取
			
			msgsnd(msqid, &msg_snd, SIZE, 0); // 消息无法发送则阻塞直到可发送为止 
			
			if(strncmp(msg_snd.buf, "quit", 4) == 0){ // 查看用户输入若为quit 则结束父进程 子进程自我结束 
				kill(getppid(), SIGKILL);
				break;
			} 
			
		} 
	}
	else{ // 父进程 
	    while(1){
		
		    msgrcv(msqid, &msg_rcv, SIZE, TYPE2, 0); // 只接收 TYPE2 直到等到有符合条件的消息为止 
		
		    if(strncmp(msg_rcv.buf, "quit", 4) == 0){
			    kill(pid, SIGKILL);
			    msgctl(msqid, IPC_RMID, NULL); // 删除消息队列 
			    break;
		    }
		
		    printf("msg_b:%s\n", msg_rcv.buf);
	    }
	}	
	return 0;
}

SndTp2RcvTp1.c:

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

#define N 128
#define SIZE sizeof(struct msgbuf) - sizeof(long)
#define TYPE1 100
#define TYPE2 200

struct msgbuf{
	long mtype;
	char buf[N];
};

int main(){
	key_t  key;
	if((key = ftok(".", 'a')) < 0){ // 创建键值 
		perror("ftok error");
		return -1;
	}
	
	int msqid;
	struct msgbuf msg_snd, msg_rcv; // 发送端接收端
	if((msqid = msgget(key, IPC_CREAT|IPC_EXCL|0664)) < 0){ // 创建消息队列 存在则报错 出现错误返回-1 
		if(errno != EEXIST){ // 若消息不存在 
			perror("msgget error");
			return -1; 
		}
		else{ // 则消息队列存在 直接打开 
			msqid = msgget(key, 0664); 
		} 
	} 
	
	pid_t pid;
	
	pid = fork(); // 创建子进程
	
	if(pid < 0){
		perror("fork error");
		return -1;
	} 
	else if(pid == 0){ // 若是子进程  发送方 
		while(1){
			msg_snd.mtype = TYPE2; // 标识信息的符号
			fgets(msg_snd.buf, N, stdin); // 标准输入 读取用户输入
			msg_snd.buf[strlen(msg_snd.buf) - 1] = '\0'; // 方便读取
			
			msgsnd(msqid, &msg_snd, SIZE, 0); // 消息无法发送则阻塞直到可发送为止 
			
			if(strncmp(msg_snd.buf, "quit", 4) == 0){ // 查看用户输入若为quit 则结束父进程 子进程自我结束 
				kill(getppid(), SIGKILL);
				break;
			} 
			
		} 
	}
	else{ // 父进程  接受方 
	    while(1){
	        msgrcv(msqid, &msg_rcv, SIZE, TYPE1, 0); // 只接收 TYPE1 直到等到有符合条件的消息为止 
		
		    if(strncmp(msg_rcv.buf, "quit", 4) == 0){
			    kill(pid, SIGKILL);
			    msgctl(msqid, IPC_RMID, NULL); // 删除消息队列 
			    break; 
		    }
		    
		    printf("msg_a:%s\n", msg_rcv.buf);
		}
	}
	 
	return 0;
}

俩个程序各开一个子进程,父进程。子进程负责发送信息,父进程负责接收信息,最终能实现在不同终端通讯,发送quit终止通讯

效果:

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

操作系统(七)| 设备管理-- 端口 驱动程序 基本I/O控制 磁盘I/O

系列文章如下 学习过程中一定要有系统观念&#xff08;知识框架&#xff0c;每一章开头都会有一个思维导图&#xff09;&#xff0c;知道目前自己在学习的是哪一板块的内容&#xff0c;和前面有什么样的联系 操作系统的很多知识点前后都是联系非常紧密的&#xff0c;去一点一…

【Openstack Train安装】十、Neutron安装

Neutron&#xff0c;是Openstack中的一大核心组件&#xff0c;设计目标是实现“网络即服务&#xff08;Networking as a Service&#xff09;”。为了达到这一目标&#xff0c;在设计上遵循了基于 SDN 实现网络虚拟化的原则&#xff0c;在实现上充分利用了 Linux 系统上的各种网…

vs配置64位汇编

vs开发64位程序无法使用内联汇编&#xff0c;需要将汇编放到一个单独文件中编译链接。 步骤如下&#xff1a; 生成汇编代码。以asm.asm为例&#xff0c;以下是模板&#xff1a; ;64位汇编程序模板 (Template) ;声明一个ExitProcess函数 ExitProcess PROTO.data;在这里声明变量…

一文1000字彻底搞懂Web测试与App测试的区别

总结分享一些项目需要结合Web测试和App测试的工作经验给大家&#xff1a; 从功能测试区分&#xff0c;Web测试与App测试在测试用例设计和测试流程上没什么区别。 而两者的主要区别体现在如下几个方面&#xff1a; 1 系统结构方面 Web项目&#xff0c;B/S架构&#xff0c;基…

Python异常处理:try语句的应用与技巧

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 异常处理在Python中是至关重要的。try-except是用于捕获和处理异常的核心机制之一。让我们深入了解如何使用try-except&#xff0c;处理各种异常情况。 try-except语句 在编程中&#xff0c;异常是指运行时发生…

Python并发编程之进程间通信

更多资料获取 &#x1f4da; 个人网站&#xff1a;ipengtao.com 进程间通信是并发编程中一个重要而复杂的主题。在多任务处理时&#xff0c;多个进程之间需要共享信息、数据和资源。在并发环境下&#xff0c;进程之间的协作和通信至关重要&#xff0c;以便能够安全地共享数据&…

AMIS【部署 01】amis前端低代码框架可视化编辑器amis-editor本地部署流程

amis-editor本地部署流程 1.amis-editor是什么1.1 amis是什么1.2 amis-editor是什么 2.amis-editor本地部署2.1 准备阶段2.2 源码修改2.3 构建项目2.4 nginx配置2.5 启动nginx 3.总结 官网仅贴出了本地运行这个项目的步骤&#xff1a; # 1.安装依赖 npm i # 2.等编译完成后本地…

30岁+项目经理和PMO少奋斗10年的职业规划路线

大家好&#xff0c;我是老原。 很多项目经理小白出来工作遇到困惑时又以得过且过的态度拒绝了别人的指导和建议&#xff0c;磨磨蹭蹭的就到了30岁。 大多数人会感到迷茫的原因&#xff0c;是因为对自己要往什么方向发展&#xff1f;做什么样的事情毫无计划和想象。 为什么会…

Docker,从入门到精通

1、DockerFile 介绍 dockerfile 是啥?dockerfile 用来构建 docker 镜像的文件。 具体步骤&#xff1a; 1、编写一个 dockerfile 文件 2、docker build 构造一个镜像 3、docker run 运行镜像 4、docker push 发布镜像 DockerFile 构建过程 1、每个保留关键字都必须是大…

数字图像处理(实践篇)十三 数据增强之给图像添加噪声!

目录 一 涉及的函数 二 实践 一 涉及的函数 skimage.util.random_noise( ) skimage.util.random_noise(image, modegaussian, seedNone, clipTrue, **kwargs) 函数的功能&#xff1a;为浮点型图片添加各种随机噪声。 输入&#xff1a; ①image&#xff1a;输入图像&…

react-virtualized报bpfrpt_proptype_WindowScroller引入错误

背景 vite构建阶段react-virtualized报错 报错信息 ✘ [ERROR] No matching export in "node_modules/_react-virtualized9.22.5react-virtualized/dist/es/WindowScroller/WindowScroller.js" for import "bpfrpt_proptype_WindowScroller"node_module…

微信开发者代码管理删除项目

微信开发者代码管理删除项目 1、打开 微信开发者代码管理平台&#xff0c;选择项目&#xff0c;显示个人用户下的项目 2、点进项目里面&#xff0c;选中设置 3、进入设置页面 4、选择高级设置–> 仓库设置 5、选中删除项目 6、删除页面 这样就 OK 了

[Python入门系列之十二]安装Jupyter notebook与代码运行

引言 Jupyter Notebook将代码、图片和文本完美结合在一起&#xff0c;为编程学习带来了前所未有的便捷性。本文旨在为初学者提供一个关于Jupyter Notebook的入门指南。 什么是Jupyter Notebook Jupyter Notebook是一个开源的Web应用程序&#xff0c;允许你创建和共享包含代码…

删除排序链表的重复元素I和II,多种解法和思考

删除排序链表的重复元素I https://leetcode.cn/problems/remove-duplicates-from-sorted-list/description/ 一个循环就可以了&#xff0c;如果当前节点和下一个节点值一样&#xff0c;当前节点不移动让next后移动一个&#xff0c;如果不一样则当前节点后移。 一个循环就可以…

python 生成器的作用

1. 生成器 参考&#xff1a; https://www.cainiaojc.com/python/python-generator.html 1.1. 什么是生成器&#xff1f; 在 python 中&#xff0c;一边循环一边计算的机制&#xff0c;称为生成器&#xff1a;generator. 1.2. 生成器有什么优点&#xff1f; 1、节约内存。p…

QNX下多窗口叠加融合方案

目的&#xff1a;QNX下EGL多窗口叠加融合方案 环境&#xff1a; 系统&#xff1a;QNX 环境&#xff1a;8155/8295问题&#xff1a; EGL有时候在同一个进程中因为引入不同的功能&#xff0c;在不同的线程中进行窗口的绘制和融合&#xff0c;QNX下的融合方案&#xff0c;实测使…

速记:一个保险丝检测电路

一个保险丝检测电路 保险丝熔断&#xff1a;红灯亮 保险丝正常&#xff1a;绿灯亮 同样的&#xff0c;仿真中的指示灯可以换成其他指示器件。

【MYSQL】表的基本查询

目录 前言 一、Create&#xff08;增&#xff09; 1.单行数据 全列插入 2.多行数据 指定列插入 3.插入否则更新 4.替换 二、Retrieve&#xff08;查&#xff09; 1.select列 1.1全列查询 1.2指定列查询 1.3查询字段为表达式 1.4为查询结果指定别名 1.5结果去重 …

Java 最全面试总结——3.多线程篇

1、说说Java中实现多线程有几种方法 创建线程的常用三种方式&#xff1a; 继承Thread类实现Runnable接口实现Callable接口&#xff08; JDK1.5> &#xff09;线程池方式创建 通过继承Thread类或者实现Runnable接口、Callable接口都可以实现多线程&#xff0c;不过实现Run…

Ebullient 硬件篇

一. 简介 哈喽&#xff0c;大家好&#xff0c;好久没有给大家分享新项目了&#xff0c;但之前分享了许多项目都没有认认真真的做完过&#xff0c;做到了一半&#xff0c;由于某些原因就放弃了&#xff0c;给自己的一种感觉是做了很多东西&#xff0c;但是能拿出来讲的缺没有几…