- •Рекомендации по написанию командных интерпретаторов для ос unix
- •Void c_handl(int num) //обработчик sigchld
- •4. Терминальный ввод/вывод
- •Int cterm, //управляющий терминал
- •5. Запуск внешних программ
- •6. Ожидание завершения фоновых программ
- •7. Анализ статуса (кода) завершения программ
- •8. Управление заданиями
- •Приложения:
- •Задания на курсовую работу по дисциплине "спо"
Void c_handl(int num) //обработчик sigchld
{
...
//разрешаем обработку SIGCHLD внутри функции,
//делая ее таким образом реентерабельной
sigprocmask(SIG_UNBLOCK,&cldset,0); //в некоторых системах проще использовать
//флаг SA_NODEFER при вызове sigaction()
...
}
...
//маскируем SIGTTOU для этого процесса и его потомков
sigemptyset(&cldset);
sigaddset(&cldset,SIGTTOU); //делаем маску
sigprocmask(SIG_BLOCK,&cldset,0); //устанавливаем
sigemptyset(&cldset);
sigaddset(&cldset,SIGCHLD); //маску cldset будет использовать обработчик
act.sa_handler=c_handl; //задаем адрес обработчика
act.sa_flags=0; //очищаем флаги (в этом примере - лишнее действие)
sigfillset(&act.sa_mask); //маскировать на время обработки все сигналы,
sigdelset(&act.sa_mask,SIGCHLD); //кроме самого SIGCHLD
sigaction(SIGCHLD,&act,0); //устанавливаем реакцию на SIGCHILD
//В результате все сигналы SIGCHLD будут обработаны,
//причем обработчик может быть прерван только сигналами SIGKILL,
//SIGSTOP, ну и SIGCHILD
...
4. Терминальный ввод/вывод
Процесс может производить чтение/запись и получать сигналы типа SIGINT, SIGQUIT
и SIGTSTP c управляющего терминала, если он принадлежит той же программной группе,
что и терминал. Иначе, при попытке чтения/записи процесс будет получать сигналы
SIGTTIN/SIGTTOU. По этому принципу процессы делятся на интерактивные (foreground)
и фоновые (background, или асинхронные).
Управляющий терминал вместе с открытыми для него стандартными потоками ввода/вывода
наследуется процессом от родителя.
Терминалы отличаются друг от друга протоколами управления, возможностями
ввода/вывода, скоростью передачи информации и т. п. Если аппаратура терминала
(или его эмулятор) поддерживает широкий набор возможностей по управлению
вводом/выводом, такой терминал называют интеллектуальным (smart), иначе
терминал будет простым (dumb). Обычно терминалы используют некоторый набор
соглашений (протокол) об обмене управляющей информацией с программами.
Примерами таких протоколов являются vt100 и ANSI, описанные в приложении.
Терминал с одной стороны, и его драйвер с другой, должны работать в согласованых
по основным параметрам режимах. Режим работы драйвера для конкретного терминала
можно изменить с помощью стандартного системного вызова ioctl(), передавая ему
в качестве одного из аргументов имя файла устройства. Существует также утилита
'stty' для просмотра/изменения параметров терминала из командной строки.
В некоторых системах есть упрощенный интерфейс к ioctl() - функции типа
tcgetattr(), tcsetattr().
Управляющие символы, поступающие с терминала, могут обрабатываться его
драйвером. Например, комбинации клавиш Ctrl+c, Ctrl+\ и Ctrl+z приводят к
посылке процессам, связанным с этим терминалом, сигналов SIGINT, SIGQUIT и
SIGTSTP соответственно. Генерацию сигналов можно включить/выключить, а
комбинацию символов - переопределить вызовом ioctl().
Рассмотрим конкретный пример изменения параметров драйвера терминала.
По умолчанию терминал UNIX работает в так называемом каноническом режиме,
что означает передачу символов, введенных с клавиатуры в пользовательскую
программу только после нажатия клавиши перевода строки. Если требуется ввод
символов без ожидания и какой-либо предварительной обработки, необходимо
отменить этот режим. Кроме того, драйвер автоматически посылает "эхо" ввода
на терминал, что тоже не всегда является приемлемым (например, Вы решили
реализовать в программе реакцию на нажатие функциональных клавиш). Эхо тоже
можно отменить, а там где оно необходимо, реализовать его в своей программе.
Пример: Изменение режимов терминала (протестирован под Linux 6.2).
#include <sys/types.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
#include <stdio.h>
struct termios term;
tcflag_t oldflags;
main()
{