На примере программы из листинга 34.4 можно продемонстрировать, что в результате завершения контролирующего процесса сигнал SIGHUP передается всем участникам активной группы терминала. Эта программа создает по одному дочернему процессу на каждый аргумент командной строки
Листинг 34.4. Перехватывание сигнала SIGHUP при отключении от терминала
pgsjc/disc_SIGHUP.c
#define _GNU_SOURCE /* Получаем объявление strsignal() из
#include
#include
#include "tlpi_hdr.h"
static void /* Обработчик сигнала SIGHUP */
handler(int sig)
{
sig, strsignal(sig));
/* НЕБЕЗОПАСНО (см. подраздел 21.1.2) */
}
int
main(int argc, char *argv[])
{
pid_t parentPid, childPid;
int j;
struct sigaction sa;
if (argc < 2 || strcmp(argv[1], "-help") == 0)
usageErr("%s {d|s}… [> sig.log 2>&1]\n", argv[0]);
setbuf(stdout, NULL); /* Отключаем буферизацию стандартного вывода */
parentPid = getpid();
printf("PID of parent process is: %ld\n", (long) parentPid);
printf("Foreground process group ID is: %ld\n", (long) tcgetpgrp(STDIN_FILENO));
childPid = fork();
if (childPid == –1)
errExit("fork");
if (childPid == 0) { /* Если это потомок… */
if (setpgid(0, 0) == –1)
errExit("setpgid");
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sa.sa_handler = handler;
errExit("sigaction");
break; /* Потомок выходит из цикла */
}
}
/* Все процессы доходят сюда */
for (;;)
}
pgsjc/disc_SIGHUP.c
Представьте, что мы запустили программу из листинга 34.4 в окне терминала с помощью следующей команды:
$ exec./disc_SIGHUP d s s > sig.log 2>&1
Встроенная команда exec заставляет командную оболочку выполнить вызов exec() и заменить себя заданной программой. Поскольку командная оболочка была контролирующим процессом для терминала, наша программа теперь сама становится контролирующим процессом и при закрытии терминала получит сигнал SIGHUP; когда это случится, в файле sig.log можно будет найти следующие строки:
PID of parent process is: 12733
Foreground process group ID is: 12733
PID=12755 PGID=12755
PID=12756 PGID=12733
PID=12757 PGID=12733
PID=12733 PGID=12733
PID 12756: caught signal 1 (Hangup)
PID 12757: caught signal 1 (Hangup)
Закрытие окна терминала привело к отправке сигнала SIGHUP контролирующему процессу (родителю), который в ответ на это завершил свою работу. Как видно, оба потомка, находившиеся в одной группе с родителем (то есть в активной группе процессов текущего терминала) тоже получили сигнал SIGHUP. Однако этот сигнал не был отправлен потомку, который был в отдельной (фоновой) группе.
Возможность управления заданиями впервые появилась в командной оболочке csh в системе BSD; это случилось в 1980 году. Она позволяет пользователю командной строки выполнять одновременно несколько программ (заданий): одну в активном режиме, а все остальные — в фоновом. Задания можно останавливать, возобновлять и переключать между фоновым и активным режимами, как будет показано в следующих подразделах.
Изначально управление заданиями в стандарте POSIX.1 было опциональным. В дальнейших стандартах, относящихся к UNIX, эта возможность стала обязательной.