实验二、进程间通信
实验二、进程间通信实验环境:Linux 平台实验时间:6 小时实验目的:初步了解 Linux 系统中,进程间通信的方法。实验目标:编写一个程序,用 Linux 中的 IPC 机制,完成两个进程“石头、剪子、布”的游戏实验步骤:本实验可以创建三个进程,其中,一个进程为裁判进程,另外两个进程为选手进程。可以将“石头、剪子、布”这三招定义为三个整型值。胜负关系:石头〉剪子〉布〉石头。选手进程按照某种策略
实验二、进程间通信
进程间通信
实验环境:
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;
}
实验部分结果的展示:
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)