brother-brother 管道是否比 father-child 更安全?

Is brother-brother pipe safer than father-child?

在两个进程之间建立管道的情况下,如果这两个进程是兄弟关系而不是father-child,他们会更容易出错吗?

我在调查下面的代码示例时提出了这个问题:

#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>

void runpipe();

int
main(int argc, char **argv)
{
    int pid, status;
    int fd[2];

    pipe(fd);

    switch (pid = fork())
    {

    case 0: /* child */
        runpipe(fd);
        exit(0);

    default: /* parent */
        while ((pid = wait(&status)) != -1) {
            fprintf(stderr, "process %d exits with %d\n", pid, WEXITSTATUS(status));
            exit(0);
        }

    case -1:
        perror("fork");
        exit(1);
    }
    exit(0);
}

char *cmd1[] = { "ls", "-al", "/", 0 };
char *cmd2[] = { "tr", "a-z", "A-Z", 0 };

void
runpipe(int pfd[])
{
    int pid;

    switch (pid = fork())
    {

    case 0: /* child */
        dup2(pfd[0], 0);
        close(pfd[1]);  /* the child does not need this end of the pipe */
        execvp(cmd2[0], cmd2);
        perror(cmd2[0]);

    default: /* parent */
        dup2(pfd[1], 1);
        close(pfd[0]);  /* the parent does not need this end of the pipe */
        execvp(cmd1[0], cmd1);
        perror(cmd1[0]);


    case -1:
        perror("fork");
        exit(1);
    }
}

在上面的例子中,parent(grandpa) 分叉了一个 child(parent),然后分叉了另一个 child(grandchild) .爷爷等爸爸,但爸爸不等孙子,因为他们都执行 execvp。如果 child 早于爸爸(僵尸)完成或爸爸早于 child(孤儿)完成,会发生什么情况?另一方面,如果我们有两个兄弟连接到管道和一个父亲并等待他们(总共三个进程),即使他们两个兄弟都执行了 execvp,一个退出也不会伤害另一个。

What happens if child finishes earlier than dad (zombie)...

这将是一个僵尸进程。一旦 parent 在 child 上没有 wait 完成,child 将是 re-parented 到 initinit 将在 child 上 wait,检索其退出代码并允许其最终退出。

...or dad finishes earlier than child (orphan) ?

孤立进程为 re-parented 到 init。然后过程将与上述相同。

In the case of establishing a pipe between two processes, if those two have a brother to brother relationship rather than a father-child, will they be more error prone ?

就管道而言,一切都取决于每个执行的 I/O 操作。如果读端的进程试图读取另一端的进程不准备写入的数据,那么它将阻塞直到写入者写入或退出。后一种情况,读取要么报错,要么return短数据。

What happens if child finishes earlier than dad (zombie) or dad finishes earlier than child (orphan) ?

如果父亲在分叉 child 之后调用 exec() 函数,然后通过 wait()waitpid() 收集它,如示例代码所示,那么它是不太可能等待 child.

无论如何,child和爸爸在死亡时都变成了僵尸。 child 是这样的,不管它是否先被孤立。如果爸爸从不收集 child(在你的例子中它不会),那么一旦爸爸终止,child(无论是活的还是僵尸)被进程 0(init)继承,这可以依赖清理它所有的僵尸children。同样,如果爷爷从不收集爸爸,那么 init 最终会收集。

在某些情况下,僵尸可能会在未收集的情况下堆积起来。这是一种资源泄漏,但最终会在 init 继承僵尸时被清除。祖父 -> parent -> child 您设置的拓扑略微加剧了这种情况,但我不会将其描述为 "error prone."