首页 > 系统相关 >系统编程练习题----使用消息队列实现两个进程之间的通信

系统编程练习题----使用消息队列实现两个进程之间的通信

时间:2024-05-27 20:58:30浏览次数:40  
标签:练习题 队列 编程 pid ---- msg 消息 进程 include

目录

题目

要求进程A创建一条消息队列之后向进程B发送SIGUSR1信号,进程B收到该信号之后打开消息队列并写入一段信息作为消息写入到消息队列中,要求进程B在写入消息之后,发SIGUSR2信号给进程A,进程A收到该信号则从消息队列中读取消息并输出消息正文的内容。

思路

  1. 通过进程A创建的消息队列,实现进程A与进程B之间的PID交换
  2. 通过kill指令完成进程A与进程B之间的信号交互,并通过状态机实现步骤的进行
  3. 进程A收到进程B的信号后,从消息队列中读出消息,并完成显示

代码展示

进程A

/*******************************************************************
*
*	file name:	process_A.c
*	author	 :  [email protected]
*	date	 :  2024/05/27
*	function :  该案例是掌握进程通信方式,主要是学习信号和消息队列的使用
* 	note	 :  None
*   version  :
*
*	CopyRight (c)  2023-2024   [email protected]   All Right Reseverd 
*
* *****************************************************************/
/****************************头文件**************************************/

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

/****************************结构体**************************************/
struct msgbuf 
{
	long mtype;       /* message type, must be > 0 */
	int mtext;    /* message data */
};

/****************************全局变量**************************************/
volatile int  flag;  //作为状态机条件

/********************************************************************
*
*	name	 :	msg_get
*	function :  改函数用于获取进程B发送的信号
*	pqram :  
*				@signum  : 捕捉到的信号类型
*				
*	retval	 :  none
*	author	 :  [email protected]
*	date	 :  2024/05/27
* 	note	 :  none
*   version  :
* 	
* *****************************************************************/
void msg_get(int signum)
{
	if(signum == SIGUSR1)
	{
		//改变标志量,从消息队列中读取进程B的pid
		flag = 1;
	}
	else if(signum == SIGUSR2)
	{
		//改变标志量,从消息队列中读取进程B发送的消息
		flag = 0;
	}
}


int main(int argc, char const *argv[])
{
	//捕捉进程B发送的信号,再从消息队列中获取进程B的pid
	signal(SIGUSR1, msg_get);
	//捕捉进程B发送的信号,再从消息队列中获取进程B发送的消息
	signal(SIGUSR2, msg_get);



	/****创建一条消息队列****/
	//1) 获取消息队列唯一键值(key)
	key_t key = ftok(".", 0xffffff01);
	//2) 定义一个变量用于存储消息队列id,创建一条消息队列
	int msg_id = msgget(key, IPC_CREAT | 0644);
	if(msg_id == -1)
	{
		fprintf(stderr, "msgget error , errno: %d, %s\n", errno, strerror(errno));
		exit(-1);
	}

	/****发送SIGUSR1信号给进程B****/
	// 通过消息队列完成A,B进程的pid交换
	//1. 将进程A的pid写入消息队列中
	struct msgbuf msg_pid;
	msg_pid.mtype = 1;
	msg_pid.mtext = getpid();


	msgsnd(msg_id, &msg_pid, 4, 0);

	//2. 捕捉进程B发送的SIGUSR1信号
	while(flag == 0);
	// 3. 从消息队列中读取进程B的pid
	struct msgbuf msg_pid_B;
	msgrcv(msg_id, &msg_pid_B, 4, 1, IPC_NOWAIT);

	//4. 发送SIGUSR1信号给进程b
	kill(msg_pid_B.mtext, SIGUSR1);

	/****接收到进程B的信号后,从消息队列中读出消息并输出****/
	while(flag);

	struct msgbuf msg_num;
	msgrcv(msg_id, &msg_num, 4, 2, IPC_NOWAIT);

	printf("The information received from process B is %d\n", msg_num.mtext);

	return 0;
}

进程B

/*******************************************************************
*
*	file name:	process_B.c
*	author	 :  [email protected]
*	date	 :  2024/05/27
*	function :  该案例是掌握进程通信方式,主要是学习信号和消息队列的使用
* 	note	 :  None
*   version  :
*
*	CopyRight (c)  2023-2024   [email protected]   All Right Reseverd 
*
* *****************************************************************/
/****************************头文件**************************************/

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

/****************************结构体**************************************/
struct msgbuf 
{
	long mtype;       /* message type, must be > 0 */
	int mtext;    /* message data */
};

/****************************全局变量**************************************/
volatile int  flag = 1;  //作为状态机条件

/********************************************************************
*
*	name	 :	msg_get
*	function :  改函数用于获取进程A发送的信号
*	pqram :  
*				@signum  : 捕捉到的信号类型
*				
*	retval	 :  none
*	author	 :  [email protected]
*	date	 :  2024/05/27
* 	note	 :  none
*   version  :
* 	
* *****************************************************************/
void msg_get(int signum)
{
	if(signum == SIGUSR1)
	{
		//改变标志量,从消息队列中读取进程A的pid
		flag = 0;
	}
}


int main(int argc, char const *argv[])
{
	//捕捉进程A发送的信号,再从消息队列中获取进程B的pid
	signal(SIGUSR1, msg_get);


	/****打开一条消息队列****/
	//1) 获取消息队列唯一键值(key)
	key_t key = ftok(".", 0xffffff01);
	//2) 定义一个变量用于存储消息队列id,创建一条消息队列
	int msg_id = msgget(key, IPC_CREAT | 0644);
	if(msg_id == -1)
	{
		fprintf(stderr, "msgget error , errno: %d, %s\n", errno, strerror(errno));
		exit(-1);
	}

	struct msgbuf msg_pid_a;
	/****从消息队列中读取进程A的pid,并将进程B的pid写入消息队列中***/
	msgrcv(msg_id, &msg_pid_a, 4, 1, IPC_NOWAIT);

	//将进程B的pid写入消息队列
	struct msgbuf msg_pid_b;
	msg_pid_b.mtype = 1;
	msg_pid_b.mtext = getpid();

	msgsnd(msg_id, &msg_pid_b, 4, 0);
	/****发送SIGUSR1信号给进程A****/
	kill(msg_pid_a.mtext, SIGUSR1);

	/****等待接收进程A的SIGUSR1信号****/
	while(flag == 1);

	/****接收到进程A的信号后,将数据写入消息队列中***/
	struct msgbuf msg_num;
	msg_num.mtype = 2;
	msg_num.mtext = 66666;

	msgsnd(msg_id, &msg_num, 4, 0);

	/****发送SIGUSR2信号给进程A****/
	kill(msg_pid_a.mtext, SIGUSR2);

	return 0;
}

结果展示

image

标签:练习题,队列,编程,pid,----,msg,消息,进程,include
From: https://www.cnblogs.com/fly-home/p/18216499

相关文章

  • 基于 Debian 部署 NFS 及其 NFS 配置
    基于Debian部署NFS及其NFS配置安装NFSServer安装NFS软件包sudoapt-getinstall-ynfs-kernel-server创建一个目录,通过NFS服务器共享文件和文件夹sudomkdir–p/nfs-test由于该文件夹将会被共享给客户端中的任何用户使用,因此权限设置为nobody用......
  • ssh 登录远程ssh 和退出
    登录远程SSH服务器通常使用以下命令:bashssh用户名@远程主机地址替换 用户名 为你的远程服务器账户名,远程主机地址 为服务器的IP地址或域名。例如,如果你的用户名是 yourusername,服务器地址是 example.com,则命令将是:[email protected]登录后,你将在......
  • ubuntu安装mysql
    ubuntu安装mysql更新软件包列表sudoaptupdate安装mysql服务器sudoaptinstallmsyql-server启动并检查mysql服务sudosystemctlstartmysqlsudosystemctlstatusmysql无密码登录mysqlsudomysql-uroot给root创建密码如果是mysql5.0版本,使用alteruser'root'......
  • 浏览器插件推荐
    一、这9款Edge浏览器必备灵魂插件,少装一个都不行!9款Edge浏览器必备灵魂插件,少装一个都不行!FlashCopilot学术资源全搜索BewlyBewly在线音乐盒篡改猴UblockOriginAIX智能下载器GlobalSpeedDarkReader  二、别眨眼,5个神级拓展插件颠覆你的Edge浏览器......
  • 如何在中文输入法模式下,使用英文符号?
    1、为什么有这种需求?当你使用Notion等笔记服务时,它的输入语法命令是斜杠(/),而在中文输入法场景下按健输入的是顿号(、),需要切换输入法才可以输入英文符号。因此,期待可以在中文输入法场景下,输入英文符号。减少切换的烦恼。2、如何解决?Windows自带的微软输入法支持......
  • 代码随想录算法训练营第五天|242(有效的字母异位词),349(两个数组的交集),202(快乐数)
    哈希C#常用的数据结构:[]Array,ArrayList数组和动态数组List集合HashSet哈希集合(无重复值)HashTable哈希表(obj,obj的键值对)Dictionary<T,T>泛型的哈希表什么时候考虑Hash数据结构?需要高效的判断一个值是否存在在一个容器中时。容器不允许重复值(HashSet或哈希表的......
  • MindSponge分子动力学模拟——多路径分子模拟(2024.05)
    技术背景在前面的MindSponge教程系列博客中,我们已经介绍过MindSponge分子动力学模拟框架的基础功能使用方法,例如MindSponge的安装与使用、定义分子系统、计算单点能和迭代器等等。这些模块和功能,更多的是凭借MindSpore深度学习框架的自动微分、GPU加速和Python语言的灵活性,而本文......
  • redis的6.2.14的docker安装
    1.拉取镜像dockerpullredis:6.2.142.运行镜像sudodockerrun--nameredis-d-p6379:6379\-v/home/cy/soft/redis/data:/data\-v/home/cy/soft/redis/conf/redis-docker.conf:/usr/local/etc/redis/redis.conf\--privileged=true\redis:6.2.14redis-server/usr/lo......
  • 什么是形式化方法
    形式化方法是一种在软件工程中使用的严格和数学化的方法,用于规范化、描述和验证软件系统的行为和性质。它们基于形式化语言和数学逻辑,通过精确的符号和规则来描述软件系统的结构、功能和行为,以及系统的性质和约束。形式化方法通常涉及以下几个方面:形式化规约:使用数学符号、逻辑......
  • 2024 蓝桥杯省赛游记
    Day-inf看了眼去年的题,一个插头dp一个杜教筛,恐怖如斯群里问了句发现hkhmtr也参加Day1完全没压力所以随便玩了。开场扫了一眼只有8道题,有个树上莫队?T1赛后看知乎好像能直接拿excel生成字符串形式的日期T2一开始没注意白棋一定有13个子,跑完了再看题才想到,提答的......