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 到 init
。 init
将在 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."
在两个进程之间建立管道的情况下,如果这两个进程是兄弟关系而不是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 到 init
。 init
将在 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."