为什么在编写linux守护进程时必须从tty中分离出来?

Ori*_*ood 24 c linux terminal daemon

当我尝试使用C在linux下编写一个守护进程时,我被告知我应该在fork代码块之后添加以下代码:

/* Preparations */
...

/* Fork a new process */
pid_t cpid = fork();
if (cpid == -1){perror("fork");exit(1);}
if (cpid > 0){exit(0);}

/* WHY detach from tty ? */
int fd = open("/dev/tty", O_RDWR);
ioctl(fd, TIOCNOTTY, NULL);

/* Why set PGID as current PID ? */
setpgid(getpid(), 0);
Run Code Online (Sandbox Code Playgroud)

我的问题是:是否有必要进行上述操作?

Ada*_*man 41

您必须取消与守护进程的关联,以避免发送与终端操作相关的信号(如终端会话结束时的SIGHUP以及可能的SIGTTIN和SIGTTOU).

但请注意,使用TIOCNOTTY与终端解除关联的方式ioctl基本上已过时.你应该使用setsid().

守护程序离开其原始进程组的原因是不接收发送到该组的信号.请注意,setsid()您还将进程放在其自己的进程组中.


pil*_*row 14

另一个答案是明确的,技术上是正确的(所以我相应地投了票).

另一个答案是: "不,不要编写守护自己的代码."

而是使用一个过程监督框架(如daemontoolsrunitlaunchd)来处理这个问题.

传统的UNIX服务器是自我守护的,因此可以解决许多问题:当前工作目录,进程组和会话独立性,信号掩码和处置,文件系统root,特权,umask,打开文件描述符等.

但是,大多数或所有这些进程属性都是在一个进程中继承的exec(),这意味着服务器进程通常可以"生成"所需的进程组,工作目录,根目录等.尽管你们需要自己做所有事情. ll通常仍然需要自己管理特权操作和特权撤销.

(实际上,我认为编写自我守护程序存在长期风险.锅炉板"后台"程序被复制和粘贴并匆忙移植和扩展,程序员花时间在辅助代码上而不是程序的主要目的上. )