实验二、进程间通信
进程间通信- 实验环境:
- 实验时间:
- 实验目的:
- 实验目标:
- 实验步骤:
- 实验报告:
- 实验步骤 1 的数据结构:
- 实验步骤 1 的大小规则:
- 实验步骤 2 的结构:
- 实验步骤 3 中,你所选择的 IPC 方法:
- 实验步骤 3,为何选择该方法?
- 实验步骤 3,如果选择消息队列机制,描述消息缓冲区结构:
- 实验步骤 4,如何创建 IPC 资源?
- 实验步骤 5,程序主要流程或关键算法
- 实验步骤 6,程序主要流程或关键算法:
Linux 平台
实验时间:6 小时
实验目的:初步了解 Linux 系统中,进程间通信的方法。
实验目标:编写一个程序,用 Linux 中的 IPC 机制,完成两个进程“石头、剪子、布”的
游戏
本实验可以创建三个进程,其中,一个进程为裁判进程,另外两个进程为选
手进程。可以将“石头、剪子、布”这三招定义为三个整型值。胜负关系:石头〉
剪子〉布〉石头。
选手进程按照某种策略(例如,随机产生)出招,交给裁判进程判断大小。
裁判进程将对手的出招和胜负结果通知选手。比赛可以采取多盘(>100盘)
定胜负,由裁判宣布最后结果。每次出招由裁判限定时间,超时判负。
每盘结果可以存放在文件或其他数据结构中。比赛结束,可以打印每盘的胜
负情况和总的结果。
1.设计表示“石头、剪子、布”的数据结构,以及它们之间的大小规则。
2.设计比赛结果的存放方式。
3.选择 IPC 的方法。
4.根据你所选择的 IPC 方法,创建对应的 IPC 资源。
5.完成选手进程。
6.完成裁判进程
使用char* apt[] 形式来存储“石头、剪子、布”
具体的形式为 char* apt[] = {“rock”, “scissors”, “papper”};
索引 0 1 2 分别代表 石头、剪刀、布
规则:石头 > 剪子 > 布 > 石头
实验步骤 2 的结构:比赛结果的存放方式:
1、使用 0 1 2 表示每个选手的出招,使用两个 int [] 数组来存放选手的出招结果
2、使用 0 1 2 表示出招结果的比较,player_01和player_02平手的话就用 0 表示,player_01胜利就用 1 表示,player_02胜利就用 2 表示
也用一个 int [] 数组 来存放结果
选择消息队列的方式进行进程间通信
实验步骤 3,为何选择该方法?使用消息队列不需要加锁,并且不局限于父子进程之间的通信,还可以实现双向通信。对于这个实验来说,正好符合选手和裁判之间的通信问题。
实验步骤 3,如果选择消息队列机制,描述消息缓冲区结构:缓冲区的结构使用一个结构体来定义,但是它必须有一个消息类型,缓冲区的其他信息可以根据具体要求定义。
实验步骤 4,如何创建 IPC 资源?创建消息队列可以使用 msgget()方法,该方法需要添加头文件 #include
使用msgget()方法创建一个消息队列:
queue_id = msgget(QUEUE_ID, IPC_CREAT | IPC_EXCL | 0600);
主要流程:
关键算法:
裁判算法:
#include实验步骤 6,程序主要流程或关键算法:#include #include #include #include #include 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 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 msgqueuen"); } 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: %sn", win, player_01, player_02); printf("---------------------------------------------------n"); } printf("the num of deuce is: %dn", count_0); printf("the num of player_01 is win: %dn", count_1); printf("the num of player_02 is win: %dn", count_2); if (count_1 == count_2) { printf("they are deucing!n"); } else if (count_1 < count_2) { printf("the winner is player_02n"); } else { printf("the winner is player_01n"); } return 0; }
两个选手的代码算法:
选手1:
#include#include #include #include #include #include #include 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#include #include #include #include #include #include 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; }
实验部分结果的展示:



