15.1.3. Обработка сигналов управления заданиями
15.1.3. Обработка сигналов управления заданиями
Хотя многие приложения можно останавливать и перезапускать без побочных эффектов, другим процессам требуется обрабатывать состояния останова и запуска. Например, большинству редакторов необходимо модифицировать параметры терминала в рабочем состоянии. Когда пользователи приостанавливают процесс, они ожидают, что их терминал восстановит свое состояние по умолчанию.
Когда процессу нужно выполнять действия перед приостановкой, должен быть предусмотрен обработчик сигнала для SIGTSTP. Это позволяет ядру уведомлять процесс о необходимости приостановки.
При получении SIGTSTP процесс должен немедленно выполнить все необходимые ему действия, чтобы разрешить приостановку (например, восстановление исходного состояния терминала) и приостановиться самому. Самый простой способ приостановки процесса — передача самому себе сигнала SIGSTOP. Однако большинство оболочек отображают сообщения с типом сигнала, вызвавшего остановку процесса, и если процесс передаст себе sigstop, он будет отличаться от большинства приостановленных процессов. Во избежание этого неудобства многие приложения сбрасывают свой обработчик SIGTSTP в SIG_DFL и передают себе SIGTSTP.
Процессам, которые требуют специальный код для правильных приостановок, обычно необходимо выполнять специальные действия при перезапуске. Это легко делается предоставлением обработчика сигнала для SIGCONT, который выполняет такие действия. Если процесс приостанавливается с помощью SIGTSTP, такие специальные действия, возможно, включают установку обработчика сигнала для SIGTSTP.
Ниже приведен код простого обработчика сигналов SIGCONT и SIGTSTP. Когда пользователь приостанавливает или перезапускает процесс, последний отображает сообщение перед остановкой или продолжением.
1: /* monitor.с */
2:
3: #include <signal.h>
4: #include <stdio.h>
5: #include <string.h>
6: #include <unistd.h>
7:
8: void catchSignal(int sigNum, int useDefault);
9:
10: void handler(int signum) {
11: if (signum == SIGTSTP) {
12: write(STDOUT_FILENO, "получен SIGTSTP ", 12);
13: catchSignal(SIGTSTP, 1);
14: kill(getpid(), SIGTSTP);
15: } else {
16: write(STDOUT_FILENO, "получен SIGCONT ", 12);
17: catchSignal(SIGTSTP, 0);
18: }
19: }
20:
21: void catchSignal(int sigNum, int useDefault) {
22: struct sigaction sa;
23:
24: memset(&sa, 0, sizeof(sa));
25:
26: if (useDefault)
27: sa.sa_handler = SIG_DFL;
28: else
29: sa.sa_handler = handler;
30:
31: if (sigaction(sigNum, &sa, NULL)) perror("sigaction");
32: }
33:
34: int main() {
35: catchSignal(SIGTSTP, 0);
36: catchSignal(SIGCONT, 0);
37:
38: while(1);
39:
40: return 0;
41: }