简体   繁体   English

带管道的非终止C程序

[英]Nonterminating C program with pipes

I am attempting to write a C program, using pipes, to play the game of “rock, paper, scissors”, between two children. 我正在尝试使用管道编写一个C程序,以在两个孩子之间玩“石头,纸,剪刀”游戏。 I have most of the code written and working. 我已经编写和工作了大部分代码。 When I run the code it plays the game, but refuses to terminate. 当我运行代码时,它会玩游戏,但拒绝终止。 It locking down the terminal, and forces me to close it and try again. 它锁定了终端,并迫使我将其关闭,然后重试。 I am not sure as to why this is. 我不确定为什么会这样。

    #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");
    }
}
}

Fork() causes the child to inherit the open file descriptors of the parent, including pipe()s. Fork()使子级继承父级的打开文件描述符,包括pipe()。 A pipe becomes unreadable (EOF) when all “writers” have closed their pipe. 当所有“编写器”都关闭其管道时,该管道将变得不可读(EOF)。 You have extraneous “write” ends of a pipe open, thus it will not close properly. 您有多余的管道“写”端打开,因此它将无法正确关闭。

At a minimum, you need the parent to close pipe1[1], pipe3[1]. 至少,您需要父级来关闭pipe1 [1],pipe3 [1]。 A little bit of checking return values probably wouldn't hurt your effort either. 一点点检查返回值也可能不会损害您的工作。

Your forking is confusing, and not the only problem. 您的分叉令人困惑,而不是唯一的问题。

you do 你做

fork if parent or error then loop both parent and child form if new parent (old child) or error then loop all three processes wait … 如果父项或错误发生,则派生,如果新的父项(旧子项)或错误发生,则循环父项和子项形式,然后循环所有三个进程,等待…

I would advise starting with a simple program with one pipe and one fork (2 processes). 我建议从一个简单的程序开始,这个程序有一个管道和一个分支(2个进程)。 Get this to work before adding more. 在添加更多内容之前,先使其工作。

See this blog post for a tutorial of this simpler use case https://ctrlaltdelor.wordpress.com/2009/06/23/creation-of-an-interprocess-pipe/ then expand for what you need. 请参阅此博客文章,以获取有关此简单用例的教程https://ctrlaltdelor.wordpress.com/2009/06/23/creation-of-an-interprocess-pipe/然后根据需要进行扩展。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM