Системное программирование в UNIX средствами Free Pascal

       

Введение


Когда пользователь взаимодействует с программой при помощи терминала, происходит намного больше действий, чем может показаться на первый взгляд. Например, если программа выводит строку на терминальное устройство, то она вначале обрабатывается в разделе ядра, которое будем называть драйвером терминала (terminal driver). В зависимости от значения определенных флагов состояния системы строка может передаваться буквально или как-то изменяться драйвером. Одно из обычных изменений заключается в замене символов line-feed (перевод строки) или newline (новая строка) на последовательность из двух символов carriage-return (возврат каретки) и newline. Это гарантирует, что каждая строка всегда будет начинаться с левого края экрана терминала или открытого окна.

Аналогично драйвер терминала обычно позволяет пользователю редактировать ошибки в строке ввода при помощи текущих символов

erase (стереть) и kill (уничтожить). Символ erase удаляет последний напечатанный символ, а символ kill – все символы до начала строки. Только после того, как вид строки устроит пользователя и он нажмет на клавишу Return (ввод), драйвер терминам передаст строку программе.

Но это еще не все. После того, как выводимая строка достигает терминала, аппаратура терминала может либо просто вывести ее на экран, либо интерпретировать ее как escape-последовательность (escape-sequence), посланную для управления экраном. В результате, например, может произойти не вывод сообщения, а очистка экрана.

На рис. 9.1 более ясно показаны различные компоненты связи между компьютером и терминалом.

Рис. 9.1. Связь между процессом UNIX и терминалом

Эта связь включает четыре элемента:

–        программы (А). Программа генерирует выходные последовательности волов и интерпретирует входные. Она может взаимодействовать с терминалом при помощи системных вызовов (fdread или fdwrite), стандартной библиотеки ввода/вывода или специального библиотечного пакета, разработанного для управления экраном. Разумеется, в конечном счете весь ввод/вывод будет осуществляться при помощи вызовов fdread и fdwrite, так как высокоуровневые библиотеки могут вызывать только эти основные примитивы;




–        драйвер терминала (В). Основная функция драйвера терминала заключается в передаче данных от программы к периферийному устройству и наоборот. В самом ядре UNIX терминал обычно состоит из двух основных программных компонентов – драйвера устройства (device driver) и дисциплины линии связи (line discipline). Драйвер устройства является низкоуровневым программным обеспечением, написанным для связи с определенным аппаратным обеспечением, которое позволяет компьютеру взаимодействовать с терминалом. На самом деле чаще всего драйверы устройств нужны для того, чтобы работать с разными типами аппаратного обеспечения. Над этим нижним слоем надстроены средства, которые полагаются на то, что основные свойства, поддерживаемые драйвером устройства, являются общими независимо от аппаратного обеспечения. Кроме этой основной функции передачи данных, драйвер терминала будет также выполнять некоторую логическую обработку входных и выходных данных, преобразуя одну последовательность символов в другую. Это осуществляется дисциплиной линии связи. Она также может обеспечивать множество функций для помощи конечному пользователю, таких как редактирование строки ввода. Точная обработка и преобразование данных зависят от флагов состояния, которые хранятся в дисциплине линии связи для каждого порта терминала. Они могут устанавливаться при помощи группы системных вызовов, которая будут рассмотрена в следующих разделах;

–        клавиатура и экран (С и D). Эти два элемента представляют сам терминал и подчеркивают его двойственную природу. Узел (С) означает клавиатуру терминала и служит источником ввода. Узел (D) представляет экран терминала и выступает в качестве назначения вывода. Программа может получить доступ к терминалу и как к устройству ввода, и как к устройству вывода при помощи общего имени терминала, и, в конечном счете, единственного дескриптора файла. Для того чтобы это было возможно, дисциплина лини связи имеет раздельные очереди ввода и вывода для каждого терминала. Эта схема показана на рис. 9.2.





Рис. 9.2. Реализация терминала

До сих пор предполагалось, что подключенное к терминалу периферийное устройство является стандартным дисплеем. Вместе с тем периферийное устройство может быть принтером, плоттером, сетевым адаптером или даже другим компьютером. Тем не менее, независимо от природы периферийного устройства, оно может служить и в качестве источника, и в качестве назначения для входного и выходного потоков данных соответственно.

Эта глава будет в основном посвящена узлам (А) и (В) схемы. Другими словами, будет рассмотрено взаимодействие между программой и драйвером устройства на уровне системных вызовов. Не будем касаться совершенно отдельного вопроса работы с экраном, поскольку драйвер терминала не принимает участия в создании соответствующих escape-последовательностей, управляющих экраном.

Перед тем как продолжить дальше, следует сделать два предостережения. Во-первых, будут рассматриваться только «обычные» терминалы, а не графические, построенные на оконных системах Х Window System или MS Windows. Для них характерны свои проблемы, которых касаться не будем. Во-вторых, работа с терминалом в UNIX является областью, печально известной своей несовместимостью. Тем не менее спецификация XSI обеспечивает стандартный набор системных вызовов. Именно на них и сфокусируем внимание.


Содержание раздела