哥哥兄弟管比父亲孩子更安全吗?

时间:2015-09-29 22:03:19

标签: c unix process pipe child-process

如果在两个进程之间建立管道,如果这两个进程有兄弟关系而不是父子关系,那么它们是否会更容易出错?

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

#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,一个退出也不会伤害另一个。

2 个答案:

答案 0 :(得分:2)

  

如果在两个进程之间建立管道,如果这两个进程有兄弟关系而不是父子关系,那么它们是否会更容易出错?

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

  

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

如果父亲在分娩后调用exec()函数并在通过wait()waitpid()收集之前调用#include <iostream> long int even_sum_fibonacci(int n){ int i = 8; int previous_i = 2; int next_i = 0; long int sum = previous_i + i;; while(n>next_i){ next_i = i*4 + previous_i; previous_i = i; i = next_i; sum = sum + i; } return sum - next_i; //now next_i and i are both the bigger number which //exceeds 4 million, but we counted next_i into sum //so we'll need to substract it from sum } int main() { std::cout << even_sum_fibonacci(4000000) << std::endl; return 0; } 函数,如示例代码所示,则不太可能等待子。

无论如何,孩子和爸爸在终止时都会成为僵尸。无论孩子是否先成为孤儿,都是如此。如果爸爸从不收集孩子(因为它在你的例子中没有收获),那么一旦爸爸终止,孩子(无论是活的还是僵尸)是由进程0(init)继承的,可以依赖它来清理所有的僵尸儿童。同样,如果爷爷永远不会收集爸爸,那么init最终会这样做。

在某些情况下,僵尸可能会无法收集。这是一种资源泄漏形式,但最终会在init继承僵尸时进行清理。爷爷稍微加剧了这一点 - &gt;父母 - &gt;您已设置的子拓扑,但我不会将其描述为容易出错。&#34;

答案 1 :(得分:1)

  

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

这将是一个僵尸进程。一旦父母完成而没有init孩子,孩子将重新成为init的父母。 wait然后init将关注孩子,检索其退出代码并允许其最终退出。

  

...或者爸爸比孩子(孤儿)早结束?

孤立的进程重新成为div.onclick = function (e, z) 的父级。然后,过程将与上述过程相同。