Linux:fork两次和daemon(ise)之间的区别

3

我正在尝试编写一个基本的多进程TCP服务器,每个新的accept()都会fork一个进程。

我不需要父进程等待子进程。我找到了两种解决方案-双重分叉和守护程序化。

  1. 这两者有什么区别?
  2. 在这种情况下哪种更合适?
  3. 选择其中一种的时候应该考虑哪些因素?

2
你读过 daemon(3) 吗?你知道 setsid(2) 吗? - Basile Starynkevitch
3
我不认为这两个都是好的设计。将子进程列表保存在主进程中,定期地对它们进行回收(当然要非阻塞)有什么问题吗?守护进程化对于将主服务进程与启动它的终端分离,使其可以在后台“永远”运行非常有用。 - 5gon12eder
我阅读了 man 手册,但仍不清楚如何使用。 - Zaxter
@5gon12eder...从设计角度来看,将服务器本身设为守护进程,并以非阻塞方式定期清理其分叉子进程是否更好(正如您所建议的)? - Zaxter
1
@user3490458 是的,那可能是更好的设计。 - 5gon12eder
2个回答

3

有一个微妙的区别。

双重派生:中间子进程已经退出并由父进程等待后,它就不会成为僵尸进程。孙子进程也不会成为僵尸进程,因为它的父进程(中间子进程)已经退出了,所以孙子进程变成了孤儿进程。孤儿进程(孙子进程)会被init接管,并在其退出时由系统负责清理。这样,父进程就无需等待收集来自子进程的退出状态信号,并且父进程可以忙于做其他工作。这也使得子进程可以长时间运行,从而不需要短时间父进程等待。

守护进程:适用于希望脱离控制终端并作为系统守护程序在后台运行的程序。没有控制终端。

选择哪种方法取决于手头的要求/场景。


2
您确实需要父进程最终等待每个子进程(使用wait()),否则子进程将一直挂起,直到父进程退出。这是一种资源泄漏的形式。
通过两次fork,中间进程在fork后立即退出,允许原始进程立即收集子进程(通过wait()),并使孙子进程成为孤儿,由系统负责清理。这是避免累积僵尸进程的一种方法。孙子进程保留在与原始进程相同的进程组(因此与相同的会话)中。
守护进程服务于一个稍微不同的目的。它将结果(子)进程放入一个新会话(和新进程组),没有控制终端。可以通过一次fork,在父进程立即调用_exit()并且子进程调用setsid()来实现相同的效果。
系统服务守护进程化以逃离启动它的会话,以便在该会话结束时不被关闭。这与多进程几乎无关,但与进程管理有很大关系。进程双重fork避免了(孙)子进程的进程管理职责;这既涉及多进程,也涉及进程管理方面。
另请注意,双重fork不仅传递了进程管理职责,还放弃了进程管理能力。这是否是一个好的权衡取决于具体情况。

感谢您的深入回答。 - Zaxter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接