单个父进程有多个子进程,如何正确使用fork()和pipe()?我该怎么做?

3
因为我的先前的帖子被标记为离题、过于模糊并要求意见和推荐有用的代码,所以我将其重新发布为我正在处理的代码问题的问题。感谢前一篇文章中的人们,通过回顾你们说的话,我能够从中拼凑出我现在的代码。 重点是父/子关系及使用fork()和pipe()来实现所需效果。 该项目是一个POSIX纸牌游戏,其中父进程(荷官)分叉成5个子进程(玩家),每个子进程都有自己从父进程读取和写入的管道。直到一个玩家有3张相同的牌(不抛弃),父程序发牌给玩家(每个玩家至少发5张牌)。获胜的孩子发送获胜的手牌和EOF(退出(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;
}

3
每个子进程需要两个管道,每个方向一个。父进程可以使用 select() 来监控所有子进程可以写入的管道,以确定哪个管道已准备好读取。 - Crowman
1
是的,没错。例如,每个子进程可以在其写通道上写入特定的字符,以表示它准备好新的卡牌,或者如果它宣布胜利则写入不同的字符。然后父进程可以按顺序读取它们并相应地采取行动。如果父进程总是按顺序分配和读取每个子进程,那么当它准备好时,甚至不需要使用 select(),只需循环并等待 read() 即可。 - Crowman
1
一个真正的系统调用。 - Crowman
@Paul Griffiths 好的,那很有道理。但是孩子如何让父进程知道管道已经被读取了呢?从您的评论中,我最初认为它正在寻找从READ管道发送的“我准备好了”值。我更改了代码以反映这一点,在读取完毕后,Child会写入111,以便让Parent知道可以处理另一张卡。while循环会停滞,直到可以从Parent的读取管道中读取到111。这里的系统调用会怎样工作?更具体地说,父进程如何知道管道已经被读取并且可以继续进行?顺便说一下,谢谢您迄今为止所做的工作。 - LazyBear
1
一般来说,如果你发现自己真的是在拼命地摸索,那么就是时候去做一些更简单的事情了。话虽如此,我写了一个答案,它不会为你制作游戏,但会向你展示一个例子机制,可以实现你想要的功能。对于你的问题,父进程知道管道已经被读取,因为它等待子进程写入其另一个管道,以告诉它这一点。 - Crowman
显示剩余3条评论
2个回答

2
你面临的基本问题是依赖EOF来检测事情,但是EOF不会发生直到管道写端上的所有句柄都关闭。因此,你必须小心关闭所有进程中不需要的句柄。
在你的代码中,你有一个循环创建管道,然后分叉:
首先,你为子0创建两个管道;
然后分叉子0;
子0关闭这些管道的父端,而父进程关闭这些管道的子端(好的);
循环:
为子1创建两个管道;
分叉子1;
子1关闭其管道的父端,而父进程关闭子端。
此时,你面临一个问题——子1继承了传递给子0的管道的父端,但没有关闭它们。这意味着子0将无法检测到从父进程读取的EOF。对于子2和后续子进程也是同样的情况。

那么我该如何防止继承呢?这是否意味着子类2从0-1继承所有父类端点,子类3从0-1-2继承所有父类端点,等等?此外,游戏似乎现在有点运行了(我在之前的帖子中在我的主循环中使用了错误的迭代器)。但是还有一些大问题。1)它以每个子级块输出而不是顺序输出(奇怪)。2)由于父级无法检测到获胜者的EOF,因此它会继续向其他玩家发牌。3)它在“wait()”处挂起。(我认为我使用它是错误的。我的意图是等待所有子进程结束,然后继续进行) - LazyBear
你无法阻止继承 -- fork 会自动继承所有打开的文件描述符。如果你不想在子进程中保持这些文件描述符打开状态,那么你需要在 fork 后在子进程中关闭它们。 - Chris Dodd

0

这似乎是一个仅包含代码的答案,但实际上不是,因为代码中的注释解释了正在发生的事情。虽然它不是你正在编写的同一款游戏,但展示了你正在寻找的机制。你可以将这种框架调整到你的具体情况。

代码:

/*  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$

输出看起来有点奇怪,似乎进程在写入之前就读取了一些东西,但这是在使用异步进程并且为演示目的而不进行输入/输出同步时发生的情况。实际读写管道是良好行为和同步的,只是调试消息发送到标准输出看起来有些混乱。您仍然应该能够看到正在发生的事情。


非常有帮助,特别是在将其插入彩色编码编辑器后。谢谢! - LazyBear
在子进程中,应该使用_exit(EXIT_SUCCESS)而不是return EXIT_SUCCESS - jfs
如果任何子进程停止读取,而父进程对应的管道调用write()函数写入了PIPE_BUF次数据,你认为会发生什么? - jfs
@J.F.Sebastian:不会的。父进程在子进程读取管道并写回告诉它之前不会第二次调用write()。如果子进程停止读取,则它将停止写入,父进程的read()将永远阻塞。这里任何一个管道中永远不会有多于一个字符。 - Crowman
我说孩子可能停止阅读。这并不意味着它不能写。如果我们假设孩子的行为与所写的完全一致,则行为已经被序列化了。 - jfs
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接