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

时间:2012-01-08 12:44:05

标签: 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);

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

2 个答案:

答案 0 :(得分:41)

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

但请注意,使用TIOCNOTTY ioctl与终端取消关联的方式已基本上已过时。您应该使用setsid()代替。

守护程序离开其原始进程组的原因是不接收发送到该组的信号。请注意,setsid()也会将您的流程置于其自己的流程组中。

答案 1 :(得分:13)

另一个答案是清楚的,技术上是正确的(所以我相应地投了赞成票)。

另一个答案是:“不,不要编写守护自己的代码。”

而是使用过程监督框架(如daemontoolsrunitlaunchd)来处理此问题。

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

但是,大多数或所有这些进程属性都是通过exec()继承的,这意味着服务器进程通常可以“生成”所需的进程组,工作目录,root等。几乎没有必要尽管你经常仍然需要自己管理特权操作和特权撤销,但你自己也要做好一切。

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