10.21 多进程间通信-信号、消息队列

时间:2024-10-22 08:47:50

作业:使用消息队列实现两个进程间通信

编程代码:使用父子进程实现通信

msgsnd.c

#include <myhead.h>
//定义自定义函数用于接收僵尸进程
void handler(int signo){
	if(signo==SIGCHLD){
		while(waitpid(-1,NULL,WNOHANG)>0);
	}
}
//定义存储消息队列信息结构体类型
struct msgbuf{
	long mtype;  //消息类型
	char mtext[1024];  //消息正文
};
//宏定义消息正文大小
#define MSGSZ (sizeof(struct msgbuf)-sizeof(long))
int main(int argc, const char *argv[])
{
	//使用消息队列实现两个进程间相互通信
	if(signal(SIGCHLD,handler)==SIG_ERR){
		perror("signal error");
		return -1;
	}//用于与SIGCHLD信号绑定
	//1.创建一个key值
	key_t key=ftok("/",'k');
	if(key==-1){
		perror("ftok error");
		return -1;
	}
	//2.创建一个消息队列
	int msqid=msgget(key,IPC_CREAT|0664);
	if(msqid==-1){
		perror("msgget error");
		return -1;
	}
	//创建一个子进程
	pid_t pid=fork();
	if(pid>0){//执行父进程
		//3.父进程存放消息类型1数据
		struct msgbuf buf;//用于存储消息
		while(1){
			printf("请输入消息队列类型1消息类型>>");
			scanf("%ld",&buf.mtype);
			getchar();//吸收垃圾字符
			printf("请输入消息队列类型1消息正文");
			fgets(buf.mtext,MSGSZ,stdin);
			buf.mtext[strlen(buf.mtext)-1]='\0';//将\n转为\0
			msgsnd(msqid,&buf,MSGSZ,0);//将信息存放于消息队列中
			printf("消息队列类型1数据已存放\n");
			if(strcmp(buf.mtext,"quit")==0){//结束循环
				break;
			}
		}
	}else if(pid==0){//执行子进程
		//4.子进程读取消息类型2数据
		struct msgbuf buf;//用于存储消息
		while(1){
			//从消息队列中读取数据
			msgrcv(msqid,&buf,MSGSZ,2,0);//2表示从消息类型2读取数据,0表示阻塞读取
			printf("消息队列类型2数据已读取,正文为:%s\n",buf.mtext);
			if(strcmp(buf.mtext,"quit")==0){
				break;
			}
		}
		exit(EXIT_SUCCESS);//结束子进程
	}else{
		perror("fork error");
		return -1;
	}
	//5.删除队列
	if(msgctl(msqid,IPC_RMID,NULL)==-1){
		perror("msgctl error");
		return -1;
	}
	return 0;
}

msgrcv.c 

#include <myhead.h>
//定义自定义函数用于接收僵尸进程
void handler(int signo){
	if(signo==SIGCHLD){
		while(waitpid(-1,NULL,WNOHANG)>0);
	}
}
//定义存储消息队列信息结构体类型
struct msgbuf{
	long mtype;  //消息类型
	char mtext[1024];  //消息正文
};
//宏定义消息正文大小
#define MSGSZ (sizeof(struct msgbuf)-sizeof(long))
int main(int argc, const char *argv[])
{
	//使用消息队列实现两个进程间相互通信
	if(signal(SIGCHLD,handler)==SIG_ERR){
		perror("signal error");
		return -1;
	}//用于与SIGCHLD信号绑定
	//1.创建一个key值
	key_t key=ftok("/",'k');
	if(key==-1){
		perror("ftok error");
		return -1;
	}
	//2.创建一个消息队列
	int msqid=msgget(key,IPC_CREAT|0664);
	if(msqid==-1){
		perror("msgget error");
		return -1;
	}
	//创建一个子进程
	pid_t pid=fork();
	if(pid>0){//执行父进程
		//3.父进程存放消息类型2数据
		struct msgbuf buf;//用于存储消息
		while(1){
			printf("请输入消息队列类型2消息类型>>");
			scanf("%ld",&buf.mtype);
			getchar();//吸收垃圾字符
			printf("请输入消息队列类型2消息正文");
			fgets(buf.mtext,MSGSZ,stdin);
			buf.mtext[strlen(buf.mtext)-1]='\0';//将\n转为\0
			msgsnd(msqid,&buf,MSGSZ,0);//将信息存放于消息队列中
			printf("消息队列类型2数据已存放\n");
			if(strcmp(buf.mtext,"quit")==0){//结束循环
				break;
			}
		}
	}else if(pid==0){//执行子进程
		//4.子进程读取消息类型1数据
		struct msgbuf buf;//用于存储消息
		while(1){
			//从消息队列中读取数据
			msgrcv(msqid,&buf,MSGSZ,1,0);//1表示从消息类型1读取数据,0表示阻塞读取
			printf("消息队列类型1数据已读取,正文为:%s\n",buf.mtext);
			if(strcmp(buf.mtext,"quit")==0){
				break;
			}
		}
		exit(EXIT_SUCCESS);//结束子进程
	}else{
		perror("fork error");
		return -1;
	}
	return 0;
}

运行结果:

思维导图: