работу с асинхронными сигналами (fprintf(), strsignal(); см. подраздел 21.1.2) */
(long) tcgetpgrp(STDERR_FILENO));
fprintf(stderr, "Process %ld (%d) received signal %d (%s)\n",
(long) getpid(), cmdNum, sig, strsignal(sig));
/* Если мы перехватим сигнал SIGTSTP, он нас не остановит.
Следовательно, чтобы остановиться, мы генерируем SIGSTOP. */
raise(SIGSTOP);
}
int
main(int argc, char *argv[])
{
struct sigaction sa;
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
sa.sa_handler = handler;
errExit("sigaction");
if (sigaction(SIGTSTP, &sa, NULL) == –1)
errExit("sigaction");
if (sigaction(SIGCONT, &sa, NULL) == –1)
errExit("sigaction");
/* Если стандартный ввод связан с терминалом, то это первый процесс в конвейере:
выводим заголовки и инициализируем сообщение, которое отправится дальше по цепочке */
fprintf(stderr, "Terminal FG process group: %ld\n",
(long) tcgetpgrp(STDIN_FILENO));
cmdNum = 0;
} else { /* Это не первый процесс, значит, считываем сообщение из конвейера */
fatal("read got EOF or error");
}
(long) getpid(), (long) getppid(),
(long) getpgrp(), (long) getsid(0));
/* Если процесс не последний, передаем сообщение дальше */
if (!isatty(STDOUT_FILENO)) /* Если нет файла tty, то это не конец конвейера */
errMsg("write");
pause();
}
pgsjc/job_mon.c
Использование программы из листинга 34.5 продемонстрировано в следующей сессии командной строки. Сначала мы выводим идентификатор процесса, принадлежащего оболочке (это лидер сессии и группы процессов, для которой он является единственным участником), после чего создаем фоновое задание, состоящее из двух процессов:
$ echo $$
1204
$ ./job_mon |./job_mon &
[1] 1227
Terminal FG process group: 1204
Command PID PPID PGRP SID
1 1226 1204 1226 1204
2 1227 1204 1226 1204
По выводу, представленному выше, понятно, что командная оболочка остается активным процессом для терминала. Мы также можем видеть, что новое задание находится в одной сессии с командной оболочкой и что все процессы собраны в одной группе. Судя по идентификаторам, процессы в задании были созданы в том же порядке, в каком были перечислены программы в командной строке (так происходит в большинстве случаев, однако некоторые командные оболочки создают процессы в другом порядке).
Теперь создадим второе фоновое задание, состоящее из трех процессов:
$ ./job_mon |./job_mon |./job_mon &
[2] 1230
Terminal FG process group: 1204
Command PID PPID PGRP SID
1 1228 1204 1228 1204
2 1229 1204 1228 1204
3 1230 1204 1228 1204
Как видите, командная оболочка по-прежнему является активной группой процессов по отношению к терминалу. Мы также видим, что процессы для нового задания находятся в одной сессии с командной оболочкой, но в другой группе по сравнению с первым заданием. Теперь переключим второе задание в активный режим и отправим ему сигнал SIGINT:
$ fg
./job_mon |./job_mon |./job_mon
Process 1230 (3) received signal 2 (Interrupt)
Process 1229 (2) received signal 2 (Interrupt)
Terminal FG process group: 1228
Process 1228 (1) received signal 2 (Interrupt)
На основе вывода, приведенного выше, можно заключить, что сигнал SIGINT был доставлен всем процессам в активной группе. Мы также видим, что данное задание теперь представляет собой активную группу процессов по отношению к терминалу. Теперь пошлем ему сигнал SIGTSTP:
Process 1230 (3) received signal 20 (Stopped)
Process 1229 (2) received signal 20 (Stopped)
Terminal FG process group: 1228
Process 1228 (1) received signal 20 (Stopped)
[2]+ Stopped./job_mon |./job_mon |./job_mon
Теперь все участники группы процессов остановлены. Вывод говорит о том, что группа процессов 1228 являлась активным заданием. После остановки ее место заняла командная оболочка, хотя по листингу сессии этого не видно.
Продолжим, перезапустив задание с помощью команды bg, которая доставляет процессу в задании сигнал SIGCONT:
$ bg
[2]+./job_mon |./job_mon |./job_mon &
Process 1230 (3) received signal 18 (Continued)
Process 1229 (2) received signal 18 (Continued)