【问题标题】:Why fork() twice while daemonizing? [duplicate]为什么在守护进程时 fork() 两次? [复制]
【发布时间】:2015-10-07 17:29:08
【问题描述】:

我想知道为什么人们会打电话给fork() 两次,以及为什么第一次打电话是在之前setsid()

是的,如果调用者已经是进程组负责人,则不会创建新会话。但是,如果我只是不让(祖)父母成为流程组负责人怎么办?谁会为我做(不问我)? (好吧,也许是 1llum1n4t1、Sc13nt0l0gy、美国国家安全局……;)

是的,第一个孩子应该立即退出,而不是创建僵尸进程。但是(祖)父母不能在分叉后退出吗?或者一两个fprintf(stderr,...write(2,... 调用(如“成功启动的守护进程xy”)会是一个大问题吗? (我不能用另一种方式来阻止僵尸吗?)

总而言之,这个 double-fork()-"magic" 真的是必需吗(不要惹麻烦)? 还是只是传统或所谓的“最佳实践”(如避免goto)? 或者它只是保证守护进程可以在“历史”(当然我的意思是“在生产环境中使用太旧”)平台上工作,比如 SVr4、BSD 3、RHEL 2 或一些糟糕的 32 位嵌入式平台?

【问题讨论】:

标签: c unix fork posix daemon


【解决方案1】:

第一次调用fork(2) 确保进程不是组长,这样该进程就有可能创建新会话并成为会话组长。第一个fork(2) 有其他原因:如果守护进程是作为 shell 命令启动的,则进程 fork 和父退出会使 shell 返回到其提示符并等待更多命令。

第二个fork(2) 用于确保新进程不是会话领导者,因此它不能(意外)分配控制终端,因为守护进程不应该有控制终端。关于第二次分叉,这里引用了 UNIX 环境中的高级编程,第 13 章(守护进程):

在基于 System V 的系统下,有人建议再次调用 fork 此时,终止父进程,并继续守护进程 孩子。这保证了守护进程不是会话领导者, 这可以防止它在 系统 V 规则。或者,为了避免获得控制权 终端,请务必在打开终端时指定 O_NOCTTY 设备。

该书的第 13.3 节描述了在守护进程时使用的更多规则和模式,如果可以的话,值得花时间阅读。

【讨论】:

  • 不能确定进程不是组长吗?
  • @AlexanderAleksandrovičKlimov 一般来说,你不知道。例如,如果进程作为 shell 命令启动,并且 shell 支持后台作业,shell 可能在 exec()ing 守护进程之前创建了一个新进程组,从而使守护进程成为进程组的领导者。这取决于 shell 实现,但 bash 正是这样做的,进程组负责人是正在执行的进程。所以,可以肯定的是,你真的需要至少分叉一次。
猜你喜欢
  • 2017-12-09
  • 2012-06-11
  • 2015-03-16
  • 2011-05-10
  • 1970-01-01
  • 2013-10-25
  • 1970-01-01
  • 2017-07-30
  • 2010-12-29
相关资源
最近更新 更多