管道兄弟姐妹子进程之间的共享

时间:2017-01-20 00:31:07

标签: c process pipe

在以下代码中,我希望子c1阻止(通过管道),直到孩子c2完成(通过pipe_close()中的c2)。但它不起作用。 c1会永远阻止。如果我将pipe_close()移出c2并将其放在父级中,它就会起作用。

这是因为从父级创建的管道在兄弟子进程之间不可共享吗?

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdarg.h>

static void pipe_close(int *);
static void pipe_read(int *);

int
main(void)
{
    int pp_main[2] = {-1, -1};
    pipe(pp_main);

    int ppid = getpid();
    int pgid = getpgrp();

    int pid_c1 = fork();
    if (pid_c1 == 0)
    {  // in child c1
        int cpid_c1 = getpid();
        int gid = getpgrp();
        printf("[c1][%d][%d] is made, wait pipe ready\n", cpid_c1, gid);
        pipe_read(pp_main);
        printf("[c1][%d][%d] done\n", cpid_c1, gid);
    }
    else
    {  // in parent
        printf("[main][%d][%d] created child c1: %d\n", ppid, pgid, pid_c1);
        int pid_c2 = fork();
        if (pid_c2 == 0)
        {  // in child c2
            int cpid_c2 = getpid();
            int gid = getpgrp();
            printf("[c2][%d][%d] is made\n", cpid_c2, gid);
            for (int i = 2; i > 0; --i)
            {
                printf("[c2][%d][%d] count down %d\n", cpid_c2, gid, i);
                sleep(1);
            }
            pipe_close(pp_main);
            printf("[c2][%d][%d] done\n", cpid_c2, gid);
        }
        else
        {   // in parent
            printf("[main][%d][%d] created child c2: %d\n", ppid, pgid, pid_c2);
        }
        int status;
        waitpid(pid_c2, &status, 0);
    }

    int status;
    waitpid(pid_c1, &status, 0);
    return 0;
}

static void
pipe_read(int *pp)
{
    char ch;
    if (pp[1] >= 0)
    {
        close (pp[1]);
        pp[1] = -1;
    }
    if (pp[0] >= 0)
    {
        while (read (pp[0], &ch, 1) == -1 && errno == EINTR);
    }
}

static void
pipe_close(int *pp)
{
    if (pp[0] >= 0)
        close (pp[0]);
    if (pp[1] >= 0)
        close (pp[1]);
    pp[0] = pp[1] = -1;
}

1 个答案:

答案 0 :(得分:1)

  

如果我将pipe_close()移出c2并将其放在父级中,它就可以工作。

这是预期的行为。在关闭所有引用之前,管道未完全关闭。在您的代码中,pipe是在fork之前创建的。因此,父进程和子进程都打开了该管道。 c2子进程将退出,以便关闭对管道的引用。但是,父进程阻止等待c1退出。这将永远不会发生,因为父进程没有显式或隐式(通过退出)关闭管道。