据我了解,fork 两次是为了避免产生僵尸进程。第一次 fork 产生的子进程 exit 之后,第二次 fork 的子进程被 init 进程收养,从而避免了使得 grandchild 称为僵尸进程。
有一点不明,如果这样,那 fork 一次不就行了吗?父进程 fork 一次,然后父进程直接退出,那子进程不是直接被 init 收养?
为什么非要 fork 两次呢?
1
iwong0exv2 2019-07-03 14:33:56 +08:00
因为大多数时候父进程不能退啊
|
2
v2byy OP @iwong0exv2 如果是这样的话,那明白了,多谢。
|
3
raysonx 2019-07-03 14:57:52 +08:00 4
> 父进程 fork 一次,然后父进程直接退出,那子进程不是直接被 init 收养?
这句话是正确的,只要父进程退出,子进程的父进程就会变成 init。 Fork 二次的目的是为了保证守护进程从当前的 controlling terminal 上 detach,并且不会重新获得 controlling terminal。 原因是,当你在子进程执行一次 setsid 的时候,这个进程会被分配一个新的 session,于是这个进程得以从当前的 controlling terminal 上脱离。但是这个进程作为新 session 的第一个进程,会成为 session lead,它可以重新获取一个 controlling terminal。为了杜绝这种可能,再 fork 一次后,孙进程就不是 session lead 了,它不能重新获取 controlling terminal。 |
4
neoblackcap 2019-07-03 15:10:26 +08:00
@raysonx 的说法是正确的,这个原理 APUE 有讲解。当然现在创建守护进程也有其他的方法,比如 daemon(),不过好像兼容性不是那么好,所以还是 fork 2 次为主。
|
5
Hardrain 2019-07-03 23:49:46 +08:00 via Android
deamonize 时候记得 fork()两次后还要 setsid()吧
得让被 init"收养"的 orphaned process 有自己的 session。 |