正确的 fork() 和 pipe() 用于具有多个孩子的单亲。我该怎么做?

Posted

技术标签:

【中文标题】正确的 fork() 和 pipe() 用于具有多个孩子的单亲。我该怎么做?【英文标题】:Proper fork() and pipe() use for a single parent having multiple children. How do I do this right? 【发布时间】:2014-10-13 02:04:44 【问题描述】:

因此,我的PREVIOUS POST 被标记为离题、过于模糊,并要求对有用代码提出意见和建议。它做了这些事情,所以我重新发布一个关于我正在处理的代码的问题。感谢上一篇文章中的那些人,我能够通过回顾你们所说的来拼凑出我在这里的内容。

这里的重点是父/子关系以及使用 fork() 和 pipe() 来获得所需的效果。

该项目是一个 POSIX 纸牌游戏,其中父母(经销商)用他们自己的管道从父母那里分叉成 5 个孩子(玩家)。父母向玩家发牌(每人至少 5 张牌),直到一名玩家拥有 3 个同类(无弃牌)。获胜的孩子将获胜的手牌和 EOF (exit(0)) 发送给父母以宣布胜利。这会触发父级打印获胜玩家并将 EOF 传输给剩余的子级以关闭它们(退出(1))。然后父级关闭。如果父母在没有获胜者的情况下到达甲板的尽头,它将EOF传输给孩子,等待他们退出(1)......然后关闭。

我遇到的主要问题是子程序如何单独读取每张卡片,而不是一遍又一遍地从管道中读取相同的值。我想我缺少一种将父级写入管道和子级从管道读取同步的方法。

我对这些人完全陌生,因此非常感谢任何帮助。非常感谢。

代码已更新:(编译时有很多问题) 完成并编译,但我显然在管道和通过它们中继数据方面遇到了问题。这里有很多错误,从无法玩游戏,到无法读取或写入管道,再到离开僵尸进程。我很感激任何关于我的烂摊子的意见。哈哈

这是我运行程序 (play.c) 时的输出:

os@debian:~/Documents/cpsc351/projects/assn2$ gcc -o play play.c
os@debian:~/Documents/cpsc351/projects/assn2$ ./play
Pipe Success...toChild 1 created.
Pipe Success...toParent 1 created.
Pipe Success...toChild 2 created.
Pipe Success...toParent 2 created.
Pipe Success...toChild 3 created.
Pipe Success...toParent 3 created.
Pipe Success...toChild 4 created.
Pipe Success...toParent 4 created.
Pipe Success...toChild 5 created.
Pipe Success...toParent 5 created.
Parent: All players are at the table.  Dealing cards... 
 30  5C to player 1
 51  KS to player 2
 9  10H to player 3
 25  KD to player 4
 6  7H to player 5
 18  6D to player 1
 45  7S to player 2
 29  4C to player 3
 37  QC to player 4
 12  KH to player 5
 7  8H to player 1
 19  7D to player 2
 20  8D to player 3
 49  JS to player 4
 35  10C to player 5
 15  3D to player 1
 5  6H to player 2
 36  JC to player 3
 0  AH to player 4
 22  10D to player 5
 48  10S to player 1
 27  2C to player 2
 42  4S to player 3
 16  4D to player 4
 32  7C to player 5
 4  5H to player 1
 14  2D to player 2
 41  3S to player 3
 39  AS to player 4
 1  2H to player 5
 26  AC to player 1
 46  8S to player 2
 34  9C to player 3
 11  QH to player 4
 24  QD to player 5
 17  5D to player 1
 31  6C to player 2
 44  6S to player 3
 40  2S to player 4
 3  4H to player 5
 21  9D to player 1
 50  QS to player 2
 13  AD to player 3
 33  8C to player 4
 23  JD to player 5
 43  5S to player 1
 2  3H to player 2
 28  3C to player 3
 47  9S to player 4
 38  KC to player 5
 10  JH to player 1
 8  9H to player 2
Child: Fork Success...Player 4 is sitting at the table.
Child: Player 4 is dealt a KD. Hand Total = 1 cards.
Child: Player 4 is dealt a QC. Hand Total = 2 cards.
Child: Player 4 is dealt a JS. Hand Total = 3 cards.
Child: Player 4 is dealt a AH. Hand Total = 4 cards.
Child: Player 4 is dealt a 4D. Hand Total = 5 cards.
Child: Player 4 is dealt a AS. Hand Total = 6 cards.
Child: Player 4 is dealt a QH. Hand Total = 7 cards.
Child: Player 4 is dealt a 2S. Hand Total = 8 cards.
Child: Player 4 is dealt a 8C. Hand Total = 9 cards.
Child: Player 4 is dealt a 9S. Hand Total = 10 cards.
Child: Fork Success...Player 5 is sitting at the table.
Child: Player 5 is dealt a 7H. Hand Total = 1 cards.
Child: Player 5 is dealt a KH. Hand Total = 2 cards.
Child: Player 5 is dealt a 10C. Hand Total = 3 cards.
Child: Player 5 is dealt a 10D. Hand Total = 4 cards.
Child: Player 5 is dealt a 7C. Hand Total = 5 cards.
Child: Player 5 is dealt a 2H. Hand Total = 6 cards.
Child: Player 5 is dealt a QD. Hand Total = 7 cards.
Child: Player 5 is dealt a 4H. Hand Total = 8 cards.
Child: Player 5 is dealt a JD. Hand Total = 9 cards.
Child: Player 5 is dealt a KC. Hand Total = 10 cards.
Child: Player 5 has left the table.
os@debian:~/Documents/cpsc351/projects/assn2$ Child: Player 4 has left the table.
Child: Fork Success...Player 3 is sitting at the table.
Child: Player 3 is dealt a 10H. Hand Total = 1 cards.
Child: Player 3 is dealt a 4C. Hand Total = 2 cards.
Child: Player 3 is dealt a 8D. Hand Total = 3 cards.
Child: Player 3 is dealt a JC. Hand Total = 4 cards.
Child: Player 3 is dealt a 4S. Hand Total = 5 cards.
Child: Player 3 is dealt a 3S. Hand Total = 6 cards.
Child: Player 3 is dealt a 9C. Hand Total = 7 cards.
Child: Player 3 is dealt a 6S. Hand Total = 8 cards.
Child: Player 3 is dealt a AD. Hand Total = 9 cards.
Child: Player 3 is dealt a 3C. Hand Total = 10 cards.
Child: Player 3 has left the table.
Child: Fork Success...Player 2 is sitting at the table.
Child: Player 2 is dealt a KS. Hand Total = 1 cards.
Child: Player 2 is dealt a 7S. Hand Total = 2 cards.
Child: Player 2 is dealt a 7D. Hand Total = 3 cards.
Child: Player 2 is dealt a 6H. Hand Total = 4 cards.
Child: Player 2 is dealt a 2C. Hand Total = 5 cards.
Child: Player 2 is dealt a 2D. Hand Total = 6 cards.
Child: Player 2 is dealt a 8S. Hand Total = 7 cards.
Child: Player 2 is dealt a 6C. Hand Total = 8 cards.
Child: Player 2 is dealt a QS. Hand Total = 9 cards.
Child: Player 2 is dealt a 3H. Hand Total = 10 cards.
Child: Player 2 is dealt a 9H. Hand Total = 11 cards.
Child: Player 2 has left the table.
Child: Fork Success...Player 1 is sitting at the table.
Child: Player 1 is dealt a 5C. Hand Total = 1 cards.
Child: Player 1 is dealt a 6D. Hand Total = 2 cards.
Child: Player 1 is dealt a 8H. Hand Total = 3 cards.
Child: Player 1 is dealt a 3D. Hand Total = 4 cards.
Child: Player 1 is dealt a 10S. Hand Total = 5 cards.
Child: Player 1 is dealt a 5H. Hand Total = 6 cards.
Child: Player 1 is dealt a AC. Hand Total = 7 cards.
Child: Player 1 is dealt a 5D. Hand Total = 8 cards.
Child: Player 1 has at least "3 of a Kind". Hand Total = 8 cards.

当前代码:

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

#include "cards.h"
#include "cards.c"

#define READ 0
#define WRITE 1

#define PLAYERS 5

int main(int argc, char *argv[])

    //loop declarations ***Would not let me initialize within a for-loop...c99 error.***
    int i;
    int j;  


    pid_t player[PLAYERS];
    int toChild_pipe[PLAYERS][2];
    int toParent_pipe[PLAYERS][2];
    int dealt_card;
    int card_count = 1;
    int player_count = 0;
    int status_forChild;
    int status_forParent;
    int player_card;

    for(i = 0; i < PLAYERS; i++)
    
        // Create the pipes
        if (pipe(toChild_pipe[i]) < 0) 
        
            perror("'To-Child' Pipe Error\n");
            exit(1);
        

        if (pipe(toParent_pipe[i]) < 0) 
        
            perror("'To-Parent' Pipe Error\n");
            exit(1);
        

        // Fork the child (new player)
        player[i] = fork();
        if (player[i] < 0)
        
            perror("Fork Error:");
            printf(" Player %d cloud not sit at table.\n", i+1);
            exit(1);
         

        else if (player[i] > 0) //Parent Process
             
            // Close unsed pipe ends in Parent
            close(toChild_pipe[i][READ]);
            close(toParent_pipe[i][WRITE]);
         

        else //(player[i] == 0)-- Child Process
             
            int player_num = (i+1);
            int player_card;
            int hand[13] = 0;         
            int player_card_count = 0;
            bool game_over = false;


            printf("Child: Fork Success...Player %d is sitting at the table.\n", player_num);

            // Close unsed pipe ends in Parent
            close(toParent_pipe[i][READ]);
            close(toChild_pipe[i][WRITE]);

            while(!game_over)
               

                if ((status_forChild = read(toChild_pipe[i][READ], &player_card, sizeof(player_card))) == 0)
                
                    //EOF from parent.  Player lost.
                    game_over = true;
                    close(toParent_pipe[i][WRITE]);
                    close(toChild_pipe[i][READ]);
                    printf("Child: Player %d has left the table.\n", player_num);
                    exit(1);

                

                else if (status_forChild == -1)
                
                    perror("");
                    printf("Child %d: ERROR: Could not read from pipe.\n", i+1);
                    exit(1);
                

                else
                
                    //Players have 5 cards, loop through hand to check for winner. If yes, WIN.                 
                    if (player_card_count == 5)
                    
                        for (j = 0; j < 13; j++)
                        
                            if(hand[j] >=3)
                            
                                //WINNER! Close process (status = 0) 
                                printf("Child: Player %d has at least. Hand Total = %d cards.\n"
                                    , player_num, rank(player_card));
                                close(toParent_pipe[i][WRITE]);
                                close(toChild_pipe[i][READ]);
                                exit(0);
                            
                        
                    

                    //Read the current card value dealt, increment card value in hand array                 
                    int card_index = value_index(rank(player_card));
                    hand[card_index]++;
                    player_card_count++;


                    printf("Child: Player %d is dealt a %s%s. Hand Total = %d cards.\n", player_num, rank(player_card), 
                        suit(player_card), player_card_count);  

                    if ((hand[card_index] >= 3)&&(player_card_count > 5)) //at least (3 of a kind) and (> 5 card hand)
                    
                        //WINNER! Close process (status = 0) 
                        printf("Child: Player %d has at least. Hand Total = %d cards.\n", player_num, rank(player_card));
                        close(toParent_pipe[i][WRITE]);
                        close(toChild_pipe[i][READ]);
                        exit(0);
                     
                
            
        
    

    shuffle();
    printf("Parent: All players are at the table.  Dealing cards... \n");

    while ((dealt_card = deal()) != EOF) 
    

        //Card is written to the pipe for current player        
        if ((status_forParent = write(toChild_pipe[i][WRITE], &dealt_card, sizeof(dealt_card))) == -1)
                   
            perror("");
            printf("Parent: ERROR: Could not read from pipe for Child %d.\n", i+1);
            exit(1);
        

        //If child process exited with status = 0, child had 3 of a kind and wins game.
        else if (status_forParent == 0)
                   
            printf("Parent: Player %d has WON!!!\n", player_count+1, rank(player_card));
            break;
           

        else    
        

            printf(" %d  %s%s to player %d\n", dealt_card, rank(dealt_card), suit(dealt_card), player_count+1);

            if (player_count >= PLAYERS-1)
                player_count = 0;           
            else
                player_count++;


        
    
    // Close pipe ends
    close(toParent_pipe[i][READ]);
    close(toChild_pipe[i][WRITE]);
    wait(NULL);
    return 0;

【问题讨论】:

每个孩子需要两个管道,每个方向一个。父级可以使用select() 来监控子级可以写入的所有管道,以确定是否可以读取。 @Paul Griffiths 所以像int toChild_pipe[PLAYERS][2], toParent_pipe[PLAYERS][2]; ...然后以相同的方式创建两个管道? 是的,没错。例如,当每个孩子准备好一张新卡片时,每个孩子都可以在其写入管道中写入一个特定的字符,或者如果它宣布胜利,则可以写入一个不同的字符。然后,父母可以依次阅读它们并采取相应的行动。如果父母总是按顺序处理和读取每个孩子,当它准备好时,那么你甚至不需要select(),只需循环并等待read() 一个实际的系统调用。 作为一般规则,如果您发现自己真的完全抓住了救命稻草,那么是时候做一些更简单的事情了。话虽如此,我写了一个答案,它不会为您制作游戏,但向您展示了一个示例机制,它将满足您的需求。对于您的问题,父级知道管道已被读取,因为它等待子级写入另一个管道来告诉它。 【参考方案1】:

您遇到的基本问题是您依赖 EOF 来检测事物,但是直到管道写入端的所有句柄都关闭后才会发生 EOF。所以你必须小心关闭所有进程中所有不需要的句柄。

在您的代码中,您有一个创建管道的循环,然后是分叉:

首先为子 0 创建两个管道 然后 fork child 0 child 0 关闭这些管道的父端,而 parent 关闭这些管道的子端(好) 循环 为子 1 创建两个管道 叉子 1 child 1 关闭其管道的父端,而 parent 关闭子端。

此时,您遇到了一个问题——子 1 已将管道的父端继承给子 0,但并未关闭它们。这意味着子 0 在从父级读取时将无法检测到 EOF。孩子 2 和以后的孩子也会发生同样的事情。

【讨论】:

那么我该如何防止这种继承呢?这是否意味着孩子 2 从 0-1 继承所有父端,孩子 3 从 0-1-2 继承所有父端,......等等?此外,游戏现在似乎可以工作了(我在之前的帖子中使用了错误的迭代器来循环)。但是有一些大问题。 1)它为每个孩子输出块而不是顺序(奇怪)。 2)由于父母无法检测到获胜者的EOF,因此它会继续向其他玩家发牌。 3)它挂在wait()。 (我想我用错了。我的意图是等待所有孩子结束,然后继续) 你不能阻止继承——fork 会自动继承所有打开的文件描述符。如果您不希望它们在子级中打开,则需要在分叉后在子级中关闭它们。【参考方案2】:

这种看起来像是纯代码的答案,但实际上并非如此,因为代码中的 cmets 解释了发生了什么。这与您正在编写的游戏不同,但显示了您正在寻找的机制。您可以根据自己的具体情况调整这种框架。

代码:

/*  Demonstration of multiplayer "game" with processes.
 *
 *  The parent sets up a number of processes equal to NUM_KIDS.
 *  It loops through each one in turn, and writes a character to
 *  each child, beginning with one. The child reads it, and if
 *  that character is the winning number, it writes back to the
 *  parent to notify it, and exits. If it's not the winning
 *  character, it writes a different character to the parent (which
 *  is ignored) and waits for another character to read. If it
 *  reads the game over character, it exits. 
 *
 *  It's not a very fun game, but demonstrates how a number of
 *  child processes can act as different players, how they can
 *  receive input from the parent and, based on that input, how
 *  they can determine a win situation and notify the parent of
 *  such.
 */


#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>


#define NUM_KIDS 5

static const int CHILD_NO_WIN = 0;  /*  Child sends this if it doesnt win    */
static const int CHILD_WIN = 1;     /*  Child sends this if it wins          */
static const int GAME_OVER = 0;     /*  Child loses if it receives this      */
static const int WINNER = 13;       /*  Child wins if it receives this       */


/*  Convenience function to make a pair of pipes  */

void make_pipe_pair(int * pair1, int * pair2)

    if ( pipe(pair1) == -1 || pipe(pair2) == -1 ) 
        perror("couldn't create pipe");
        exit(EXIT_FAILURE);
    



/*  Convenience function to close a pair of file descriptors  */

void close_pair(const int rfd, const int wfd)

    if ( close(rfd) == -1 || close(wfd) == -1 ) 
        perror("couldn't close file");
        exit(EXIT_FAILURE);
    



/*  Main child process function  */

void child_func(const int rpipe, const int wpipe, const size_t child_id)

    char out_c = CHILD_NO_WIN;      /*  Character to write  */
    char in_c;                      /*  Character to read   */
    bool keep_reading = true;

    while ( keep_reading ) 

        /*  Read a single character from the parent  */

        ssize_t num_read;
        if ( (num_read = read(rpipe, &in_c, 1)) == -1 ) 
            perror("error reading from pipe in child");
            exit(EXIT_FAILURE);
        
        else if ( num_read == 0 ) 
            printf("Pipe from parent closed to child %zu.\n", child_id);
            keep_reading = false;
        
        else 
            printf("Child %zu read %d from parent.\n", child_id, in_c);

            if ( in_c == GAME_OVER ) 

                /*  We lost, so tell loop to end. No need to write()
                 *  to parent, since it already knows a previous
                 *  child won.                                        */

                printf("Child %zu got game over signal.\n", child_id);
                keep_reading = false;
            
            else 
                if ( in_c == WINNER ) 

                    /*  We won, so send won signal to parent  */

                    out_c = 1;
                

                /*  Write won signal to parent if we won, or
                 *  other character if we didn't.             */

                if ( write(wpipe, &out_c, 1) == -1 ) 
                    perror("error writing to pipe in child");
                    exit(EXIT_FAILURE);
                
                else 
                    printf("Child %zu wrote %d to parent.\n", child_id, out_c);
                
            
        
    


    /*  Close file descriptors and exit  */

    close_pair(rpipe, wpipe);



/*  Main function  */

int main(void)

    int ptoc_fd[NUM_KIDS][2];   /*  Parent to child pipes    */
    int ctop_fd[NUM_KIDS][2];   /*  Child to parent pipes    */
    pid_t children[NUM_KIDS];   /*  Process IDs of children  */
    int winning_child;          /*  Holds number of winner   */


    /*  Create pipe pairs and fork children  */

    for ( size_t i = 0; i < NUM_KIDS; ++i ) 
        make_pipe_pair(ptoc_fd[i], ctop_fd[i]);

        if ( (children[i] = fork()) == -1 ) 
            perror("error calling fork()");
            return EXIT_FAILURE;
        
        else if ( children[i] == 0 ) 
            printf("Child %zu created.\n", i + 1);
            close_pair(ctop_fd[i][0], ptoc_fd[i][1]);
            child_func(ptoc_fd[i][0], ctop_fd[i][1], i + 1);
            printf("Child %zu terminating.\n", i + 1);
            return EXIT_SUCCESS;
        
        else 
            close_pair(ptoc_fd[i][0], ctop_fd[i][1]);
        
    


    /*  Set up game variables and enter main loop  */

    char out_c = 1;
    char in_c = 0;
    bool won = false;

    while ( !won ) 

        /*  Loop through each child  */

        for ( size_t i = 0; !won && i < NUM_KIDS; ++i ) 

            /*  Write next number to child  */

            if ( write(ptoc_fd[i][1], &out_c, 1) == -1 ) 
                perror("error writing to pipe");
                exit(EXIT_FAILURE);
            
            else 
                printf("Parent wrote %d to child %zu.\n", out_c, i+1);
            

            ++out_c;


            /*  Read status from child if game not over  */

            if ( !won ) 
                ssize_t num_read;
                if ( (num_read = read(ctop_fd[i][0], &in_c, 1)) == -1 ) 
                    perror("error reading from pipe");
                    return EXIT_FAILURE;
                
                else if ( num_read == 0 ) 
                    printf("Pipe from child %zu closed.\n", i+1);
                
                else 
                    printf("Parent read %d from child %zu.\n", in_c, i+1);
                    if ( in_c == CHILD_WIN ) 
                        printf("Parent got won signal from child %zu.\n", i+1);
                        won = true;
                        winning_child = i+1;
                    
                
            
        
    


    /*  Clean up and harvest dead children  */

    out_c = 0;
    for ( size_t i = 0; i < NUM_KIDS; ++i ) 
        if ( write(ptoc_fd[i][1], &out_c, 1) == -1 ) 
            perror("error writing to pipe");
            exit(EXIT_FAILURE);
        
        else 
            printf("Parent wrote %d to child %zu.\n", out_c, i + 1);
        

        if ( waitpid(children[i], NULL, 0) == -1 ) 
            perror("error calling waitpid()");
            return EXIT_FAILURE;
        
        else 
            printf("Successfully waited for child %zu.\n", i + 1);
        

        close_pair(ptoc_fd[i][1], ctop_fd[i][0]);
    


    /*  Show who won, and then quit.  */

    printf("Parent terminating. Child %d won.\n", winning_child);

    return EXIT_SUCCESS;

和输出:

paul@thoth:~/src/sandbox/multipipe$ ./multipipe
Child 1 created.
Child 1 read 1 from parent.
Parent wrote 1 to child 1.
Child 1 wrote 0 to parent.
Child 3 created.
Parent read 0 from child 1.
Parent wrote 2 to child 2.
Child 2 created.
Child 2 read 2 from parent.
Parent read 0 from child 2.
Parent wrote 3 to child 3.
Child 3 read 3 from parent.
Parent read 0 from child 3.
Child 4 created.
Parent wrote 4 to child 4.
Child 3 wrote 0 to parent.
Child 2 wrote 0 to parent.
Child 4 read 4 from parent.
Child 5 created.
Parent read 0 from child 4.
Parent wrote 5 to child 5.
Child 4 wrote 0 to parent.
Child 5 read 5 from parent.
Parent read 0 from child 5.
Parent wrote 6 to child 1.
Child 5 wrote 0 to parent.
Child 1 read 6 from parent.
Parent read 0 from child 1.
Parent wrote 7 to child 2.
Child 1 wrote 0 to parent.
Child 2 read 7 from parent.
Parent read 0 from child 2.
Parent wrote 8 to child 3.
Child 3 read 8 from parent.
Parent read 0 from child 3.
Child 2 wrote 0 to parent.
Parent wrote 9 to child 4.
Child 4 read 9 from parent.
Parent read 0 from child 4.
Parent wrote 10 to child 5.
Child 3 wrote 0 to parent.
Child 4 wrote 0 to parent.
Child 5 read 10 from parent.
Child 5 wrote 0 to parent.
Parent read 0 from child 5.
Parent wrote 11 to child 1.
Child 1 read 11 from parent.
Parent read 0 from child 1.
Parent wrote 12 to child 2.
Child 2 read 12 from parent.
Child 1 wrote 0 to parent.
Parent read 0 from child 2.
Parent wrote 13 to child 3.
Child 3 read 13 from parent.
Parent read 1 from child 3.
Parent got won signal from child 3.
Parent wrote 0 to child 1.
Child 2 wrote 0 to parent.
Child 1 read 0 from parent.
Child 1 got game over signal.
Child 1 terminating.
Child 3 wrote 1 to parent.
Successfully waited for child 1.
Parent wrote 0 to child 2.
Child 2 read 0 from parent.
Child 2 got game over signal.
Child 2 terminating.
Successfully waited for child 2.
Parent wrote 0 to child 3.
Child 3 read 0 from parent.
Child 3 got game over signal.
Child 3 terminating.
Successfully waited for child 3.
Parent wrote 0 to child 4.
Child 4 read 0 from parent.
Child 4 got game over signal.
Child 4 terminating.
Successfully waited for child 4.
Parent wrote 0 to child 5.
Child 5 read 0 from parent.
Child 5 got game over signal.
Child 5 terminating.
Successfully waited for child 5.
Parent terminating. Child 3 won.
paul@thoth:~/src/sandbox/multipipe$

输出看起来有点奇怪,看起来进程在写入之前正在读取内容,但是当您使用异步进程并且不费心为演示目的同步输入/输出时会发生这种情况。对管道的实际读取和写入行为良好且同步,只是进入标准输出的调试消息看起来很奇怪。您应该仍然可以看到发生了什么。

【讨论】:

对理解这一点很有帮助。特别是在将其插入颜色编码编辑器之后。谢谢! 你应该在孩子中使用_exit(EXIT_SUCCESS) 而不是return EXIT_SUCCESS @J.F.Sebastian:有时这就是您想要做的,但在这里没有任何区别,因为当孩子退出时没有退出处理程序和未刷新的 stdio 缓冲区(提供没有人采取将这个输出重定向到文件的稍微奇怪的步骤,即使在这种情况下,这里的 stdio 表现得很糟糕,开始时它不会产生任何实际影响)。 printf()fork() 之后可能会导致输出乱码。 父进程使用write()的方式,read()可以在写入超过PIPE_BUF字节的情况下序列化子进程。您可能应该将select 循环放入父级。

以上是关于正确的 fork() 和 pipe() 用于具有多个孩子的单亲。我该怎么做?的主要内容,如果未能解决你的问题,请参考以下文章

C - 内部带有 fork() / pipe() 的 WHILE 循环

popen() 可以制作像 pipe() + fork() 这样的双向管道吗?

C fork 和 pipe 从文件中添加数字

linux下fork两子进程为啥只有一个读取到pipe的内容?

Linux pipe 源代码分析

c_cpp 一个小样本程序模拟几个工人交替使用fork()和pipe()