SWD Software Ltd. - официальный дистрибьютор QNX на территории России и стран бывшего СССР Операционная система реального времени QNX
Инструменты для создания надёжных встраиваемых систем и
интеллектуальных устройств любой сложности
QNX Software Systems - разработчик встраиваемой операционной системы QNX
Информационные брошюры
Статьи и публикации
Техническая литература
Литература по QNX 4
Литература по QNX 6
Материалы конференций QNX-Россия
Полезные ссылки
Блог QNX
Главная страница > Материалы > Техническая литература > Литература по QNX 4 > Книга "Системная архитектура" > Менеджер устройств Сделать страницу стартовой Послать ссылку коллеге Версия для печати

Менеджер устройств

Эта глава охватывает следующие темы:

Введение

Менеджер устройств QNX (Dev) является интерфейсом между процессами и терминальными устройствами. Эти терминальные устройства располагаются в пространстве имен ввода/вывода с именами, начинающимися с /dev. Например, консольное устройство в QNX будет иметь имя:

/dev/con1

Обслуживание устройств

Программы в QNX получают доступ к терминальным устройствам, используя стандартные функции open(), close(), read() и write(). Для процесса QNX терминальное (оконечное) устройство представляется двунаправленным потоком байт, который может считываться и записываться процессом.

Менеджер устройств регулирует поток данных между приложением и устройством. Dev выполняет некоторую обработку этих данных в соответствии с параметрами управляющей структуры терминала (называемой termios), которая существует для каждого устройства. Пользователи могут запрашивать и/или изменять эти параметры с помощью утилиты stty; программы могут использовать функции tcgetattr() и tcsetattr().

Параметры структуры termios управляют функциональностью низкого уровня, такой как:

  • параметры линии (включая скорость передачи, контроль четности, стоп-биты, биты данных);
  • эхо-вывод символов;
  • редактирование строки ввода;
  • распознавание и реакция на команду "Break" и зависания;
  • программное и аппаратное управление потоком данных;
  • преобразование выводимых символов.

Менеджер устройств также предоставляет набор дополнительных услуг, доступных процессам для работы с терминальным устройством. В следующей таблице приведены некоторые из этих услуг.

Процесс может: Функция Си:
Выполнять операции чтения с контролем времени dev_read() или read() и tcsetattr()
Получать асинхронное извещение о доступных данных dev_arm()
На одном или более устройствах ввода ждать полного завершения операции вывода tcdrain()
Посылать команду Break по каналу связи tcsendbreak()
Разорвать соединение tcdropline()
Вставить входные данные dev_insert_chars()
Выполнять неблокирующиеся чтение и запись open() и fcntl() (O_NONBLOCK mode)

Режим редактируемого ввода

Наиболее важный режим работы устройства управляется битом ICANON в управляющей структуре termios. Если этот управляющий бит установлен, то Менеджер устройств выполняет функции редактирования строки для принимаемых символов. Таким образом, только когда строка "введена" - обычно, когда получен символ перевода каретки (CR), - данные станут доступны для прикладных процессов. Такой режим работы называется редактируемым - от английского edited. Этот режим еще называют canonical (каноническим) и иногда cooked (приготовительным).

Большинство неполноэкранных приложений выполняются в редактируемом режиме. Типичным примером является командный интерпретатор (Shell).

Следующая таблица показывает, как Dev обрабатывает некоторые специальные управляющие символы, если соответствующие параметры установлены в структуре termios.

Dev выполнит: Когда получит символ:
Сдвиг курсора на один символ влево LEFT
Сдвиг курсора на один символ вправо RIGHT
Сдвиг курсора в начало строки HOME
Сдвиг курсора в конец строки END
Удаление символа слева от курсора ERASE
Удаление символа в текущей позиции курсора DEL
Удаление всей строки ввода KILL
Стирание текущей строки и восстановление предыдущей UP
Стирание текущей строки и восстановление следующей DOWN
Переключение между режимами вставки и замены INS

Символы редактирования строки отличаются для различных терминалов. При запуске консоли QNX всегда определен полный набор редактирующих символов.

Если терминал подключен к QNX через последовательный канал, необходимо установить редактирующие символы, которые будут использоваться для данного конкретного терминала. Для этого вы можете использовать утилиту stty. Например, если терминал VT100 подключен к последовательному порту (/dev/ser1), то следующая команда извлечет соответствующие редактирующие символы из базы данных terminfo и применит их к /dev/ser1:

stty term=vt100

Если же к этому последовательному порту подключен модем, для связи с другой QNX системой с помощью утилиты qtalk, редактирующие символы следует установить так:

stty term=qnx

Режим необрабатываемого ввода

Когда бит ICANON не установлен, то говорят, что устройство находится в необрабатываемом ("сыром", английский термин raw) режиме. В этом режиме не производится никакое редактирование ввода, а все получаемые данные немедленно становятся доступными для QNX-процессов.

Полноэкранные программы и коммуникационные программы являются примерами приложений, которые переводят устройство в сырой режим.

При чтении из сырого устройства приложение может задать условия, при которых будет удовлетворен запрос на ввод данных. Критерии, используемые при приеме сырых данных, базируются на двух параметрах структуры termios: MIN и TIME. Приложение может определить еще один дополнительный параметр при вызове функции dev_read(). Этот параметр, TIMEOUT, используется при написании протоколов или приложений реального времени. Учтите, что для функции read() TIMEOUT всегда 0.

Когда процесс запрашивает ввод n байт данных, эти три параметра определяют, когда должен быть удовлетворен запрос:

MINTIMETIMEOUT Описание:
0 0 0 Вернуть немедленно столько байт, сколько доступно в данный момент (но не более n байт)
M 0 0 Вернуть не более n байт только тогда, когда доступны, по меньшей мере, M байт
0 T 0 Вернуть не более n байт только тогда, когда доступен хотя бы один байт либо истекло T x .1 секунд.
M T 0 Вернуть не более n байт только тогда, либо когда будут доступны M байт, либо будет принят хотя бы один байт и интервал между любыми последовательно принятыми символами превысил T x .1 секунд.
0 0 t Зарезервировано.
M 0 t Вернуть не более n байт только тогда, когда доступны M байт либо истекло t x .1 секунд.
0 T t Зарезервировано.
M T t Вернуть не более n байт только тогда, когда доступны M байт, либо истекло t x .1 секунд и не был получен ни один символ, либо был принят хотя бы один байт и интервал между любыми последовательно принятыми символами превысил T x .1 секунд.

Драйверы устройств

На рисунке показана типичная подсистема устройств в QNX.

Менеджер устройств (Dev) организует обмен данными между устройствами и прикладными программами. Аппаратный интерфейс управляется индивидуальными процессами драйверами. Dev, для каждого из устройств, обменивается данными с драйверами через очереди в разделяемой памяти.


Использование разделяемой памяти требует, чтобы Dev и драйверы находились на одном и том же физическом компьютере, преимуществом же является повышенная производительность.

Для каждого терминального устройства используются три очереди. Каждая очередь реализована на основе механизма "первый вошел - первый вышел". Каждой очереди также соответствует своя управляющая структура.

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

Dev помещает выводимые данные в очередь вывода; данные извлекаются драйвером по мере того, как символы физически передаются устройству. Dev вызывает проверенную процедуру внутри драйвера каждый раз, когда добавляются новые данные, таким образом он "подталкивает" драйвер к работе (в случае, если он не был занят). Благодаря использованию очередей вывода Dev реализует буферизованную запись (write-behind) для всех терминальных устройств. Только когда буферы вывода заполнены, Dev вызывает блокирование процесса при записи.

Редактируемая очередь полностью управляется Dev и используется при вводе данных в редактируемом режиме. Размер этой очереди определяет максимальный размер строки редактируемого ввода для конкретного устройства.

Размеры всех этих очередей могут конфигурироваться системным администратором; единственное ограничение состоит в том, что общий суммарный размер всех трех очередей не может превышать 64K. Значений по умолчанию обычно более чем достаточно для большинства аппаратных конфигураций, но вы можете "настраивать" их, либо для уменьшения общей потребности системы в памяти, либо в случае нестандартных аппаратных конфигураций.

Управление устройствами

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

Чтобы обеспечить хорошую реакцию на входные события, Dev должен выполняться с достаточно высоким приоритетом. Dev обычно мало загружен работой, поэтому он редко снижает общую производительность системы. Сами драйверы, как и любые другие процессы в QNX, могут выполняться с различными приоритетами в зависимости от характера обслуживаемых устройств.

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

Управление устройствами на низком уровне выполняется через дальний вызов входной точки ioctl внутри каждого драйвера. Общий набор ioctl команд поддерживается непосредственно Dev. Специфические для устройства ioctl команды могут быть посланы QNX процессами драйверу через функцию Си qnx_ioctl().

Консоль QNX

Системные консоли поддерживаются драйвером Dev.con. Экран, адаптер дисплея и системная клавиатура - вместе называются консолью.

QNX позволяет параллельное выполнение множества сессий на консолях посредством виртуальных консолей. Драйвер Dev.con обычно поддерживает более одного набора очередей ввода/вывода к Dev, которые доступны пользовательским процессам как множество терминальных устройств с именами вида /dev/con1, /dev/con2 и т.д. С точки зрения приложения, это "настоящие" доступные консоли.

Конечно, существует только один физический экран и клавиатура, и поэтому только одна из этих виртуальных консолей действительно показывается в каждый момент времени. Клавиатура "подключена" к той виртуальной консоли, которая видима в текущий момент.

Функции, специфичные для консоли

В дополнение к реализации стандартного терминала QNX (описан в Руководстве пользователя), драйвер консоли также обеспечивает набор специфических для консоли функций, которые позволяют приложениям непосредственно взаимодействовать с драйвером консоли путем обмена сообщениями. Связь устанавливается вызовом функции Си console_open(). После того как связь установлена, процесс имеет доступ к следующим возможностям:

Процесс может:Через функцию Си:
Читать непосредственно с экрана консоли console_read()
Писать непосредственно на экран консоли console_write()
Получать асинхронное извещение о важных событиях (например, изменение положения курсора, размера дисплея, переключение консоли и т.д.) console_arm()
Управлять размерами консоли console_size()
Переключать видимую консоль console_active()

Драйвер консоли QNX выполняется как нормальный процесс QNX. Вводимые с клавиатуры символы помещаются обработчиком прерывания клавиатуры непосредственно в очередь ввода. Выводимые данные отображаются Dev.con в то время, когда он выполняется как процесс.

Последовательные устройства

Последовательные каналы связи обслуживаются драйвером Dev.ser. Этот драйвер может обслуживать более одного физического канала; он обеспечивает терминальные устройства с именами вида /dev/ser1, /dev/ser2 и т.д.

При запуске Dev.ser вы можете задать аргументы командной строки, которые определяют, какие - и сколько - последовательные порты установлены. Чтобы увидеть доступные последовательные порты, используйте утилиту ls:

ls /dev/ser*

Dev.ser является примером управляемого прерываниями сервера ввода/вывода. После инициализации оборудования сам процесс переходит в состояние ожидания ("засыпает"). Прерывания помещают входные данные непосредственно в очередь ввода. Первый выводимый символ передается устройству, когда Dev "подталкивает" драйвер. Последующие символы передаются при обработке соответствующего прерывания.

Параллельные устройства

Параллельные порты принтера обслуживаются драйвером Dev.par. При запуске Dev.par вы можете задать аргумент командной строки, который определяет, какой последовательный порт установлен. Чтобы увидеть, доступен ли последовательный порт, используйте утилиту ls:

ls /dev/par*

Dev.par является только выводящим драйвером, поэтому у него нет очередей ввода. Вы можете конфигурировать размер буфера вывода с помощью аргументов командной строки при запуске Dev.par. Буфер вывода может быть сделан очень большим, если вы хотите обеспечить программный буфер печати.

Dev.par является примером сервера ввода/вывода, не использующим прерывания. Этот процесс нормально находится в состоянии RECEIVE-блокирован, ожидая появления данных в очереди вывода и "толчка" от Dev. Когда доступны данные для вывода на печать, Dev.par выполняется в цикле работа-ожидание (с относительно низким адаптивным приоритетом), ожидая, когда символы будут приняты принтером. Такой низкоприоритетный цикл работа-ожидание не влияет на общую производительность системы и, в то же время, достигает максимально возможную пропускную способность к параллельному устройству.

Производительность подсистемы устройств

Поток событий внутри подсистемы устройств сконструирован так, чтобы минимизировать избыточность и достичь максимальной пропускной способности, когда устройство работает в сыром режиме. С этой целью используются следующие правила:

  • Обработчики прерываний помещают принятые данные непосредственно в очереди в памяти. Только при наличии ждущего запроса на чтение и при условии, что этот запрос может быть удовлетворен, обработчик прерывания инициирует выполнение Dev. Во всех остальных случаях выполняется просто возврат из прерывания. Более того, если Dev уже выполняется, то никакой диспетчеризации не производится.
  • Когда запрос на чтение удовлетворен, Dev копирует данные в приложение непосредственно из буфера сырого ввода. Как результат, данные копируются только один раз.

Эти правила - в сочетании с исключительно маленькими задержками прерывания и диспетчеризации в QNX - обеспечивают очень эффективную модель ввода.

Рассказать друзьям:

     Рейтинг@Mail.ru