•
Драйвер терминала также интерпретирует ряд специальных символов, таких как прерывание (обычно Ctrl+C) и конец файла (обычно Ctrl+D). Это может приводить к генерированию сигнала для фоновой группы процессов или выполнению некоего условия, которого ожидает программа, считывающая данные из терминала. Программы, переключающие терминал в неканонический режим, обычно также отключают часть специальных символов (или все).
Драйвер терминала управляет двумя очередями (см. рис. 58.1): одна — для ввода символов, передающихся из устройства в считывающий процесс (их может быть несколько), а другая — для вывода символов, которые процесс передает терминалу. Если включена функция эхо-контроля, драйвер автоматически добавляет копию любого введенного символа в конец исходящей очереди; это позволяет отображать в терминале вводимый текст.
Стандарт SUSv3 оговаривает ограничение MAX_INPUT, позволяющее системе устанавливать максимальную длину входящей очереди терминала. Еще одно ограничение, MAX_CANON, определяет максимальное количество байтов, которое может содержаться в одной строке в каноническом режиме. В Linux вызовы sysconf(_SC_MAX_INPUT) и sysconf(_SC_MAX_CANON) возвращают значение 255. Однако ни одно из этих ограничений не используется самим ядром, имеющим собственное ограничение для размера входящей очереди — 4096 байт. Аналогичное ограничение существует и для исходящей очереди, но оно не влияет на работу приложений, поскольку в случае если процесс генерирует вывод быстрее, чем драйвер может его обработать, то ядро приостанавливает выполнение данного процесса, пока в исходящей очереди опять не появится свободное место.
В Linux доступен вызов ioctl(fd, FIONREAD, &cnt), позволяющий получить количество непрочитанных байтов во входящей очереди терминала, на который указывает файловый дескриптор fd. Эта возможность не предусмотрена стандартом SUSv3.
Для извлечения и изменения атрибутов терминала предусмотрены функции tcgetattr() и tcsetattr().
#include
int tcgetattr(int
int tcsetattr(int
const struct termios *
Обе функции возвращают 0 при успешном завершении или -1 при ошибке
Рис. 58.1.
Аргумент fd представляет собой файловый дескриптор, который должен ссылаться на терминал (в противном случае эти функции завершаются ошибкой ENOTTY).
Аргумент termios_p является указателем на структуру termios, хранящую атрибуты терминала:
struct termios {
tcflag_t c_iflag; /* Флаги ввода */
tcflag_t c_oflag; /* Флаги вывода */
tcflag_t c_cflag; /* Управляющие флаги */
tcflag_t c_lflag; /* Локальные режимы */
cc_t c_line; /* Порядок следования строк (нестандартное) */
cc_t c_cc[NCCS]; /* Специальные символы терминала */
speed_t c_ispeed; /* Скорость ввода (нестандартное; не используется) */
speed_t c_ospeed; /* Скорость вывода (нестандартное; не используется) */
};
Первые четыре поля структуры termios — битовые маски (тип данных tcflag_t представлен целым числом подходящего размера), содержащие флаги, которые влияют на различные аспекты работы драйвера терминала:
• c_iflag содержит флаги, управляющие вводом терминала;
• c_oflag содержит флаги, управляющие выводом терминала;
• c_cflag содержит флаги, связанные с аппаратным управлением последовательного порта;
• c_lflag содержит флаги, управляющие пользовательским интерфейсом для терминального ввода.
Все флаги, используемые в приведенных выше полях, будут перечислены в табл. 58.2 далее.
Поле c_line определяет порядок следования строк для текущего терминала. С целью поддержки эмуляторов терминала оно всегда равно N_TTY; это новый режим, который является частью кода ядра, занимающегося работой с терминалом и реализующего обработку ввода/вывода в каноническом режиме. Изменение данного поля имеет смысл при программировании последовательных портов.
Массив c_cc содержит специальные символы терминала (
Поля c_ispeed и c_ospeed не используются в Linux (и не предусмотрены стандартом SUSv3). О том, как эта ОС хранит данные о скорости последовательного порта, мы расскажем в разделе 58.7.