Я читаю книгу о системном программировании 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
вызывается дважды в функции?