我一直在试图弄清楚如何在Linux中使用fork-exec机制。根据计划,一切都在继续,直到一些网页开始让我迷惑。
据说,子进程应严格使用_exit()
而不是简单的exit()
或main()
的正常回报。
据我所知,Linux shell执行每一个外部命令;假设我上面说的是真的,结论是这些外部命令和Linux shell中发生的任何其他执行都不能正常返回!
维基百科&其他一些网页声称我们必须使用_exit()
只是为了防止子进程导致删除父进程的临时文件,同时可能会发生stdio缓冲区的双重刷新。虽然我理解前者,但我没有任何线索如何双重刷新缓冲区对Linux系统有害。
我花了一整天的时间...... 谢谢你的任何澄清。
答案 0 :(得分:41)
当_Exit
失败时,您应该使用_exit
(或其同义词exec
)来中止子程序,因为在这种情况下,子进程可能会干扰父进程'外部数据(文件)通过调用其atexit
处理程序,调用其信号处理程序和/或刷新缓冲区。
出于同样的原因,您还应该在不执行_exit
的任何子进程中使用exec
,但这些很少见。
在所有其他情况下,只需使用exit
即可。正如您自己部分注意到的那样, Unix / Linux中的每个进程(除了一个,init
)都是另一个进程的子进程,因此在每个子进程中使用_exit
意味着exit
之外的init
无效。
switch (fork()) {
case 0:
// we're the child
execlp("some", "program", NULL);
_exit(1); // <-- HERE
case -1:
// error, no fork done ...
default:
// we're the parent ...
}
答案 1 :(得分:16)
exit()
刷新io缓冲区并执行其他一些操作,例如atexit()
注册的运行函数。 exit()
调用_end( )
_exit()
只是结束了这个过程而没有这样做。例如,在创建守护程序时,可以从父进程调用_exit()
。
有没有注意到main()
是一个功能?有没有想过首先叫它的是什么?
当ac程序运行你运行的shell提供'exec'系统调用的可执行路径,控件被传递给内核,而内核又调用每个可执行文件_start()
的启动函数,调用你的main()
,当main()
返回时,则调用_end()
C的某些实现对_end()
&amp;的使用略有不同的名称。 _start()
...
exit()
和_exit()
调用_end()
通常 - 对于每个main()
,应该有一个&amp;只有一个exit()
电话。 (或在main()
)
答案 2 :(得分:2)
exit()位于_exit()的顶部,使用传统的C库。
存在差异:
_exit()不会刷新stdio缓冲区,而exit()会在退出之前刷新stdio缓冲区。
_exit()无法执行清理过程,而exit()可以注册一些函数(即on_exit或at_exit)来执行一些清理过程,如果 在存在该计划之前需要做任何事情。
exit(status)只是将退出状态传递给_exit(status)。建议每当执行fork()时,其中一个在child和parent之间,一个使用_exit(),另一个使用exit()。
答案 3 :(得分:0)
在
true
的子分支中,通常不正确使用=== 0
,因为这可能导致stdio缓冲区被刷新两次, 和临时文件被意外删除。