如何退出子进程 - _exit() 与 exit
Posted
技术标签:
【中文标题】如何退出子进程 - _exit() 与 exit【英文标题】:how to exit a child process - _exit() vs. exit 【发布时间】:2011-01-20 17:46:12 【问题描述】:考虑一下这段代码sn-p:
pid_t cpid = fork();
if (cpid == -1)
perror("fork");
exit(EXIT_FAILURE);
if (cpid == 0) // in child
execvp(argv[1], argv + 1);
perror("execvp");
_exit(EXIT_FAILURE);
// in parent
如果 execvp 返回,我应该如何退出子进程?我应该使用 exit() 还是 _exit()?
【问题讨论】:
【参考方案1】:如果成功,execvp 将退出子进程,因此您不必退出。
在执行失败时,我只是在孩子中使用exit(EXIT_FAILURE);
。
编辑:经过一番研究,我发现:http://www.unixguide.net/unix/programming/1.1.3.shtml
所以看起来最好在 fork 孩子中使用_exit()
,特别是当你在 C++ 中时:p
谢谢你的问题,我学到了一些东西:D
【讨论】:
【参考方案2】:这取决于您想要的行为:man -s 3 exit
和 man _exit
以获取有关您系统的更多详细信息。一般来说,我相信 _exit 不会运行在 atexit() 注册的函数,而 exit 会运行(这些函数最好不要调用 exit - 否则你会得到递归)。
一般来说,我更喜欢 exit 而不是 _exit,除了在 atexit 注册的函数中,如果需要,我会调用 _exit。
【讨论】:
【参考方案3】:您绝对应该使用_Exit()
。 exit()
调用您使用atexit()
添加的函数并删除使用tmpfile()
创建的文件。由于父进程确实希望在它存在时完成这些事情,因此您应该调用_Exit()
,它不会执行这些操作。
注意_Exit()
带有大写字母E。_exit(2)
可能不是您想直接调用的。 exit(3)
和 _Exit(3)
会为你打电话。如果你没有_Exit(3)
,那么是的,_exit()
就是你想要的。
【讨论】:
+1 您希望失败的子进程安静地退出,就好像它从未创建过一样。 好吧,因为旧的 C 标准允许链接器解析不区分大小写的 _Exit() 不能成为标准库函数,因为它会与旧的 _exit() 冲突。对不起。 相反。 _Exit(3) 是标准 C 库 (ISO C99)。 _exit(2) 是 POSIX.1 系统调用,而不是 C 标准。 调用_Exit
后是否关闭文件等打开的资源是实现定义的。您可能不希望这种行为(关于未刷新的流)。我见过的所有手册页都说_exit
不会刷新流,因此如果文件在分叉发生时具有未刷新的内容会更安全。 _exit
不是标准 C 的事实是有争议的,因为 fork
也是 Unix 特定的。 C 标准委员会可能有特殊原因引入_Exit
,但Unix 程序员完全没有理由将_exit
更改为_Exit
。 @VariableLengthCoder【参考方案4】:
fork() 的子进程应该总是调用 _exit()。
调用 exit() 是一种很好的方法,可以将挂起的 stdio 缓冲区刷新两次。
【讨论】:
exec 不会返回,除非您调用 _exit 出错。【参考方案5】:exit()
是 ANSI-C 函数,因此它独立于操作系统。它关闭所有 ANSI-C 标准函数。
_exit()
被exit()
调用以关闭与操作系统相关的功能,因为exit()
不知道它们。(exit
与操作系统无关)
【讨论】:
“_exit() 是一个 Linux 内核函数”不正确,见pubs.opengroup.org/onlinepubs/9699919799/functions/_Exit.html 你说得对,但我其余的评论都是正确的。参见:David Curry 的 Unix Systems Programming,第 291 页。以上是关于如何退出子进程 - _exit() 与 exit的主要内容,如果未能解决你的问题,请参考以下文章