我对UNIX中进程的结束感到困惑。 UNIX中的进程何时终止?我们是否必须写exit(0)
来终止进程?在我看来 - 不,但我无法弄清楚这两段代码之间的区别。
pid_t pid=fork();
if(pid < 0)
{
perror("Fork error\n");
return 1;
}
else if (pid==0) /* child */
{
//Do some operations here
}
else
{
wait(NULL);
//Do some operations
}
和
pid_t pid=fork();
if(pid < 0)
{
perror("Fork error\n");
return 1;
}
else if (pid==0) /* child */
{
//Do some operations here
exit(0);
}
else
{
wait(NULL);
//Do some operations here
}
可能我们只需exit(0)
wait()
函数。在这种情况下,如果我们wait()
未完成exit(0)
会发生什么
之前?
答案 0 :(得分:2)
请参阅exit()
:
终止流程
重要的是,无论过程是否
_exit()
(可能间接通过exit()
)或由于信号或其他原因而终止,都会发生所述过程终止的后果。
[...]
根据ISO C标准的要求,使用
main()
的返回与使用返回值调用exit()
具有相同的行为(除语言范围问题之外)。到达main()
函数的末尾与调用exit(0)
具有相同的行为。
另见wait()
。正常终止:
如果由于子进程的状态可用而返回
wait()
或waitpid()
,则这些函数将返回等于子进程的进程ID的值。[...]
存储在stat_loc
所指向的位置的值应为0
当且仅当返回的状态来自已终止的子进程,该进程以下列方式之一终止:
- 该流程从
0
返回main()
。- 此过程名为
_exit()
或exit()
,状态参数为0
。- 该进程已终止,因为进程中的最后一个线程已终止。
指定的终止原因列表:
WIFEXITED(stat_val)
如果正常终止的子进程返回状态,则计算为非零值。
WIFSIGNALED(stat_val)
如果由于收到未捕获的信号而终止的子进程返回状态,则评估为非零值(参见
<signal.h>
)。
及各自的状态信息:
WEXITSTATUS(stat_val)
如果
WIFEXITED(stat_val)
的值不为零,则此宏计算为子进程传递给_exit()
或exit()
的状态参数的低8位,或者子进程从main()
返回的值。
WTERMSIG(stat_val)
如果
WIFSIGNALED(stat_val)
的值不为零,则此宏将评估导致子进程终止的信号编号。
总而言之,POSIX提到了如何终止进程的两种方式:
exit()
,_exit()
或从main()
返回,或者进程的最后一个线程终止; 如果您需要阻止所有线程在main()
返回时终止,请参阅"Is it OK to call pthread_exit from main?"。
exit()
在这种情况下,如果我们在没有
wait()
之前完成exit(0)
会发生什么?
fork()
重复当前进程,父进程和子进程在fork()
返回时从同一点继续执行。
考虑以下示例:
int main() {
if (fork() == 0) { /* child */
foo();
}
else { /* parent */
wait(NULL);
}
bar(); /* called in parent in child */
return 0; /* or exit(0) */
}
在此示例中,子项不会在其exit()
分支中调用if
,因此在调用foo()
后,它会调用bar()
而不是从main()
返回子进程终止。换句话说,孩子和家长都在这里打电话bar()
。
通常这不是你想要的,而是你写的:
int main() {
if (fork() == 0) { /* child */
foo();
exit(0);
}
else { /* parent */
wait(NULL);
}
bar(); /* called only in parent */
return 0;
}
在这种情况下,孩子在致电foo()
后立即退出,以便bar()
未在孩子中召唤。