Разработка приложений в среде 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
и выполняется дополнительная работа по синхронизации.
Поделиться:
Популярные книги
Война
7. Ермак
Фантастика:
боевая фантастика
альтернативная история
5.25
рейтинг книги
Экономка тайного советника
Фантастика:
фэнтези
5.00
рейтинг книги
Чужбина
2. Дворянская кровь
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Мятежник
4. Стеллар
Фантастика:
боевая фантастика
7.39
рейтинг книги
Бестужев. Служба Государевой Безопасности. Книга вторая
2. Граф Бестужев
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Метатель. Книга 3
3. Метатель
Фантастика:
попаданцы
альтернативная история
рпг
фэнтези
фантастика: прочее
постапокалипсис
5.00
рейтинг книги
Студент из прошлого тысячелетия
2. Соприкосновение миров
Фантастика:
героическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Ты не мой BOY
5. Самбисты
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Идеальный мир для Лекаря 2
2. Лекарь
Фантастика:
юмористическая фантастика
попаданцы
аниме
5.00
рейтинг книги
Лекарь для захватчика
Фантастика:
попаданцы
историческое фэнтези
фэнтези
5.00
рейтинг книги
Отверженный VI: Эльфийский Петербург
6. Отверженный
Фантастика:
городское фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Он тебя не любит(?)
Любовные романы:
современные любовные романы
7.46
рейтинг книги
Убивать чтобы жить 3
3. УЧЖ
Фантастика:
героическая фантастика
боевая фантастика
рпг
5.00
рейтинг книги
Темный Лекарь 11
11. Темный Лекарь
Фантастика:
попаданцы
аниме
фэнтези
5.00