Чтение онлайн

на главную

Жанры

Разработка приложений в среде Linux. Второе издание

Троан Эрик В.

Шрифт:

514: pipe(controlfds);

515:

516: if (!(newJob.progs[i].pid = fork)) {

517: signal(SIGTTOU, SIG_DFL);

518:

519: close(controlfds[1]);

520: /* это чтение вернет 0, когда закроется записывающая сторона*/

521: read(controlfds[0], &len, 1);

522: close(controlfds[0]);

Канал

controlfds
используется для приостановки дочернего процесса до того, как оболочка переместит этот
процесс в подходящую группу процессов. Закрытием записывающей стороны канала и чтением из считывающей стороны дочерний процесс останавливается до тех пор, пока родительский процесс закроет записывающую сторону, что происходит после вызова
setpgid
в строке 546. Этот тип механизма необходим для гарантии того, что дочерний процесс перемещается в группу процессов до происшествия
exec
. Если подождать до
exec
, то не будет уверенности, что процесс попадет в правильную группу процессов, пока он не начнет доступ к терминалу (который может быть запрещен).

Завершенные дочерние процессы проверяются

ladsh
два раза. Первый раз это происходит во время ожидания процессов в группе процессов переднего плана. После завершения либо остановки процесса переднего плана
ladsh
проверяет изменения в состояниях своих фоновых процессов с помощью функции
checkJobs
. Обе этих кодовых цепочки необходимо модифицировать с целью обработки остановленных и завершенных дочерних процессов.

Добавление флага

WUNTRACED
к вызову
waitpid
, ожидающему на процессах переднего плана, позволяет заметить также остановленные процессы. Когда процесс скорее останавливается, чем завершается, устанавливается флаг дочернего процесса
isStopped
и увеличивается номер задания
stoppedProgs
. Если все программы задания были остановлены,
ladsh
снова перемещается на передний план и ожидает команды пользователя. Вот как выглядит часть главного цикла
ladsh
, ожидающая на процессе переднего плана.

708: /* задание выполняется на переднем плане; ожидать его */

709: i = 0;

710: while (!jobList.fg->progs[i].pid ||

711: jobList.fg->progs[i].isStopped) i++;

712:

713: waitpid(jobList.fg->progs[i].pid, &status, WUNTRACED);

714:

715: if (WIFSIGNALED(status) &&

716: (WTERMSIG(status) != SIGINT)) {

717: printf("%s\n", strsignal(status));

718: }

719:

720: if (WIFEXITED(status) || WIFSIGNALED(status)) {

721: /* дочерний процесс завершен */

722: jobList.fg->runningProgs--;

723: jobList.fg->progs[i].pid = 0;

724:

725: if (!jobList.fg->runningProgs) {

726: /* дочерний процесс завершен */

727:

728: removeJob(&jobList, jobList.fg);

729: jobList. fg = NULL;

730:

731: /* переместить оболочку на передний план */

732: if (tcsetpgrp (0, getpid))

733: perror("tcsetpgrp");

734: }

735: } else {

736: /*
дочерний процесс остановлен */

737: jobList.fg->stoppedProgs++;

738: jobList.fg->progs[i].isStopped = 1;

739:

740: if (jobList.fg->stoppedProgs ==

741: jobList.fg->runningProgs) {

742: printf ("\n" JOB_STATUS_FORMAT,

743: jobList.fg->jobId,

744: "Остановлен", jobList.fg->text);

745: jobList.fg = NULL;

746: }

747: }

748:

749: if (!jobList.fg) {

750: /* переместить оболочку на передний план */

751: if (tcsetpgrp (0, getpid))

752: perror("tcsetpgrp");

753: }

754: }

Подобным образом фоновые задания могут прерываться с помощью сигналов. Мы снова добавляем

WUNTRACED
к
waitpid
, что проверяет состояния фоновых процессов. После остановки фонового процесса обновляются флаг
isStopped
и счетчик
stoppedProgs
, а в случае остановки всего задания выводится сообщение.

Последняя возможность, требуемая для

ladsh
— перемещение задания между состоянием выполнения на переднем плане, состоянием выполнения в фоне и остановом. Это делается с помощью двух встроенных команд:
fg
и
bg
. Они являются ограниченными версиями нормальных команд оболочки, носящих те же имена. Оба принимают один параметр, являющийся номером задания, которому предшествует знак
%
(для совместимости со стандартными оболочками). Команда
fg
перемещает определенное задание на передний план, a
bg
запускает его в фоне.

Обе операции выполняются передачей

SIGCONT
каждому процессу в активизируемой группе процессов. Поскольку этот сигнал может передаваться каждому процессу с помощью отдельных вызовов
kill
, несколько проще передать его всей группе процессов, используя отдельный вызов
kill
. Ниже приведена реализация встроенных команд
fg
и
bg
.

461: } else if (! strcmp(newJob.progs[0].argv[0], "fg") ||

462: !strcmp(newJob.progs[0].argv[0], "bg")) {

463: if (!newJob.progs[0].argv[1] || newJob.progs[0].argv[2]) {

464: fprintf(stderr,

465: "%s: ожидался в точности один аргумент\n",

466: newJob.progs[0].argv[0]);

467: return 1;

468: }

469:

470: if (sscanf(newJob.progs[0].argv[l], "%%%d", &jobNum) != 1)

471: fprintf(stderr, "%s: ошибочный аргумент '%s'\n",

Поделиться:
Популярные книги

Черный Маг Императора 9

Герда Александр
9. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Черный Маг Императора 9

Не грози Дубровскому! Том II

Панарин Антон
2. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том II

Идеальный мир для Социопата 7

Сапфир Олег
7. Социопат
Фантастика:
боевая фантастика
6.22
рейтинг книги
Идеальный мир для Социопата 7

Бремя империи

Афанасьев Александр
Бремя империи - 1.
Фантастика:
альтернативная история
9.34
рейтинг книги
Бремя империи

Приручитель женщин-монстров. Том 5

Дорничев Дмитрий
5. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 5

Мастер...

Чащин Валерий
1. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
6.50
рейтинг книги
Мастер...

Эфемер

Прокофьев Роман Юрьевич
7. Стеллар
Фантастика:
боевая фантастика
рпг
7.23
рейтинг книги
Эфемер

Приручитель женщин-монстров. Том 4

Дорничев Дмитрий
4. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 4

Идеальный мир для Лекаря 3

Сапфир Олег
3. Лекарь
Фантастика:
фэнтези
юмористическое фэнтези
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 3

Дракон

Бубела Олег Николаевич
5. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.31
рейтинг книги
Дракон

Не грози Дубровскому! Том V

Панарин Антон
5. РОС: Не грози Дубровскому!
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Не грози Дубровскому! Том V

Первый пользователь. Книга 2

Сластин Артем
2. Первый пользователь
Фантастика:
боевая фантастика
рпг
4.80
рейтинг книги
Первый пользователь. Книга 2

Последний попаданец 9

Зубов Константин
9. Последний попаданец
Фантастика:
юмористическая фантастика
рпг
5.00
рейтинг книги
Последний попаданец 9

Запретный Мир

Каменистый Артем
1. Запретный Мир
Фантастика:
фэнтези
героическая фантастика
8.94
рейтинг книги
Запретный Мир