работу с асинхронными сигналами (fprintf(), strsignal(); см. подраздел 21.1.2) */

if (getpid() == getpgrp()) /* Если процесс является лидером группы */

 fprintf(stderr, "Terminal FG process group: %ld\n",

(long) tcgetpgrp(STDERR_FILENO));

fprintf(stderr, "Process %ld (%d) received signal %d (%s)\n",

(long) getpid(), cmdNum, sig, strsignal(sig));

/* Если мы перехватим сигнал SIGTSTP, он нас не остановит.

Следовательно, чтобы остановиться, мы генерируем SIGSTOP. */

if (sig == SIGTSTP)

raise(SIGSTOP);

}

int

main(int argc, char *argv[])

{

struct sigaction sa;

sigemptyset(&sa.sa_mask);

sa.sa_flags = SA_RESTART;

sa.sa_handler = handler;

if (sigaction(SIGINT, &sa, NULL) == –1)

errExit("sigaction");

if (sigaction(SIGTSTP, &sa, NULL) == –1)

errExit("sigaction");

if (sigaction(SIGCONT, &sa, NULL) == –1)

errExit("sigaction");

/* Если стандартный ввод связан с терминалом, то это первый процесс в конвейере:

выводим заголовки и инициализируем сообщение, которое отправится дальше по цепочке */

if (isatty(STDIN_FILENO)) {

fprintf(stderr, "Terminal FG process group: %ld\n",

(long) tcgetpgrp(STDIN_FILENO));

 fprintf(stderr, "Command PID PPID PGRP SID\n");

cmdNum = 0;

} else { /* Это не первый процесс, значит, считываем сообщение из конвейера */

 if (read(STDIN_FILENO, &cmdNum, sizeof(cmdNum)) <= 0)

fatal("read got EOF or error");

}

cmdNum++;

fprintf(stderr, "%4d %5ld %5ld %5ld %5ld\n", cmdNum,

(long) getpid(), (long) getppid(),

(long) getpgrp(), (long) getsid(0));

/* Если процесс не последний, передаем сообщение дальше */

if (!isatty(STDOUT_FILENO)) /* Если нет файла tty, то это не конец конвейера */

 if (write(STDOUT_FILENO, &cmdNum, sizeof(cmdNum)) == –1)

errMsg("write");

for(;;) /* Ждем сигнала */

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

Нажмите Ctrl+C, чтобы сгенерировать сигнал SIGINT (signal 2)

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:

Нажмите Ctrl+Z, чтобы сгенерировать сигнал SIGTSTP (signal 20 в Linux/x86-32)

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)

Перейти на страницу:

Похожие книги