我正在读一本关于 Unix 系统编程的书。书中有一个创建守护进程的函数。
部分代码对我来说不是很清楚,特别是以下内容:
struct sigaction sa;
....
/* *Become a session leader to lose controlling TTY. */
if ((pid = fork()) < 0)
{
err_quit("%s: can’t fork", cmd);
}
else if (pid != 0) /* parent */
{
exit(0); //the parent will exit
}
setsid();
/* *Ensure future opens won’t allocate controlling TTYs. */
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
{
err_quit("%s: can’t ignore SIGHUP", cmd);
}
在哪里
SIGHUP
如果终端接口检测到断开连接,则发送到与控制终端关联的控制进程(会话领导者)的信号。
所以基本上父进程调用fork
然后退出。这样我们就可以保证孩子不是组长。孩子成为与setsid
.
我不明白何时SIG_UP
生成信号:从定义看来它是在关闭终端窗口时生成的,但从代码中的注释来看
/* *Ensure future opens won’t allocate controlling TTYs. */
似乎它是在不同的情况下生成的:它是什么时候生成的?
其次它想忽略这个信号,所以它设置sa.sa_handler = SIG_IGN
然后调用sigaction
。如果它忽略SIG_IGN
作为其处理程序的信号设置,为什么将传递给的掩码设置sigaction
为sigemptyset(&sa.sa_mask);
?我的意思是如果没有处理程序,则不会使用在执行处理程序之前设置的掩码:是吗?
完整的功能如下:
void daemonize(const char *cmd)
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
/* *Clear file creation mask.*/
umask(0);
/* *Get maximum number of file descriptors. */
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
{
err_quit("%s: can’t get file limit", cmd);
}
/* *Become a session leader to lose controlling TTY. */
if ((pid = fork()) < 0)
{
err_quit("%s: can’t fork", cmd);
}
else if (pid != 0) /* parent */
{
exit(0); //the parent will exit
}
setsid();
/* *Ensure future opens won’t allocate controlling TTYs. */
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0)
{
err_quit("%s: can’t ignore SIGHUP", cmd);
}
if ((pid = fork()) < 0)
{
err_quit("%s: can’t fork", cmd);
}
else if (pid != 0) /* parent */
{
exit(0);
}
/*
*Change the current working directory to the root so
* we won’t prevent file systems from being unmounted.
*/
if (chdir("/") < 0)
{
err_quit("%s: can’t change directory to /", cmd);
}
/*
*Close all open file descriptors.
*/
if (rl.rlim_max == RLIM_INFINITY)
{
rl.rlim_max = 1024;
}
for (i = 0; i < rl.rlim_max; i++)
{
close(i);
}
/*
*Attach file descriptors 0, 1, and 2 to /dev/null.
*/
fd0 = open("/dev/null", O_RDWR);
fd1 = dup(0);
fd2 = dup(0);
/*
*Initialize the log file.
*/
openlog(cmd, LOG_CONS, LOG_DAEMON);
if (fd0 != 0 || fd1 != 1 || fd2 != 2) {
syslog(LOG_ERR, "unexpected file descriptors %d %d %d", fd0, fd1, fd2);
exit(1);
}
}
编辑
另外我还有一个问题。为什么fork
在函数中被调用两次?