c - 带管道的非终止 C 程序

标签 c unix pipe

我正在尝试编写一个C程序,使用管道在两个 child 之间玩“石头、剪刀、布”的游戏。我已经编写并运行了大部分代码。当我运行代码时,它会玩游戏,但拒绝终止。它锁定了终端,并迫使我关闭它并重试。我不确定这是为什么。

    #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() 使子进程继承父进程的打开文件描述符,包括 pipeline()。当所有“编写者”都关闭其管道时,管道将变得不可读(EOF)。您打开了管道的无关“写入”端,因此它将无法正确关闭。

至少,您需要父级关闭 pipeline1[1]、pipe3[1]。稍微检查一下返回值可能也不会损害您的努力。

关于c - 带管道的非终止 C 程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53088681/

相关文章:

c - 无法访问共享内存内容

regex - 如何让 grep 输出所有匹配的行?

c - OpenBSD 和 Linux 上 pthread_cond_wait 的不同行为

c - 在 c 中创建的 minishell 无法按预期工作,与管道相关

c - 由于快速松弛数学而导致可接受的精度降低

c - 链接列表未显示正确的数据

c - kbhit() 和 getch() 和系统 ("cls"的可移植替代方案)

c - (C) 在for循环下删除整型数组的元素,只有满足条件

c - 双向 popen() 在 C 中的 Mac OS X 上工作吗?

c - 从父进程到子进程并返回的管道