最近在看后台守护进程,对于其中fork两次产生了疑问,记录一下。
这篇文章写的挺好的:
linux环境下使用daemon函数实现守护进程_linux daemon函数-优快云博客
结论这里贴一下
以下是调用两次 fork() 函数的工作原理:
调用第一次 fork() 函数:创建子进程1。父进程退出,子进程1成为孤儿进程,也就是没有父进程的进程。此时,子进程1仍然与原来的控制终端相关联。
子进程1调用 setsid() 函数创建一个新的会话,并成为新会话的领头进程和新进程组的组长进程。由于孤儿进程已经成为新会话的领头进程,因此它无法再重新关联到终端。此时,子进程1仍然是当前进程组的组长进程,并且与新的控制终端相关联。
调用第二次 fork() 函数:创建子进程2。由于子进程1是新会话的领头进程,因此子进程2不再与任何控制终端相关联。此时,子进程2成为孤儿进程,并与新会话和新进程组分离。
子进程2关闭不需要的文件描述符,改变工作目录和文件掩码,最后运行守护进程。
总结:第一次fork为了将进程变为后台进程,第二次fork脱离终端关联
文章中对一次还是两次fork有争议,于是找ai问了一下
以下是DS的结果
-
单次
fork的场景- 目的:仅需脱离父进程控制,不涉及终端防护。
- 流程:
- 调用
fork()创建子进程后,父进程退出,子进程通过setsid()成为新会话首进程。 - 适用系统:某些现代系统(如 CentOS 7.6)的
setsid()已能完全隔离终端,无需二次fork。
- 调用
-
两次
fork的场景- 目的:彻底避免终端关联风险(如 SIGHUP 信号干扰)。
- 流程:
- 第一次
fork:父进程退出,子进程调用setsid()脱离原会话组。 - 第二次
fork:确保子进程非会话首进程(防止重新获取终端控制权)。
- 第一次
- 必要性:传统 System V 系统中,会话首进程可能意外关联终端。
tips:
- System V 限制:早期 Unix 系统中,会话首进程可能通过
open("/dev/tty")重新绑定终端,二次fork是标准做法。- Linux 优化:现代内核(如 ≥3.10)的
setsid()已默认阻断终端关联,二次fork逐渐成为可选。- 实践建议:若需跨平台兼容性,建议保留二次
fork;若仅针对现代 Linux,单次fork+setsid()足够。
700

被折叠的 条评论
为什么被折叠?



