信号通信与消息队列实现的通信:2024/2/23

作业1:将信号和消息队列的课堂代码敲一遍

1.1 信号

1.1.1 信号默认、捕获、忽略处理(普通信号)

代码:

cpp 复制代码
#include <myhead.h>
void handler(int signo)
{
	if(signo==SIGINT){
		printf("用户键入 ctrl+c\n");
	}
}
int main(int argc, const char *argv[])
{
	//忽略信号
	if(signal(SIGINT,SIG_IGN)==SIG_ERR){
		perror("signal error");
		return -1;
	}
	/*
	//默认处理信号
	if(signal(SIGINT,SIG_IGN)==SIG_ERR){
		perror("signal error");
		return -1;
	}
	//捕获信号
	if(signal(SIGINT,handler)==SIG_ERR){
		perror("signal error");
		return -1;
	}
	*/
	while(1)
	{
		printf("123456\n");
		sleep(1);
	}
	return 0;
}

效果图:

1.1.2 SIGCHLD回收僵尸进程

代码:

cpp 复制代码
#include <myhead.h>
void handler(int signo)
{
	if(signo==SIGCHLD){
		while(waitpid(-1,NULL,WNOHANG)>0);
		//waitpid(-1,NULL,WNOHANG);
	}
}
int main(int argc, const char *argv[])
{
	
	//捕获信号
	if(signal(SIGCHLD,handler)==SIG_ERR){
		perror("signal error");
		return -1;
	}
	//创建僵尸进程
	for(int i=0;i<5;i++)
	{
		if(fork()==0){
			sleep(1);
			exit(EXIT_SUCCESS);
		}
	}
	while(1);
	return 0;
}

效果图:

1.1.3 模拟出牌

代码:

cpp 复制代码
#include <myhead.h>

//信号处理函数
void handler(int signo)
{
	if(signo==SIGALRM){
		printf("系统为您出了一张牌\n");
		alarm(5);
	}
}
int main(int argc, const char *argv[])
{
	//捕获SIGALRM信号
	if(signal(SIGALRM,handler)==SIG_ERR){
		perror("signal error");
		return -1;
	}
	alarm(5);             //启动定时器
	
	//出的牌
	char ch=0;
	while(1)
	{
		scanf("%c",&ch);
		getchar();

		printf("你出的牌为:%c\n",ch);
		alarm(5);
	}
	return 0;
}

效果图:

1.1.4 发送信号函数

代码:

cpp 复制代码
#include <myhead.h>

void hander(int signo)
{
	if(signo==SIGUSR1){
		printf("大清亡了\n");
		raise(SIGKILL);
	}
}
int main(int argc, const char *argv[])
{
	//发送信号
	if(signal(SIGUSR1,hander)==SIG_ERR){
		perror("signal error");
		return -1;
	}
	
	
	//创建进程
	pid_t pid=fork();

	if(pid>0){
		//父进程
		while(1)
		{
			printf("这是朕的江山\n");
			sleep(1);
		}
	}else if(pid==0){
		//子进程
		sleep(3);
		printf("我才是真命天子\n");
		kill(getppid(),SIGUSR1);
		while(1)
		{
			printf("现在是我的了\n");
			sleep(1);
		}
	}else{
		perror("pid error");
		return -1;
	}
	return 0;
}

效果图:

1.2 消息队列

msgsnd.c:

cpp 复制代码
#include <myhead.h>

//消息队列结构体
struct msgbuf
{
	long mtype;
	char mtest[1024];
};
//宏表示消息正文的大小
#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)

int main(int argc, const char *argv[])
{
	//创建 key 值
	key_t key=0;
	if((key=ftok("/",'k'))==-1){
		perror("ftok error");
		return -1;
	}
	printf("fork success key=%#x\n",key);
	//根据key值创建消息队列
	int msqid=-1;
	if((msqid=msgget(key,IPC_CREAT|0664))==-1){
		perror("msgget error");
		return -1;
	}
	printf("msgget success msqid=%#x\n",msqid);
	//定义一个消息
	struct msgbuf sbuf;

	while(1)
	{
		//清空正文的容器
		bzero(sbuf.mtest,sizeof(sbuf.mtest));
		
		printf("请输入当前消息的类型:");
		scanf("%ld",&sbuf.mtype);
		getchar();                 //吸收垃圾字符
		printf("请输入消息正文:");
		fgets(sbuf.mtest,sizeof(sbuf.mtest),stdin);
		sbuf.mtest[strlen(sbuf.mtest)-1]='\0';

		//将消息存放到队列中
		msgsnd(msqid,&sbuf,MSGSIZE,0);
		printf("发送成功\n");

		if(strcmp(sbuf.mtest,"quit")==0){
			break;
		}

	}

	return 0;
}

msgrcv.c:

cpp 复制代码
#include <myhead.h>

//消息队列结构体
struct msgbuf
{
	long mtype;
	char mtest[1024];
};
//宏表示消息正文的大小
#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)

int main(int argc, const char *argv[])
{
	//创建 key 值
	key_t key=0;
	if((key=ftok("/",'k'))==-1){
		perror("ftok error");
		return -1;
	}
	printf("fork success key=%#x\n",key);
	//根据key值创建消息队列
	int msqid=-1;
	if((msqid=msgget(key,IPC_CREAT|0664))==-1){
		perror("msgget error");
		return -1;
	}
	printf("msgget success msqid=%#x\n",msqid);
	//定义一个消息
	struct msgbuf rbuf;

	while(1)
	{
		//清空正文的容器
		bzero(rbuf.mtest,sizeof(rbuf.mtest));
	
		//从消息队列中读取一个消息
		msgrcv(msqid,&rbuf,MSGSIZE,0,0);

		printf("收到的消息为:%s\n",rbuf.mtest);

		if(strcmp(rbuf.mtest,"quit")==0){
			break;
		}

	}

	//删除消息队列
	if(msgctl(msqid,IPC_RMID,NULL)!=0){
		perror("msgctl error");
		return -1;
	}

	return 0;
}

效果图:

作业2:使用消息队列完成两个进程间相互通信

msgsnd.c:

cpp 复制代码
#include <myhead.h>

//定义一个消息类型
struct msgbuf
{
	long mtype;
	char mtest[1024];
};

//宏表示消息正文大小
#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)

/*****************************主程序***********************/
int main(int argc, const char *argv[])
{
	//1、创建key值
	key_t key=0;
	if((key=ftok("/",'k'))==-1){
		perror("ftok error");
		return -1;
	}
	//根据key值创建一个消息队列
	int msqid=-1;
	if((msqid=msgget(key,IPC_CREAT|0664))==-1){
		perror("msgget error");
		return -1;
	}
	//创建一个子进程
	pid_t pid=fork();

	if(pid>0){
		//父进程向消息队列中写入类型为1的消息正文
		//定义一个消息
		struct msgbuf sbuf;
		sbuf.mtype=1;
		while(1)
		{
			//清空容器
			bzero(sbuf.mtest,sizeof(sbuf.mtest));

			printf("发送的消息:");
			fgets(sbuf.mtest,sizeof(sbuf.mtest),stdin);
			sbuf.mtest[strlen(sbuf.mtest)-1]='\0';

			//将消息存放到消息队列
			msgsnd(msqid,&sbuf,MSGSIZE,0);
			printf("发送成功\n");

			if(strcmp(sbuf.mtest,"quit")==0){
				break;
			}
		}
        wait(NULL);	
	}else if(pid==0){
		//子进程从消息队列中取出类型为2的消息正文
		//定义一个消息
		struct msgbuf rbuf;

		while(1)
		{
			//清空容器
			bzero(rbuf.mtest,sizeof(rbuf.mtest));

			//从消息队列中读取类型为2的消息正文
			msgrcv(msqid,&rbuf,MSGSIZE,2,0);

			printf("收到的消息为:%s\n",rbuf.mtest);
			if(strcmp(rbuf.mtest,"quit")==0){
				break;
			}
		}
        exit(EXIT_SUCCESS);
	}else{
		perror("fork error");
		return -1;
	}

	return 0;
}

msgrcv.c:

cpp 复制代码
#include <myhead.h>

//定义一个消息类型
struct msgbuf
{
	long mtype;
	char mtest[1024];
};

//宏表示消息正文大小
#define MSGSIZE sizeof(struct msgbuf)-sizeof(long)

/*****************************主程序***********************/
int main(int argc, const char *argv[])
{
	//1、创建key值
	key_t key=0;
	if((key=ftok("/",'k'))==-1){
		perror("ftok error");
		return -1;
	}
	//根据key值创建一个消息队列
	int msqid=-1;
	if((msqid=msgget(key,IPC_CREAT|0664))==-1){
		perror("msgget error");
		return -1;
	}
	//创建一个子进程
	pid_t pid=fork();

	if(pid>0){
		//父进程从消息队列中取出类型为1的消息正文
		//定义一个消息
		struct msgbuf rbuf;

		while(1)
		{
			//清空容器
			bzero(rbuf.mtest,sizeof(rbuf.mtest));

			//从消息队列中读取类型为1的消息正文
			msgrcv(msqid,&rbuf,MSGSIZE,1,0);

			printf("收到的消息为:%s\n",rbuf.mtest);
			if(strcmp(rbuf.mtest,"quit")==0){
				break;
			}
		}
        wait(NULL);
	}else if(pid==0){
		//子进程向消息队列中写入类型为2的消息正文
		//定义一个消息
		struct msgbuf sbuf;
		sbuf.mtype=2;
		while(1)
		{
			//清空容器
			bzero(sbuf.mtest,sizeof(sbuf.mtest));

			printf("发送的消息:");
			fgets(sbuf.mtest,sizeof(sbuf.mtest),stdin);
			sbuf.mtest[strlen(sbuf.mtest)-1]='\0';

			//将消息存放到消息队列
			msgsnd(msqid,&sbuf,MSGSIZE,0);
			printf("发送成功\n");

			if(strcmp(sbuf.mtest,"quit")==0){
				break;
			}
		}
        exit(EXIT_SUCCESS);
	}else{
		perror("fork error");
		return -1;
	}

	return 0;
}

效果图:

作业3:思维导图

相关推荐
猷咪7 分钟前
C++基础
开发语言·c++
IT·小灰灰8 分钟前
30行PHP,利用硅基流动API,网页客服瞬间上线
开发语言·人工智能·aigc·php
快点好好学习吧10 分钟前
phpize 依赖 php-config 获取 PHP 信息的庖丁解牛
android·开发语言·php
秦老师Q11 分钟前
php入门教程(超详细,一篇就够了!!!)
开发语言·mysql·php·db
烟锁池塘柳011 分钟前
解决Google Scholar “We‘re sorry... but your computer or network may be sending automated queries.”的问题
开发语言
是誰萆微了承諾11 分钟前
php 对接deepseek
android·开发语言·php
2601_9498683615 分钟前
Flutter for OpenHarmony 电子合同签署App实战 - 已签合同实现
java·开发语言·flutter
yyy(十一月限定版)28 分钟前
寒假集训4——二分排序
算法
星火开发设计29 分钟前
类型别名 typedef:让复杂类型更简洁
开发语言·c++·学习·算法·函数·知识
醉颜凉39 分钟前
【LeetCode】打家劫舍III
c语言·算法·leetcode·树 深度优先搜索·动态规划 二叉树