2.4.2 Функции управления терминалом
Терминал, как и любое другое внешнее устройство управляется при помощи системного вызова ioctl:
#include <sys/ioctl.h>
int ioctl(int d, int request, ...);
Вызов ioctlQ выполняет функцию request над файлом на который указывает дескриптор d и результат помещает в параметры следующие за параметром request. Список функций различен для каждого устройства. Например, для терминала имеется функция получения его геометрических параметров:
#include <termios.h>
struct winsize {
unsigned short ws_row; unsigned short ws_col; unsigned short ws.xpixel; unsigned short ws_ypixel;
#define TIOCGWINSZ
Таким образом, чтобы получить размер окна терминала необходимо выполнить следующее:
ioctl (d, TIOCGWINSZ, &win);
2.2 Доступы к терминалам в Linux
Алфавитно-цифровой терминал - последовательное устройство, и операционная система обмен данными с терминалом через последовательный интерфейс - терминальную линию. С каждой терминальной линией ассоциирован специальный файл устройства, например /dev/ttyO.
Узнать, какая терминальная линия используется (или просто какой терминал используется) можно посредствам вызова функции ttyname:
#include <unistd.h>
char *ttyname(int desc);
Функция ttyname возвращает указатель на строку, содержащую название специального файла терминальной линии (например ,/dev/pts/О), соответсвующей дескриптору desc. В случае возникновения ошибки функция возвращает NULL.
Для ввода и вывода на терминал пользовательские программы могут использовать стандартные вызовы функций библиотеки Си - scanf и printf. Такой способ взаимодействия с терминалом называется высокоуровневый. Для низкоуровневого доступа программа пользователей должна взаимодействовать со специальным файлом терминальной линией. При таком способе доступа можно управлять режимом терминала.
2.2.1 Режимы работы терминала
Терминальные драйверы выполняют ту же функцию, что и остальные драйверы (см. рис.13): управление передачей данных от/на терминалы. Однако терминалы имеют одну особенность, связанную с тем, что они обеспечивают интерфейс пользователя с системой. Обеспечивая интерактивное использование системы UNIX, терминальные драйверы имеют свой внутренний интерфейс с модулями, интерпретирующими ввод и вывод строк. Модуль, отвечающий за такую обработку, называется дисциплиной линии (line discipline). Существует два режима терминального ввода/вывода:
Канонический режим. В этом режиме ввод с терминала обрабатывается в виде законченных строк.
Неканонический режим, при котором ввод не интерпретируется.
В каноническом режиме интерпретаторы строк преобразуют неструктурированные последовательности данных, введенные с клавиатуры, в каноническую форму (то есть в форму, соответствующую тому, что пользователь имел в виду на самом деле) прежде, чем послать эти данные принимающей программе. Драйвер терминала получает всю введенную последовательность, включая и символы стирания. В каноническом режиме модуль дисциплины линии буферизует информацию в строку (набор символов, заканчивающийся символом возврата каретки) и стирает символы в буфере, прежде чем переслать исправленную последовательность считывающему процессу. В таком режиме, например, работает командный интерпретатор shell.
В режиме без обработки строковый интерфейс передает данные между программой и терминалом без каких-либо преобразований. Например, текстовый редактор работает с драйвером в неканоническом режиме, благодаря чему любой символ, введенный пользователем, интерпретируется самим процессом.
В функции модуля дисциплины линии входят:
1. Построчный разбор введенных последовательностей.
Обработка символов стирания.
Обработка символов удаления, отменяющих всех предыдущих символов.
Отображение символов, полученных терминалом.
Расширение выходных данных, например, преобразование символов табуляции в последовательности пробелов.
Предоставление возможности не обрабатывать специальные символы, такие как символы стирания, удаления и возврата каретки.