【问题标题】:Is brother-brother pipe safer than father-child?兄弟管比父子更安全吗?
【发布时间】:2015-09-29 22:03:19
【问题描述】:

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

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

#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);
    }
}

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

【问题讨论】:

    标签: c unix process pipe child-process


    【解决方案1】:

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

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

    如果孩子早于爸爸(僵尸)或爸爸早于孩子(孤儿)完成会怎样?

    如果父亲在 fork 一个孩子之后调用 exec() 函数,然后再通过 wait()waitpid() 收集它,如示例代码中所示,则不太可能等待孩子。

    不管怎样,孩子和爸爸在终止时都会变成僵尸。无论孩子是否首先成为孤儿,这对孩子来说都是如此。如果爸爸从不收集孩子(在你的例子中不会),那么一旦爸爸终止,孩子(无论是活的还是僵尸的)都会被进程 0(init)继承,可以依靠它来清理它所有的僵尸孩子.同样,如果爷爷从不收集爸爸,那么 init 最终会这样做。

    在某些情况下,僵尸可能会聚集起来而未被收集。这是一种资源泄漏的形式,但最终会在僵尸被 init 继承时被清理掉。您设置的爷爷 -> 父 -> 子拓扑稍微加剧了这种情况,但我不会将其描述为“容易出错”。

    【讨论】:

      【解决方案2】:

      如果孩子比爸爸(僵尸)早完成会发生什么......

      这将是一个僵尸进程。一旦父母在孩子没有waiting 的情况下完成,孩子将重新成为init 的父母。然后initwait 在孩子身上,检索其退出代码并允许其最终退出。

      ...或者爸爸比孩子(孤儿)早完成?

      孤立的进程被重新设置为init。该过程将与上述相同。

      【讨论】:

      • 所以父子可以导致这些情况,而兄弟之间的管道不能,因为父亲会等待他的两个孩子(兄弟),因此第二个更安全
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-02
      • 1970-01-01
      • 1970-01-01
      • 2011-09-28
      • 1970-01-01
      • 2012-11-19
      相关资源
      最近更新 更多