如何退出子进程 - _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 exitman _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的主要内容,如果未能解决你的问题,请参考以下文章

abort exit _exit return的区别

Linux进程控制(精讲)

进程控制详解

进程控制详解

进程控制详解

os._exit(), sys.exit(), exit()