我正在尝试编写一个程序,该程序有一个父进程在 while 循环中创建多个子进程。为了进行测试,我开始尝试仅创建 4 个进程(1 个父进程及其 3 个子进程)。但看起来孩子们正在执行他们创建的行之上的代码,即使他们没有递归(据我所知)可以返回到该行。
这是我现在所拥有的:
int main() {
time_t start;
time_t end;
int i = 0;
pid_t pid;
start = time(NULL);
printf("Αρχική τιμή δευτερολέπτων %d\n", start);
pid = fork();
printf("%d ", pid);
while (i < 2) {
if (pid > 0) {
fork();
wait();
i++;
}
}
printf("check ");
printf("%d", pid);
if (pid > 0) {
end = time(NULL);
printf("%d\n", end - start);
}
return 0;
}
我的输出是:
Αρχική τιμή δευτερολέπτων 1547394155
29338 check 29338 0
29338 check 29338 0
29338 check 29338 0
29338 check 29338 0
所以看起来好像printf ("%d ", pid)
运行了 4 次,尽管当时应该只运行 2 个进程。
答案1
这与“为什么使用 fork() 的程序有时会多次打印其输出?”。
当您执行此操作时,输出缓冲区不会立即刷新,printf("%d ", pid)
因为字符串不是以换行符结尾,并且您没有调用fflush(stdout)
.这意味着未刷新的缓冲区由子进程继承,并且当缓冲区最终被最后一次printf()
调用(输出换行符)或在程序执行结束时刷新时,您会多次输出原始父进程的 PID 。
fflush(stdout)
在该调用之后直接插入printf()
(以及包含适当的标头并wait()
正确调用)将导致类似的结果
Αρχική τιμή δευτερολέπτων 1547400480
79301 0 check 793010
check 793010
check 793010
check 793010
另请注意,您将得到一个在循环中无限循环的进程while
(第一个子进程,其pid
值为零)。
答案2
首先,请注意,wait()
不带参数的调用是不可接受的;它不等于wait(NULL)
;EFAULT
当尝试存储状态时,它要么会失败,要么会浪费内存。
我将尝试解释您的代码中发生的情况,而不运行它(我也遇到过叉子炸弹,非常感谢)。
pid = fork(); printf("%d ", pid); while (i < 2) { if (pid > 0) { fork(); wait(); i++; } }
在第一个之后fork
,您将有 2 个进程;在子进程中将pid
等于0
,因此子进程将继续无限循环运行,因为i++
只有当 时才会执行pid > 0
。
从那时起,pid > 0
在父级和由循环内部的第二个分支创建的所有子级中,该值都为 true,因为该pid
变量永远不会在任何地方再次更新。
所以fork()
从循环内部将创建(1)第一次在父母中奔跑的孩子,(2)父级中第二次运行的子级,并且(3)在循环的第一次运行中创建的子级中,第二次运行时还有另一个子级。
这使得 3 + 1 = 4 个进程,它们都将运行到函数的末尾main()
,并且pid > 0
所有进程都为 true,因此它们都会打印出整个内容(包括循环printf("%d ", ...
之前添加的未刷新的数据) while
)。
作为旁注,您应该dprintf(1 or 2, ...)
在需要调试时随时使用printf()
;这将消除任何虚假的缓冲(以及对其发生的虚假恐惧);dprintf()
现在也属于标准。