Experiment 2, inter-process communication
interprocess communication
-
- lab environment:
- Experiment time:
- Purpose:
- Experimental goals:
- Experimental steps:
- experimental report:
-
- Data structure of experiment step 1:
- Size rules for Experimental Step 1:
- Structure of Experiment Step 2:
- In lab step 3, the IPC method you choose:
- Experimental step 3, why choose this method?
- Experimental step 3, if you choose the message queue mechanism, describe the message buffer structure:
- Experiment step 4, how to create an IPC resource?
- Experimental step 5, the main process or key algorithm of the program
- Experimental step 6, the main process or key algorithm of the program:
lab environment:
Linux platform
Experiment time:
6 hours
Purpose:
Have a preliminary understanding of the method of inter-process communication in the Linux system.
Experimental goals:
Write a program to use the IPC mechanism in Linux to complete the two-process "rock, scissors, cloth"
game
Experimental steps:
This experiment can create three processes, one of which is the referee process, and the other two are player
processes. The three tricks of "rock, scissors, and cloth" can be defined as three integer values. Winning relationship: rock >
scissors > cloth > rock.
Players process moves according to a certain strategy (for example, randomly generated), and hand them over to the referee process to judge the size.
The referee process notifies the players of the opponent's move and the result of the outcome. The game can take multiple rounds (>100 rounds)
to decide the outcome, and the referee will announce the final result. The time for each move is limited by the referee, and the timeout will be judged as a loss.
The per-disk results can be stored in files or other data structures. At the end of the game, the winning and losing situation of each set
and the total result can be printed.
1. Design a data structure representing "rock, paper, scissors" and the size rules between them.
2. Design the way to store the results of the competition.
3. Select the method of IPC.
4. Create corresponding IPC resources according to the IPC method you choose.
5. Complete the player process.
6. Complete the referee process
experimental report:
Data structure of experiment step 1:
Use the form of char* apt[] to store "rock, scissors, cloth" The
specific form is char* apt[] = {"rock", "scissors", "papper"};
index 0 1 2 represent rock, scissors, cloth
Size rules for Experimental Step 1:
Rule: rock > scissors > cloth > rock
Structure of Experiment Step 2:
How to save the game results:
1. Use 0 1 2 to represent the move of each player, and use two int [] arrays to store the result of the player's move
2. Use 0 1 2 to represent the comparison of the result of the move. If player_01 and player_02 are tied, use 0 to represent , player_01 wins with 1, player_02 wins with 2 and
also uses an int [] array to store the result
In lab step 3, the IPC method you choose:
Choose the way of message queue for inter-process communication
Experimental step 3, why choose this method?
The use of message queues does not require locking, and is not limited to communication between parent and child processes, but also enables two-way communication. For this experiment, the problem of communication between the players and the referee fits perfectly.
Experimental step 3, if you choose the message queue mechanism, describe the message buffer structure:
The structure of the buffer is defined by a structure, but it must have a message type, and other information of the buffer can be defined according to specific requirements.
Experiment step 4, how to create an IPC resource?
To create a message queue, you can use the msgget() method, which needs to add header files #include<sys/ipc.h> and #include<sys/msg.h>
Use the msgget() method to create a message queue:
queue_id = msgget(QUEUE_ID , IPC_CREAT | IPC_EXCL | 0600);
Experimental step 5, the main process or key algorithm of the program
Main process:
Key algorithm:
Referee Algorithm:
#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;
}
Experimental step 6, the main process or key algorithm of the program:
Code algorithm for two players:
Player 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;
}
Player 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;
}
The display of the results of the experimental part: