Разработка приложений в среде Linux. Второе издание
Шрифт:
Процессам, которые требуют специальный код для правильных приостановок, обычно необходимо выполнять специальные действия при перезапуске. Это легко делается предоставлением обработчика сигнала для
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\n", 12);
13: catchSignal(SIGTSTP, 1);
14: kill(getpid, SIGTSTP);
15: } else {
16: write(STDOUT_FILENO, "получен SIGCONT\n", 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: }
15.2. Управление заданиями в
ladsh
Добавление управления заданиями к
ladsh
— это последнее добавление к простой оболочке, окончательный исходный код которой можно найти в приложении Б. Для начала потребуется добавить по элементу в структуры struct childProgram
, struct job
и struct jobSet
. Поскольку ladsh
некоторое время не рассматривался, вернитесь в главу 10, где были впервые представлены эти структуры данных. Ниже показано окончательное определение struct childProgram
. 35: struct childProgram {
36: pid_t pid; /* 0 на выходе */
37: char ** argv; /*
имя программы с аргументами * /
38: int numRedirections; /* элементы в массиве переадресации */
39: struct redirectionSpecifier * redirections; /* переадресации ввода-вывода */
40: glob_t globResult; /* результат универсализации параметров */
41: int freeGlob; /* должен ли освобождаться globResult? */
42: int isStopped; /* выполняется ли программа в данный момент?*/
43: };
Мы уже различаем работающие и завершенные дочерние программы с помощью элемента
pid
структуры struct childProgram
, равного нулю в случае завершения дочерней программы, а в противном случае содержащего действительный идентификатор процесса. Новый элемент, isStopped
, не равен нулю, если процесс был остановлен, в ином же случае он равен нулю. Обратите внимание, что его значение неважно, если pid
равен нулю. Аналогичные изменения потребуется внести и в
struct job
. Ранее эта структура отслеживала определенное количество программ в задании и количество выполняющихся процессов. Ее новый элемент, stoppedProgs
, записывает количество процессов задания, остановленных в данный момент. Он может быть вычислен на основе элементов isStopped
дочерних программ, содержащихся в задании, но лучше отслеживать его отдельно. После этого изменения получаем окончательную форму структуры struct job
. 45: struct job {
46: int jobld; /* номер задания */
47: int numProgs; /* количество программ в задании */
48: int runningProgs; /* количество выполняющихся программ */
49: char * text; /* имя задания */
50: char * cmdBuf; /* буфер различных argv */
51: pid_t pgrp; /* идентификатор группы процессов задания */
52: struct childProgram* progs; /* массив программ в задании */
53: struct job * next; /* для слежения за фоновыми программами */
54: int stopped Progs; /* количество активных, однако остановленных программ */
55: };
Как и предыдущие версии
ladsh
, код ladsh4.с
игнорирует SIGTTOU
. Это делается, чтобы позволить использовать tcsetpgrp
даже тогда, когда оболочка не является процессом переднего плана. Однако поскольку оболочка уже будет поддерживать правильное управление заданиями, дочерним процессам не следует игнорировать сигнал. Как только новый процесс разветвляется с помощью runCommand
, он устанавливает обработчик для SIGTTOU
в SIG_DFL
. Это позволяет драйверу терминала приостановить фоновые процессы, пытающиеся выполнить запись в терминал или провести с ним еще какие-то действия. Ниже приведен код, который начинается с создания дочернего процесса, где сбрасывается SIGTTOU
и выполняется дополнительная работа по синхронизации.
Поделиться:
Популярные книги
На распутье
2. Лэрн
Фантастика:
фэнтези
героическая фантастика
стимпанк
5.00
рейтинг книги
Идеальный мир для Лекаря 15
15. Лекарь
Фантастика:
боевая фантастика
юмористическая фантастика
аниме
5.00
рейтинг книги
Гром над Академией Часть 3
4. Гром над миром
Фантастика:
фэнтези
5.25
рейтинг книги
Попаданка в Измену или замуж за дракона
Любовные романы:
любовно-фантастические романы
6.25
рейтинг книги
Проданная невеста
Любовные романы:
любовно-фантастические романы
5.80
рейтинг книги
Лорд Системы
1. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
4.00
рейтинг книги
Вторая жизнь майора. Цикл
Вторая жизнь майора
Фантастика:
героическая фантастика
боевая фантастика
попаданцы
5.00
рейтинг книги
Сердце Дракона. Том 12
12. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.29
рейтинг книги
Уязвимость
Любовные романы:
современные любовные романы
7.44
рейтинг книги
Имя нам Легион. Том 4
4. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Безумный Макс. Ротмистр Империи
2. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
4.67
рейтинг книги
Наследница Драконов
2. Наследница Драконов
Любовные романы:
современные любовные романы
любовно-фантастические романы
6.81
рейтинг книги
Вечный. Книга III
3. Вечный
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Дурашка в столичной академии
Фантастика:
фэнтези
7.80