为什么守护进程要分叉?
我知道一些(全部?)守护进程在启动时会分叉。我的印象是,这是以权限较低的用户身份运行子进程,特别是当守护进程类似于 HTTP 服务器时。
为什么这是必要的呢?进程不能在不分叉子进程的情况下启动并放弃其权限吗?分叉是“强制”的,还是有其他特殊原因(除了运行多个子工作进程之外)?
我对此很陌生,非常感谢我能得到的所有帮助。
I'm aware some (all?) daemons fork when they're being started. I'm under the impression this is to run the child processes as less privileged users, especially if the daemon is something like a HTTP server.
Why is this necessary though? Couldn't a process start up and drop its privileges without forking a child process? Is it "mandatory" for forking, or is there some other special reason (other than for running multiple child worker processes)?
I'm new to this and would appreciate all the help I can get.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我认为守护进程分叉有几个原因:
一个原因是将进程与启动它的任何 shell 分离。有些 shell(例如 Bash)会在退出时杀死儿童,除非采取特殊的、特定于 shell 的预防措施。分叉是避免这种情况的通用方法。
另一个原因是报告守护进程已成功启动。
假设它没有分叉。您如何知道守护进程已成功启动?您不能只读取和解析守护程序输出,因为守护程序管理程序应该以通用方式执行此操作。所以唯一的办法就是获取程序的返回码。
事实上,如果守护进程无法启动(例如,它找不到配置文件),您会立即知道。但是,嘿,如果一个守护进程已成功启动,它可能永远不会返回!因此,您的守护进程管理器无法知道守护进程是否仍在尝试启动,或者已经启动并且正在工作。 Fork 可以解决问题,如果 fork 运行良好,fork 程序将返回成功。
至于权限,在
execve
之后删除它们比在execve
之前删除它们要安全得多。这是 fork 方便的另一个原因。I think daemons fork for several reasons:
One reason is to detach process from any shell that starts it. Some shells (Bash, for instance) kill children upon exit, unless special, shell-specific precautions are made. Forking is a generic way to evade this.
Another reason is to report that the daemon was successfully started.
Assume it doesn't fork. How would you know that the daemon has been started successfully? You can't just read and parse daemon output, because daemon management programs should do it in a generic way. So the only way is to get return code of the program.
Indeed, if a daemon failed to start (for example, it couldn't find config file), you would know that immediately. But hey, if a daemon has been started successfully, it may never return! So your daemon manager can't know whether daemon is still trying to start, or has been started, and is working. Fork would solve the problem, and the forking program would return success if a fork worked well.
As for privileges, dropping them after
execve
is much less secure than doing so beforeexecve
. Here's another reason why fork is handy.守护进程必须分叉两次,因为它们必须独立于其他进程,也就是说,没有办法杀死守护进程来杀死另一个进程,并且必须在后台运行,不附加到终端。
启动时,守护进程分叉并且父进程死亡。这使得分叉进程成为 init 的子进程,因此基本上它独立于其他进程。
在第二个分支上,子进程不再是进程领导者,并且与终端分离。
其他好的实践也可能适用,阅读简单守护进程的源代码可能会很有洞察力。
Daemons must fork two times because they must be indipendent of other processes, that is there's no way to kill the daemon killing another process, and must be running in the background, that is not attached to a terminal.
On startup the daemon forks and the parent dies. This makes the forked process a child of
init
, so basically it's indipendent from other processes.On the second fork the child is no more a process leader, and is detached from the terminal.
Others good practices may apply, reading the source code of a simple daemon may be insightful.
我的印象是这样做是为了使守护进程完全不附加到任何其他进程(如 shell 或类似进程)。通过分叉并退出父进程,孤立进程将被系统 init 进程“采用”。
I was under the impression that this was done to keep the daemon completely unattached to any other processes (like a shell or similar). By forking and exiting the parent process the Orphaned process will be "adopted" by the system init process.
为了支持 daramarak 所说的内容,摘自维基百科文章:
基本上,该进程需要与其他进程和终端等解除关联。
To back up what daramarak said, from Wikipedia's article:
Basically the process needs to disassociate from other processes and from terminals and such.