传统Linux fork-exec中使用_exit()和exit()之间有什么区别?
我一直在试图弄清楚在Linux内部如何使用fork-exec机制。 一切都按照计划进行,直到一些网页开始混淆我。
据说一个subprocess应该严格使用_exit()
而不是简单的exit()
或者main()
的正常返回。
据我所知,Linuxshellfork-execs每一个外部命令; 假设我上面说的是真的,结论是这些外部命令和Linux shell内部发生的任何其他执行都不能正常返回!
维基百科和其他一些网页声称,我们必须使用_exit()
只是为了防止subprocess删除父的临时文件,而可能的双重刷新stdio缓冲区可能会发生。 虽然我理解前者,但是我没有线索,双缓冲区的刷新对Linux系统是有害的。
我花了整整一天的时间…感谢您的任何澄清。
当exec
失败时,应该使用_exit
(或其同义词_Exit
)来中止exec
,因为在这种情况下,subprocess可能通过调用它的atexit
处理程序来干扰父进程的外部数据(文件),调用其信号处理程序,和/或冲洗缓冲区。
出于同样的原因,你也应该在任何不执行exec
subprocess中使用_exit
,但是这很less见。
在其他所有情况下,只需使用exit
。 正如你自己部分注意到的那样,Unix / Linux中的每个进程(除了init
)都是另一个进程的subprocess,所以在每个subprocess中使用_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 ... }
exit()
刷新io缓冲区,并执行一些其他的事情,如由atexit()
注册的运行函数。 exit()
调用_end( )
_exit()
仅仅是结束了这个过程。 例如,在创build守护进程时,可以从父进程调用_exit()
。
有没有注意到main()
是一个函数? 有没有想过是什么叫它呢? 当ac程序运行你正在运行的shell时,提供了'exec'系统调用的可执行path,控制权被传递给内核,内核依次调用每个可执行文件_start()
的启动函数,调用main()
main()
返回它然后调用_end()
C的一些实现使用_end()
&_ _start()
稍微不同的名称…
exit()
和_exit()
调用_end()
通常 – 对于每个main()
应该只有一个exit()
调用。 (或者在main()
的末尾返回)
exit()位于_exit()的顶部,使用传统的C库。
有差异:
-
当exit()在退出之前刷新stdio缓冲区时,_exit()不会刷新stdio缓冲区。
-
_exit()不能执行清理过程,而exit()可以用某个函数(例如,on_exit或at_exit)注册,如果在程序存在之前需要任何东西,就执行一些清理过程。
退出(状态)只是将退出状态传递给_exit(状态)。 build议每当执行fork(),其中一个父子之间,一个使用_exit()和另一个使用exit()。