如何解决为什么这段代码有时只调用一次printf而不是两次?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main() {
pid_t pid;
pid = fork();
fork();
if (pid > 0) {
printf("Hello,World!\n");
}
return EXIT_SUCCESS;
}
运行上面的代码时,它将输出以下输出,这是预期的:
Hello,World!
Hello,World!
但是有时我在再次执行代码后得到以下输出:
Hello,World!
为什么代码有时只将消息打印一次?
仅当该程序在IDE的终端中或在onlinegdb之类的环境中运行时,才会发生这种仅的情况。
从交互式外壳启动程序时,总是这两个预期行都是“ Hello,World!”。被打印出来。
解决方法
TL;在分叉孩子与退出孩子之间的DR竞争状况
取决于子进程还是父进程在(第二次)派生之后首先运行,父进程可能会打印消息并退出,IDE可能会检测到它已经退出并在子进程获取之前关闭所有组件运行并打印它的消息。
从bash运行时不会发生这种情况,因为即使这样,孩子仍然可以输出其消息。从理论上讲,这可能会在shell打印下一个提示符后发生,但这似乎极不可能。
要记住的重要一点是,您的程序始终由某种程序(shell或IDE等)运行,并且某些程序将等待其退出,但不会等待您可能会分叉的任何子进程。因此,如果您要确保孩子们完整,就需要等他们退出后。
,观察到的行为是由外壳在看到原始进程终止后终止而引起的。
线索是vxs8122的观察
当我直接在OS终端上执行代码时,我不再遇到该问题
从交互式外壳程序启动进程时,原始进程终止后,交互式外壳程序将继续运行。其他三个分叉的进程可以正常运行,因此其中两个打印“ Hello world”。
由IDE启动进程时,通常IDE将创建一个Shell实例来执行该进程(或者IDE本身执行诸如Shell之类的等效操作)。
shell将子流程放入新的流程组中,并使其成为流程组负责人。分叉的进程继承了进程组。 Shell等待其原始子项终止,然后终止自身。在终止之前,shell将SIGHUP发送到进程组,以确保没有孤立的进程在周围徘徊。该信号可能会到达最多三个分叉的进程中的任何一个(如果尚未到此终止的话)。
SIGHUP未被示例程序捕获,它的标准操作是终止该过程。因此,“打印”过程可能会被终止的外壳提前终止。在这种情况下,不会打印输出。
如果您在main()
的早期忽略了程序中的SIGHUP,则总是打印两行。
signal(SIGHUP,SIG_IGN);
您还可以尝试使用此版本,以验证子进程是否收到了SIGHUP,具体取决于您的运行环境。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
void handler(int sig)
{
puts("got SIGHUP");
exit(EXIT_SUCCESS);
}
int main() {
signal(SIGHUP,handler);
pid_t pid;
pid = fork();
fork();
if (pid > 0) {
printf("Hello,World!\n");
}
return EXIT_SUCCESS;
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。