如果我在 parent 和 child 中 fork 并执行会发生什么?
What will happen if I fork and exec in parent and child?
这是我的示例代码,名为 server.c(已删除包含以保持简单)。
int main()
{
for(int i = 0; i < 10; i++) {
fork();
execl("./client", "./client", NULL);
}
if (wait(NULL) == -1)
perror("error with wait");
return 0;
}
这是从上述程序中执行的客户端代码。
int main()
{
printf("This is the child with pid = %d from parent %d", getpid(), getppid());
return 0;
}
现在让我解释一下我认为会发生什么以及我实际得到的输出。
在服务器中,我们进入for循环。在第一次迭代中,我们点击了 fork()。此时有两个进程,即parent和第一个child。现在我们从这两个进程中执行一个名为 "client" 的程序。此客户端代码仅打印一些信息。所以当我 运行 这个服务器程序时,我应该得到两行,对吧?一行来自 parent,另一行来自 child?但是我只打印了一行,在使用 strace 之后我发现只有 parent 正在打印东西,而不是 child。那这是为什么?
是否因为 child 已被执行而无法再收集,因为 parent 已死(这是正确的术语吗?)?如果是这样,child 会怎样?变成丧尸了吧?它会被init收集吗?即便如此,为什么它在像僵尸一样结束之前不打印出那一行?
If stdout is connected to a terminal, it should be line-buffered, so there's no need to flush. And all streams are flushed automatically when they're closed, which happens when the program finishes.
也许你看到两者打印在同一行?
试试这个代码:
#include <stdio.h>
int main(int argc, char **argv) {
printf("This is the child with pid = %d from parent %d\n", getpid(), getppid());
return 0;
}
顺便说一下,您在 printf
中缺少一个 %d
。
你绝对应该得到两条线。
如果不是,可能是因为您 运行 程序的使用方式。 parent 可能会打印并退出,如果您此时停止查看或收听,您将丢失来自 child.
的消息
因此,请确保您直接从 shell 终端 运行 脚本,而不是来自 IDE、编辑器或任何其他脚本的脚本的一部分工具.
例如,这里是 ./server; echo "Done"
的输出:
user ~ $ ./server; echo "Done."
This is the child with pid = 27904 from parent
Done.
这使得看起来只有一行输出。但是,在这之后的行中,提示返回并且 child 进程在其后写入了一些信息:
user ~ $ This is the child with pid = 27905 from parent
如果您 运行 以 shell 等待的方式编写脚本,例如添加 | cat
将等待管道完全关闭,您可以看到两者更清楚:
user ~ $ ./server | cat; echo "Done."
This is the child with pid = 27953 from parent
This is the child with pid = 27955 from parent
Done.
这是我的示例代码,名为 server.c(已删除包含以保持简单)。
int main()
{
for(int i = 0; i < 10; i++) {
fork();
execl("./client", "./client", NULL);
}
if (wait(NULL) == -1)
perror("error with wait");
return 0;
}
这是从上述程序中执行的客户端代码。
int main()
{
printf("This is the child with pid = %d from parent %d", getpid(), getppid());
return 0;
}
现在让我解释一下我认为会发生什么以及我实际得到的输出。
在服务器中,我们进入for循环。在第一次迭代中,我们点击了 fork()。此时有两个进程,即parent和第一个child。现在我们从这两个进程中执行一个名为 "client" 的程序。此客户端代码仅打印一些信息。所以当我 运行 这个服务器程序时,我应该得到两行,对吧?一行来自 parent,另一行来自 child?但是我只打印了一行,在使用 strace 之后我发现只有 parent 正在打印东西,而不是 child。那这是为什么?
是否因为 child 已被执行而无法再收集,因为 parent 已死(这是正确的术语吗?)?如果是这样,child 会怎样?变成丧尸了吧?它会被init收集吗?即便如此,为什么它在像僵尸一样结束之前不打印出那一行?
If stdout is connected to a terminal, it should be line-buffered, so there's no need to flush. And all streams are flushed automatically when they're closed, which happens when the program finishes.
也许你看到两者打印在同一行? 试试这个代码:
#include <stdio.h>
int main(int argc, char **argv) {
printf("This is the child with pid = %d from parent %d\n", getpid(), getppid());
return 0;
}
顺便说一下,您在 printf
中缺少一个 %d
。
你绝对应该得到两条线。
如果不是,可能是因为您 运行 程序的使用方式。 parent 可能会打印并退出,如果您此时停止查看或收听,您将丢失来自 child.
的消息因此,请确保您直接从 shell 终端 运行 脚本,而不是来自 IDE、编辑器或任何其他脚本的脚本的一部分工具.
例如,这里是 ./server; echo "Done"
的输出:
user ~ $ ./server; echo "Done."
This is the child with pid = 27904 from parent
Done.
这使得看起来只有一行输出。但是,在这之后的行中,提示返回并且 child 进程在其后写入了一些信息:
user ~ $ This is the child with pid = 27905 from parent
如果您 运行 以 shell 等待的方式编写脚本,例如添加 | cat
将等待管道完全关闭,您可以看到两者更清楚:
user ~ $ ./server | cat; echo "Done."
This is the child with pid = 27953 from parent
This is the child with pid = 27955 from parent
Done.