我正在尝试使用管道编写一个C
程序,以便在两个孩子之间玩“石头,纸,剪刀”游戏。我已经编写和工作了大部分代码。当我运行代码时,它会玩游戏,但拒绝终止。它锁定了终端,并迫使我将其关闭,然后重试。我不确定为什么会这样。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <time.h>
static char* const ARGV[] = {
"prog","4",NULL
};
int main(int argc, char *argv[]) {
int pipe1[2], pipe2[2], pipe3[2], pipe4[2];
int pid, pid2, cpid;
int turns, readbyte;
char message[100];
int object, i, status;
char p1[5], p2[5], choice[5];
srand(time(NULL));
if((argc != 2) || ((turns = atoi(argv[1])) <= 0)) {
fprintf(stderr, "Usage: %s turns\n",argv[0]);
exit(1);
}
if(pipe(pipe1) == -1) {
perror("Could not create pipe");
exit(1);
}
if(pipe(pipe2) == -1) {
perror("Could not create pipe");
exit(1);
}
if(pipe(pipe3) == -1) {
perror("Could not reach pipe");
exit(1);
}
if(pipe(pipe4) == -1) {
perror("Could not reach pipe");
exit(1);
}
if(pid = fork()) {
write(pipe1[1], "Ready", strlen("Ready")+1);
for(i=1; i <= turns; i++) {
readbyte = read(pipe2[0],message,100);
srand(time(NULL));
object = rand() % 3;
sprintf(choice,"%d",object);
write(pipe1[1],choice,strlen(choice)+1);
}
}
if(pid = fork()) {
write(pipe3[1], "Ready", strlen("Ready")+1);
for(i=1; i<=turns; i++){
readbyte = read(pipe4[0],message,100);
sleep(1);
srand(time(NULL));
object = rand()%3;
sprintf(choice,"%d",object);
write(pipe3[1],choice,strlen(choice)+1);
}
}
cpid = wait(&status);
readbyte = read(pipe3[0],message,100);
readbyte = read(pipe1[0],message,100);
printf("Child 1 PID: %d\n", getpid());
printf("Child 2 PID: %d\n", getpid()-1);
printf("A brawl is surely brewing\n%d Rounds\nFight! \n",turns);
for(i=1; i<=turns; i++){
write(pipe2[1],"Go",strlen("Go")+1);
write(pipe4[1],"Go",strlen("Go")+1);
readbyte = read(pipe1[0],p1,5);
readbyte = read(pipe3[0],p2,5);
printf("Round %d:\n",i);
if((atoi(p1)) == 0){
printf("Child 1 throws Rock\n");
}
else if((atoi(p1)) == 1){
printf("Child 1 throws Paper\n");
}
else{
printf("Child 1 throws Scissors\n");
}
if((atoi(p2)) == 0){
printf("Child 2 throws Rock\n");
}
else if((atoi(p2)) == 1){
printf("Child 2 throws Paper\n");
}
else{
printf("Child 2 throws Scissors\n");
}
if(atoi(p1) == atoi(p2)){
printf("This round is a tie\n");
}
else if((atoi(p1) == 0) && (atoi(p2) == 2)){
printf("Rock beats Scissors: Child 1 wins!\n");
}
else if((atoi(p1) == 0) && (atoi(p2) == 1)){
printf("Paper beats Rock: Child 2 wins!\n");
}
else if((atoi(p1) == 1) && (atoi(p2) == 0)){
printf("Paper beats Rock: Child 1 wins!\n");
}
else if((atoi(p1) == 1) && (atoi(p2) == 2)){
printf("Scissors beats Paper: Child 2 wins!\n");
}
else if((atoi(p1) == 2) && (atoi(p2) == 1)){
printf("scissors beats Paper: Child 1 wins!\n");
}
else if(((atoi(p1)) == 2) && (atoi(p2) == 0)){
printf("Rock beats Scissors: Child 2 wins!\n");
}
}
}
答案 0 :(得分:1)
Fork()使子级继承父级的打开文件描述符,包括pipe()。当所有“编写器”都关闭其管道时,该管道将变得不可读(EOF)。您的管道有多余的“写”端,因此无法正确关闭。
至少,您需要父级来关闭pipe1 [1],pipe3 [1]。一点点检查返回值也可能不会损害您的工作。
答案 1 :(得分:0)
您的分叉是令人困惑的,而不是唯一的问题。
您这样做
叉 如果父项或错误则循环 父母和子女形式 如果是新父母(大孩子)或错误,则循环 三个过程都在等待 …
我建议从一个简单的程序开始,这个程序有一个管道和一个分支(2个进程)。在添加更多功能之前,先使其工作。
有关此更简单的用例https://ctrlaltdelor.wordpress.com/2009/06/23/creation-of-an-interprocess-pipe/的教程,请参见此博客文章,然后根据需要进行扩展。