我试图在python中创建一个守护进程。我发现了下面的问题,其中有一些很好的资源,我目前正在关注,但我很好奇为什么需要双分叉。我对谷歌进行了研究,发现了大量的资源,这些资源都表明这是必要的,但不知道为什么。
有人提到这是为了防止守护进程获取控制终端。如果没有第二个分叉,它将如何做到这一点?后果是什么?
我试图在python中创建一个守护进程。我发现了下面的问题,其中有一些很好的资源,我目前正在关注,但我很好奇为什么需要双分叉。我对谷歌进行了研究,发现了大量的资源,这些资源都表明这是必要的,但不知道为什么。
有人提到这是为了防止守护进程获取控制终端。如果没有第二个分叉,它将如何做到这一点?后果是什么?
当前回答
根据Stephens和Rago的“Unix环境中的高级编程”,第二个fork更多的是一个建议,它是为了保证守护进程不会在基于System v的系统上获得控制终端。
其他回答
摘自Bad CTK:
在某些类型的Unix上,为了进入守护进程模式,你不得不在启动时执行双叉操作。这是因为单分叉不能保证与控制终端分离。”
如果daemon()调用成功,则有父调用_exit()。最初的动机可能是让父母在孩子守护的时候做一些额外的工作。
这也可能是基于一种错误的信念,认为这是必要的,以确保守护进程没有父进程,并被重新父化给init——但在单分叉的情况下,一旦父进程死亡,无论如何都会发生这种情况。
所以我认为这一切最终都归结为传统——只要父母在短时间内死亡,一个分叉就足够了。
一个原因是父进程可以立即为子进程wait_pid(),然后忘记它。当孙子孙女死亡时,它的父节点是init,它将wait()等待它——并将它从僵尸状态中取出。
结果是,父进程不需要知道被分叉的子进程,这也使得从库等中分叉长时间运行的进程成为可能。
这样也许更容易理解:
第一个fork和setsid将创建一个新的会话(但是进程ID ==会话ID)。 第二个fork确保进程ID !=会话ID。
我试图理解这个双叉,无意中发现了这个问题。经过大量研究,我得出了这个结论。希望它能帮助那些有同样问题的人更好地澄清事情。
在Unix中,每个进程都属于一个组,而这个组又属于一个会话。这是层次结构……
会话(SID)→进程组(PGID)→进程(PID)
进程组中的第一个进程成为进程组组长,会话中的第一个进程成为会话组长。每个会话都可以有一个与之关联的TTY。只有会话领导者才能控制TTY。为了使进程真正被守护(在后台运行),我们应该确保会话领导者被杀死,这样会话就不可能控制TTY。
我在我的Ubuntu上运行了Sander Marechal的python示例守护程序。以下是结果和我的评论。
1. `Parent` = PID: 28084, PGID: 28084, SID: 28046
2. `Fork#1` = PID: 28085, PGID: 28084, SID: 28046
3. `Decouple#1`= PID: 28085, PGID: 28085, SID: 28085
4. `Fork#2` = PID: 28086, PGID: 28085, SID: 28085
请注意,该进程是在脱钩#1之后的会话领导者,因为它是PID = SID。它仍然可以控制TTY。
注意,Fork#2不再是会话领导PID != SID。这个过程永远不能控制TTY。真正的监控。
我个人认为术语fork-twice令人困惑。一个更好的习语可能是fork- decoupling -fork。
其他感兴趣的链接:
Unix进程- http://www.win.tue.nl/~aeb/linux/lk/lk-10.html