我试图在python中创建一个守护进程。我发现了下面的问题,其中有一些很好的资源,我目前正在关注,但我很好奇为什么需要双分叉。我对谷歌进行了研究,发现了大量的资源,这些资源都表明这是必要的,但不知道为什么。

有人提到这是为了防止守护进程获取控制终端。如果没有第二个分叉,它将如何做到这一点?后果是什么?


当前回答

这样也许更容易理解:

第一个fork和setsid将创建一个新的会话(但是进程ID ==会话ID)。 第二个fork确保进程ID !=会话ID。

其他回答

摘自Bad CTK:

在某些类型的Unix上,为了进入守护进程模式,你不得不在启动时执行双叉操作。这是因为单分叉不能保证与控制终端分离。”

查看问题中引用的代码,理由是:

Fork a second child and exit immediately to prevent zombies. This causes the second child process to be orphaned, making the init process responsible for its cleanup. And, since the first child is a session leader without a controlling terminal, it's possible for it to acquire one by opening a terminal in the future (System V- based systems). This second fork guarantees that the child is no longer a session leader, preventing the daemon from ever acquiring a controlling terminal.

因此,这是为了确保守护进程被重新父化到init上(以防启动守护进程的进程是长期存在的),并消除守护进程重新获得控制tty的任何机会。因此,如果这两种情况都不适用,那么一个分叉就足够了。“Unix网络编程- Stevens”在这方面有一个很好的章节。

这样也许更容易理解:

第一个fork和setsid将创建一个新的会话(但是进程ID ==会话ID)。 第二个fork确保进程ID !=会话ID。

关于它的一个像样的讨论似乎在http://www.developerweb.net/forum/showthread.php?t=3025上

引用mlampkin的话:

...将setsid()调用视为做事的“新”方式(与终端分离),而[第二个]fork()调用作为处理SVr4的冗余…

我试图理解这个双叉,无意中发现了这个问题。经过大量研究,我得出了这个结论。希望它能帮助那些有同样问题的人更好地澄清事情。

在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