(请注意,下面我经常使用术语“守护进程或工作者“只是为了表明我不知道该使用哪个词,因为我不知道它们在下面解释的上下文中的确切区别。)
考虑以下场景:
- 我需要编写一个监听某个端口的服务器,它接受该端口上的请求并分叉一个新的守护进程或工作者对于每个传入的请求来处理它们。
- 我需要编写一个服务器来启动一些预先确定的数量守护进程或工人,然后侦听某个端口,最后将该端口上的传入请求分配给当前空闲的端口之一守护进程或工人。这种方法预先创建了预定数量的守护进程或工人只是为了避免在收到大量请求时产生大量请求,这可能是第一种情况的情况。
我正在使用 python 在 linux 中执行此操作。我遇到了两种创建方法守护进程或工作者:
通过使用
multiprocessing.Process
并设置其daemon
到True
。当我尝试这个并观察ps
命令输出中的守护进程或工作人员时,我意识到守护进程或工人没有PPID=1
(initd
linux中的进程),但它们被设置为服务器的PPID
PID(此处)。28822
请注意,这种方法还留下了那些守护进程和工人处于失效状态,它们不会ps
自动从命令输出中删除。我必须明确地杀死他们。$ ps axo pid,ppid,pgid,sess,comm --forest | grep -E 'python| PID' PID PPID PGID SESS COMMAND 28822 25898 28822 25898 | \_ python3 28823 28822 28822 25898 | | \_ python3 <defunct> 28828 28822 28822 25898 | | \_ python3 <defunct> 28831 28822 28822 25898 | | \_ python3 <defunct>
但是,当我使用双分叉时
os.fork()
1,2和处理singnal.SIGCHLD
,它不会留下失效的进程,并正确地将这些守护进程的 PPID 分配为 1。例如,按照ps
命令的输出:$ ps axo pid,ppid,pgid,sess,comm --forest | grep -E 'python| PID' PID PPID PGID SESS COMMAND 43680 43300 43680 43300 | \_ python3 43683 1 43682 43682 python3 43690 1 43689 43689 python3 43699 1 43698 43698 python3
这三个 PID 为 {43683,43690,43699} 的 python 进程是守护进程或工人,然后
PPID=1
一旦完全执行,它们就会从命令输出中消失。
疑虑
PPID=1
我相信由双分叉创建的进程是真正的unix守护进程。另外,请注意多处理文档如下所示:此外,这些不是 Unix 守护进程或服务,它们是正常进程,如果非守护进程退出,它们将被终止(并且不会加入)。
所以,我觉得双分叉创建的进程是真正的Linux守护进程,而多处理库创建的进程只是工作者,即使该库称它们为守护进程。
我这样说对吗?
我想知道哪种方法适合上述场景。我觉得场景1应该用多处理方法更好地实现,而场景2应该用双分叉方法更好地实现。
我这样说对吗?
答案1
从技术上讲,守护进程还需要setsid()
在分叉后调用以启动新会话,成为其领导者,并与控制 tty 分离,但是,是的,您是对的。
实际上,您想在两种情况下同时执行这两种操作。您希望首先进行守护进程,然后守护进程可以派生更多工作人员。