实验二、进程间通信

实验二、进程间通信

实验环境:

Linux 平台

实验时间:

6 小时

实验目的:

初步了解 Linux 系统中,进程间通信的方法。

实验目标:

编写一个程序,用 Linux 中的 IPC 机制,完成两个进程“石头、剪子、布”的
游戏

实验步骤:

本实验可以创建三个进程,其中,一个进程为裁判进程,另外两个进程为选
手进程。可以将“石头、剪子、布”这三招定义为三个整型值。胜负关系:石头〉
剪子〉布〉石头。
选手进程按照某种策略(例如,随机产生)出招,交给裁判进程判断大小。
裁判进程将对手的出招和胜负结果通知选手。比赛可以采取多盘(>100盘)
定胜负,由裁判宣布最后结果。每次出招由裁判限定时间,超时判负。
每盘结果可以存放在文件或其他数据结构中。比赛结束,可以打印每盘的胜
负情况和总的结果。
1.设计表示“石头、剪子、布”的数据结构,以及它们之间的大小规则。
2.设计比赛结果的存放方式。
3.选择 IPC 的方法。
4.根据你所选择的 IPC 方法,创建对应的 IPC 资源。
5.完成选手进程。
6.完成裁判进程

实验报告:

实验步骤 1 的数据结构:

使用char* apt[] 形式来存储“石头、剪子、布”
具体的形式为 char* apt[] = {“rock”, “scissors”, “papper”};
索引 0 1 2 分别代表 石头、剪刀、布

在这里插入图片描述

实验步骤 1 的大小规则:

规则:石头 > 剪子 > 布 > 石头

实验步骤 2 的结构:

比赛结果的存放方式:

1、使用 0 1 2 表示每个选手的出招,使用两个 int [] 数组来存放选手的出招结果
2、使用 0 1 2 表示出招结果的比较,player_01和player_02平手的话就用 0 表示,player_01胜利就用 1 表示,player_02胜利就用 2 表示
也用一个 int [] 数组 来存放结果

在这里插入图片描述

实验步骤 3 中,你所选择的 IPC 方法:

选择消息队列的方式进行进程间通信

实验步骤 3,为何选择该方法?

使用消息队列不需要加锁,并且不局限于父子进程之间的通信,还可以实现双向通信。对于这个实验来说,正好符合选手和裁判之间的通信问题。

实验步骤 3,如果选择消息队列机制,描述消息缓冲区结构:

缓冲区的结构使用一个结构体来定义,但是它必须有一个消息类型,缓冲区的其他信息可以根据具体要求定义。

在这里插入图片描述

实验步骤 4,如何创建 IPC 资源?

创建消息队列可以使用 msgget()方法,该方法需要添加头文件 #include<sys/ipc.h>和#include<sys/msg.h>
使用msgget()方法创建一个消息队列:
queue_id = msgget(QUEUE_ID, IPC_CREAT | IPC_EXCL | 0600);

在这里插入图片描述

实验步骤 5,程序主要流程或关键算法

主要流程:

在这里插入图片描述

关键算法:

裁判算法:

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

struct msgbuf {
    
                                             //消息缓冲区,具体看 play_01.c
	long msgtype;
	int rps;
	int limit_time;
};



int result[105];                       //save the result of player_01 and player_02
int player_01_info[105];       //save the player_01 information
int player_02_info[105];       // 能用数组尽量用,用结构体的话,可能会出现内存错误

int main () {
    
    
	char *apt[] = {
    
    
		"rock",
		"scissors",
		"papper"
	};

	
	
	key_t key_01 = ftok(".", 21);
	key_t key_02 = ftok(".", 22);
	int Msg_ID_01 = msgget(key_01, IPC_CREAT|0777);
	int Msg_ID_02 = msgget(key_02, IPC_CREAT|0777);
	struct msgbuf Snd_Buf_01 = {
    
    1,-1, 1};
	struct msgbuf Rcv_Buf_01;
	struct msgbuf Snd_Buf_02 = {
    
    2,-1, 1};
	struct msgbuf Rcv_Buf_02;
	int count_0 = 0;     // the two players are all win
	int count_1 = 0;    // player_01 win
	int count_2 = 0;
	int index = 0;       // The index of wfo
	
/*

	msgsnd() msgrcv() 两个函数最重要的是第三个参数 sizeof(Buf) - sizeof(msgtype)
*/


	while (index < 101) {
    
    
		int nsend_01 = msgsnd(Msg_ID_01, &Snd_Buf_01, sizeof(Snd_Buf_01)- sizeof(long),0);
		
		int nread_01 = msgrcv(Msg_ID_01, &Rcv_Buf_01, sizeof(Rcv_Buf_01)-sizeof(long), 521, 0);
		
		int nsend_02 = msgsnd(Msg_ID_02, &Snd_Buf_02, sizeof(Snd_Buf_02)-sizeof(long), 0);
		
		int nread_02 = msgrcv(Msg_ID_02, &Rcv_Buf_02, sizeof(Rcv_Buf_02) - sizeof(long), 522, 0);
		
		int player_01_rps = Rcv_Buf_01.rps;  // player_01 result
		int player_02_rps = Rcv_Buf_02.rps;
		int cha = player_01_rps - player_02_rps;
		
		
		int temp;
		if (cha == 0){
    
             // ping ju 
			temp = 0;
			count_0++;
		}
		else if (cha == -1 || cha == 2) {
    
         // player_01 win the game
			temp = 1;
			count_1++;
		}
		else {
    
    
			temp = 2;
			count_2++;
		
		}
		int info1 = player_01_rps;
		int info2 = player_02_rps;
		
		result[index] = temp;
		player_01_info[index] = info1;
		player_02_info[index] = info2;
		index++;
		

	}
	printf("the result of the match is below:\n");
	int ret1 = msgctl(Msg_ID_01, IPC_RMID, NULL);
	int ret2 = msgctl(Msg_ID_02, IPC_RMID, NULL);
	if (ret1 == -1 || ret2 == -1) {
    
    
		printf("fail to destory the msgqueue\n");
	}
	for (int i = 0; i < index; i++) {
    
    
		int w = result[i];
		char* win;
		if (w == 0) {
    
    
			win = "deuce";
		}
		else if(w == 1) {
    
    
			win = "player_01";
		}
		else {
    
    
			win = "player_02";
		}
		
		int p1 = player_01_info[i];
		int p2 = player_02_info[i];

		char* player_01 = apt[p1];
		char* player_02 = apt[p2];
		printf("winner: %s, player_01: %s, player_02: %s\n", win, player_01, player_02);
		printf("---------------------------------------------------\n");
	}
	printf("the num of deuce is: %d\n", count_0);
	printf("the num of player_01 is win: %d\n", count_1);
	printf("the num of player_02 is win: %d\n", count_2);
	if (count_1 == count_2) {
    
    
		printf("they are deucing!\n");
	}
	else if (count_1 < count_2) {
    
    
		printf("the winner is player_02\n");
	}
	else {
    
    
		printf("the winner is player_01\n");
	}
	return 0;
}

实验步骤 6,程序主要流程或关键算法:

两个选手的代码算法:
选手1:

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>


/*
	消息缓冲区的定义
	long msgtype;     消息类型
	int rps;                  代表石头剪刀布  0  1  2
	int limit_time;       裁判发来的出招限制时间,但是我没用 嘿嘿
*/
struct msgbuf {
    
                                              
	long msgtype;                         
	int rps;                                    
	int limit_time;
};

int main () {
    
    
	struct msgbuf Snd_Buf = {
    
    521, -1, 0};             // 发送消息类型为 521 到消息队列
	struct msgbuf Rcv_Buf;
	key_t key = ftok(".", 21);                                  // key 与 裁判程序里面的一样
	int Msg_ID = msgget(key, IPC_CREAT|0777);
	if (Msg_ID == -1) {
    
    
		printf("Msg create failure!\n");
	}
	int index = 0;
	srand(time(NULL));
	while (index < 101) {
    
    
		int nread = msgrcv(Msg_ID, &Rcv_Buf, sizeof(Rcv_Buf) - sizeof(long), 1, 0);    
		// 这个函数 的 sizeof(Rcv_Buf) - sizeof(long)很重要
			
		int rps_01 = rand()%3;
		Snd_Buf.rps = rps_01;
		int nsnd = msgsnd(Msg_ID, &Snd_Buf, sizeof(Snd_Buf) - sizeof(long), 0);
		
		index++;
	}	
	return 0;
}

选手2:

#include<stdio.h>
#include<sys/types.h>
#include<sys/ipc.h>
#include<sys/msg.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>

struct msgbuf {
    
    
	long msgtype;
	int rps;
	int limit_time;
};

int main () {
    
    
	struct msgbuf Snd_Buf = {
    
    522, -1, 0};
	struct msgbuf Rcv_Buf;
	key_t key = ftok(".", 22);
	int Msg_ID = msgget(key, IPC_CREAT|0777);
	if (Msg_ID == -1) {
    
    
		printf("Msg create failure!\n");
	}
	int index = 0;
	srand(time(NULL));
	while (index < 101) {
    
    
		int nread = msgrcv(Msg_ID, &Rcv_Buf, sizeof(Rcv_Buf) - sizeof(long), 2, 0);
			
		int rps_02 = rand()%3;
		Snd_Buf.rps = rps_02;
		int nsnd = msgsnd(Msg_ID, &Snd_Buf, sizeof(Snd_Buf) - sizeof(long), 0);
		
		index++;
	}	
	return 0;
}

实验部分结果的展示:

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45788387/article/details/120815371