使用 fork 时 while(wait(NULL)){} 和 while(wait(NULL) > 0){} 有什么区别
What's the difference between while(wait(NULL)){} and while(wait(NULL) > 0){} when using fork
我有如下一段代码:
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
int main() {
for(int i = 0; i <3; i++){
fork();
}
while(wait(NULL)){}
printf("Text\n");
return 0;
}
当我尝试执行它时,我收到一个 SIGKILL
错误,而不是从 fork 调用中收到 8 条文本消息。但是,如果我改变
while(wait(NULL)){}
到
while(wait(NULL) == 0){}
或
while(wait(NULL) > 0){}
我按预期收到了 8 份“文本”打印件。
为什么程序在第一种情况下不工作? wait(NULL)
循环或 wait(0)
循环不是应该等到所有子进程都执行完吗?
感谢您的帮助!
当你这样做时:
while(wait(NULL)){}
等于:
while(wait(NULL) != 0){}
wait
函数 return 成功时为 child pid,错误时为 -1。所以 return 值永远不会为 0。这会导致无限循环。
这样做:
while(wait(NULL) > 0){}
只要 child returns 就会循环,并在 returned -1 时退出。
几件事...
您正在循环执行 fork
但您 没有 将 parent/child 操作分开。也就是说,both 完成循环并且 both parent 和 child 尝试 wait
完成。
您可能只想在 parent 中执行 wait
。
wait(NULL)
将 suspend/wait 用于 下一个 child 完成(即 不是 所有其中)。这就是为什么你必须循环。
来自 wait
的 return 是刚刚退出的 child 进程的 pid
[> 0]。如果错误,-1 是 returned。如果没有更多 child 个进程等待,wait
将 return -1(errno
设置为 ECHILD
)。
所以,while (wait(NULL) > 0)
是你最好的选择。
添加一些 printf
语句可能有助于您的理解:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int
main()
{
pid_t pid;
setbuf(stdout,NULL);
printf("parent: my pid is %d\n",getpid());
for (int i = 0; i < 3; i++) {
pid = fork();
if (pid != 0) {
printf("%d forked %d\n",getpid(),pid);
}
else {
printf("child: %d\n",getpid());
}
}
while ((pid = wait(NULL)) > 0) {
printf("%d: wait on %d\n",getpid(),pid);
}
printf("Text (from %d)\n",getpid());
return 0;
}
这是输出:
parent: my pid is 469844
469844 forked 469845
child: 469845
469844 forked 469846
child: 469846
469844 forked 469848
469845 forked 469847
child: 469848
469846 forked 469849
Text (from 469848)
469845 forked 469850
child: 469849
child: 469850
Text (from 469849)
Text (from 469850)
child: 469847
469844: wait on 469848
469847 forked 469851
469845: wait on 469850
child: 469851
469846: wait on 469849
Text (from 469846)
Text (from 469851)
469844: wait on 469846
469847: wait on 469851
Text (from 469847)
469845: wait on 469847
Text (from 469845)
469844: wait on 469845
Text (from 469844)
while(wait(NULL) > 0) {}
等待所有子进程完成,当没有子进程剩余时,返回一个 -1
中断 while,因为 -1 > 0
为 false。查看 wait 手册页。在第一种情况下导致无限循环,因为 -1
被评估为 true。
pid_t wait(int *wstatus);
系统调用用于等待调用进程child的状态变化,并获取状态发生变化的child的信息。
wait(&status)
系统调用有两个目的。首先,如果一个child的调用进程
尚未通过调用 exit()
终止,然后 wait()
暂停执行
进程,直到其 children 之一终止。二、终止状态
在 wait()
.
的状态参数中返回 child 的
No when wstatus
is NUll no status information well being stored!
成功时,returns 终止的进程 ID child;出错时返回 -1。
while(wailt(null)>0){
}
这意味着我们正在等待所有 children 在成功条件下终止!出现第一个错误时,我们将退出 while,如果调用进程有更多尚未终止的 children,我们将不会等待它们,稍后终止的 childs 仍处于“僵尸”状态.
while(wailt(null)){
}
这意味着即使在 child 之一的 witing 中发生错误(例如由于选项参数无效或任何其他原因参见文档),我们将继续等待直到最后一个child终止。
我有如下一段代码:
#include<stdio.h>
#include<stdlib.h>
#include<sys/wait.h>
#include<unistd.h>
int main() {
for(int i = 0; i <3; i++){
fork();
}
while(wait(NULL)){}
printf("Text\n");
return 0;
}
当我尝试执行它时,我收到一个 SIGKILL
错误,而不是从 fork 调用中收到 8 条文本消息。但是,如果我改变
while(wait(NULL)){}
到
while(wait(NULL) == 0){}
或
while(wait(NULL) > 0){}
我按预期收到了 8 份“文本”打印件。
为什么程序在第一种情况下不工作? wait(NULL)
循环或 wait(0)
循环不是应该等到所有子进程都执行完吗?
感谢您的帮助!
当你这样做时:
while(wait(NULL)){}
等于:
while(wait(NULL) != 0){}
wait
函数 return 成功时为 child pid,错误时为 -1。所以 return 值永远不会为 0。这会导致无限循环。
这样做:
while(wait(NULL) > 0){}
只要 child returns 就会循环,并在 returned -1 时退出。
几件事...
您正在循环执行 fork
但您 没有 将 parent/child 操作分开。也就是说,both 完成循环并且 both parent 和 child 尝试 wait
完成。
您可能只想在 parent 中执行 wait
。
wait(NULL)
将 suspend/wait 用于 下一个 child 完成(即 不是 所有其中)。这就是为什么你必须循环。
来自 wait
的 return 是刚刚退出的 child 进程的 pid
[> 0]。如果错误,-1 是 returned。如果没有更多 child 个进程等待,wait
将 return -1(errno
设置为 ECHILD
)。
所以,while (wait(NULL) > 0)
是你最好的选择。
添加一些 printf
语句可能有助于您的理解:
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
int
main()
{
pid_t pid;
setbuf(stdout,NULL);
printf("parent: my pid is %d\n",getpid());
for (int i = 0; i < 3; i++) {
pid = fork();
if (pid != 0) {
printf("%d forked %d\n",getpid(),pid);
}
else {
printf("child: %d\n",getpid());
}
}
while ((pid = wait(NULL)) > 0) {
printf("%d: wait on %d\n",getpid(),pid);
}
printf("Text (from %d)\n",getpid());
return 0;
}
这是输出:
parent: my pid is 469844
469844 forked 469845
child: 469845
469844 forked 469846
child: 469846
469844 forked 469848
469845 forked 469847
child: 469848
469846 forked 469849
Text (from 469848)
469845 forked 469850
child: 469849
child: 469850
Text (from 469849)
Text (from 469850)
child: 469847
469844: wait on 469848
469847 forked 469851
469845: wait on 469850
child: 469851
469846: wait on 469849
Text (from 469846)
Text (from 469851)
469844: wait on 469846
469847: wait on 469851
Text (from 469847)
469845: wait on 469847
Text (from 469845)
469844: wait on 469845
Text (from 469844)
while(wait(NULL) > 0) {}
等待所有子进程完成,当没有子进程剩余时,返回一个 -1
中断 while,因为 -1 > 0
为 false。查看 wait 手册页。在第一种情况下导致无限循环,因为 -1
被评估为 true。
pid_t wait(int *wstatus);
系统调用用于等待调用进程child的状态变化,并获取状态发生变化的child的信息。
wait(&status)
系统调用有两个目的。首先,如果一个child的调用进程
尚未通过调用 exit()
终止,然后 wait()
暂停执行
进程,直到其 children 之一终止。二、终止状态
在 wait()
.
No when wstatus
is NUll no status information well being stored!
成功时,returns 终止的进程 ID child;出错时返回 -1。
while(wailt(null)>0){
}
这意味着我们正在等待所有 children 在成功条件下终止!出现第一个错误时,我们将退出 while,如果调用进程有更多尚未终止的 children,我们将不会等待它们,稍后终止的 childs 仍处于“僵尸”状态.
while(wailt(null)){
}
这意味着即使在 child 之一的 witing 中发生错误(例如由于选项参数无效或任何其他原因参见文档),我们将继续等待直到最后一个child终止。