Linux 基本语句_13_消息队列

news/2024/7/24 4:29:46 标签: linux, 运维, 服务器

概念:

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

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

常用函数功能:

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终止通讯

效果:

在这里插入图片描述


http://www.niftyadmin.cn/n/5225691.html

相关文章

自学成为android framework工程师需要准备哪些装备-千里马车载车机系统开发学习

背景 hi&#xff0c;粉丝朋友们&#xff1a; 大家好&#xff01;经常有很多学员买课同学都会问到需要准备哪些装备&#xff0c;我也回答了很多学员了&#xff0c;今天就搞一篇文章来统一说明一下&#xff0c;告诉一下大家如果你想从一个framework新手变成一个framework开发的高…

java - 冒泡排序

一、什么是冒泡排序 冒泡排序&#xff08;Bubble sort&#xff09;是一种简单的排序算法&#xff0c;其基本思想是通过相邻元素的比较和交换&#xff0c;将较大的元素逐渐交换到序列的一端&#xff0c;从而达到排序的目的。 具体步骤如下&#xff1a; 从序列的第一个元素开始&a…

【广州华锐视点】3D宪法普法知识宣传展厅——线上法律知识学习新途径

随着科技的不断发展&#xff0c;人们的生活方式也在不断地改变。在这个信息爆炸的时代&#xff0c;传统的普法教育方式已经无法满足人们的需求。为了适应这一变化&#xff0c;越来越多的教育机构开始尝试利用现代科技手段进行普法教育。其中&#xff0c;3D宪法普法知识宣传展厅…

LeetCode:907. 子数组的最小值之和(单调栈 C++ 、Java)

目录 907. 子数组的最小值之和 题目描述&#xff1a; 实现代码与解析&#xff1a; 单调栈 原理思路&#xff1a; 907. 子数组的最小值之和 题目描述&#xff1a; 给定一个整数数组 arr&#xff0c;找到 min(b) 的总和&#xff0c;其中 b 的范围为 arr 的每个&#xff08;…

二叉树(判断是否为对称二叉树)

题目&#xff08;力扣&#xff09;&#xff1a; 观察题目&#xff0c;只需判断该二叉树是否对称。 判断二叉树是否对称&#xff0c;就可以换位去判断该二叉树的左子树和右子树是否对称。 这时就可以写一个辅助函数来方便判断。 该函数是判断两颗树是否镜像对称&#xff0c;这…

L1-004:计算摄氏温度

题目描述 给定一个华氏温度F&#xff0c;本题要求编写程序&#xff0c;计算对应的摄氏温度C。计算公式&#xff1a;C5(F−32)/9。题目保证输入与输出均在整型范围内。 输入格式&#xff1a;输入在一行中给出一个华氏温度。 输出格式&#xff1a;在一行中按照格式“Celsius C”…

java8 lambda常用整理(1)

1.map遍历 可以使用Map接口提供的新方法forEach来遍历Map的键值对。这个方法接受一个BiConsumer函数式接口作为参数&#xff0c;该接口定义了一个操作&#xff0c;接收键和对应的值作为输入。 下面是一个示例代码&#xff0c;展示如何在Java 8中使用forEach方法遍历Map&#…

软件测试之bug分析定位技巧

1、web前端 Web前端就是通常说的网页。互联网公司的前端一般包含如下内容&#xff1a;JavaScript、ActionScript、CSS、HTML(..ML)、Flash、交互式设计、视觉设计 web前端测试可能发现的问题——版面设计、交互设计、文字、性能、功能 bug定位通用思路&#xff1a;现象-->…