带管道的非终止C程序

时间:2018-10-31 17:05:36

标签: c unix pipe

我正在尝试使用管道编写一个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");
    }
}
}

2 个答案:

答案 0 :(得分:1)

Fork()使子级继承父级的打开文件描述符,包括pipe()。当所有“编写器”都关闭其管道时,该管道将变得不可读(EOF)。您的管道有多余的“写”端,因此无法正确关闭。

至少,您需要父级来关闭pipe1 [1],pipe3 [1]。一点点检查返回值也可能不会损害您的工作。

答案 1 :(得分:0)

您的分叉是令人困惑的,而不是唯一的问题。

您这样做

叉 如果父项或错误则循环 父母和子女形式 如果是新父母(大孩子)或错误,则循环 三个过程都在等待 …

我建议从一个简单的程序开始,这个程序有一个管道和一个分支(2个进程)。在添加更多功能之前,先使其工作。

有关此更简单的用例https://ctrlaltdelor.wordpress.com/2009/06/23/creation-of-an-interprocess-pipe/的教程,请参见此博客文章,然后根据需要进行扩展。