Каталог | Индекс раздела |
Назад | Оглавление | Вперед |
Администратор устройств (Dev) обеспечивает интерфейс между процессами и периферийными устройствами. Имена периферийных устройств принадлежат пространству имен ввода/вывода и начинаются с префикса /dev. Например, консоль в системе QNX имеет имя /dev/con1.
Программы QNX получают доступ к периферийным устройствам с помощью стандартных функций read(), write(), open() и close(). Для процесса QNX периферийное устройство представляется двунаправленным потоком байтов, который может считываться или записываться процессом.
Администратор устройств регулирует прохождение потока между приложением и устройством. Частичная обработка этих данных выполняется администратором Dev в соответствии с параметрами, заданными в структуре управления периферийными устройствами (termios), которая существует для каждого устройства. Пользователи могут просмотреть и/или изменить эти параметры, используя утилиту stty; в программе для этой цели используются функции tcgetattr() и tcsetattr().
Параметры tеrmios управляют функционированием устройств на низшем уровне, в частности они задают:
Кроме того, Администратор устройств реализует ряд дополнительных функций, с помощью которых процессы могут управлять периферийными устройствами.
В приведенной ниже таблице представлены некоторые из этих функций.
6.2. Работа с устройствами
Процесс может | Посредством функции Си |
Выполнять синхронизированные операции чтения | dev_read() или read() + tcsetattr() |
Асинхронно оповестить процесс о доступности данных на одном или нескольких устройств ввода | dev_arm() |
Ожидать полного завершения передачи выходных данных | tcdrain() |
Послать прерывание по каналу связи | tcsendbreak() |
Отсоединить коммуникационный канал | tcdropline() |
Ввести данные | dev_insert_chars() |
Выполнить неблокирующее чтение или запись (режим O_NONBLOCK) | open() и fcntl() |
Наиболее важным режимом работы с устройствами управляет бит ICANON управляющей структуры termios. Если этот управляющий бит установлен, то Администратор устройств выполняет функции строчного редактирования принимаемых символов. Таким образом, данные будут доступны для обработки прикладным процессам только при вводе строки, что обычно определяется поступлением кода символа "возврат каретки" (CR). Этот режим работы называется режимом редактируемого ввода, каноническим или, иногда, "cooked".
Большинство неполноэкранных приложений работают в режиме редактируемого ввода. Интерпретатор Shell является типичным примером.
В следующей таблице представлены некоторые специальные управляющие символы, которые могут быть заданы в управляющей структуре termios для того, чтобы указать Администратору Dev, каким образом выполнять редактирование.
Dev будет выполнять | При получении |
Перемещение курсора на один символ влево | LEFT |
Перемещение курсора на один символ вправо | RIGHT |
Перемещение курсора в начало строки | HOME |
Перемещение курсора в конец строки | END |
Стирание символа слева от курсора | ERASE |
Удаление символа в текущей позиции курсора | DEL |
Стирание всей вводимой строки | KILL |
Стирание текущей строки и переход к предыдущей строке | UP |
Стирание текущей строки и переход к следующей строке | DOWN |
Переключение между режимами вставки и наложения (каждая новая строка начинает вводиться в режиме наложения) |
INS |
stty term=vt100 </dev/ser1
И наоборот, если вы подключили к последовательному порту модем, который в свою очередь соединен с другим компьютером, загруженным системой QNX, в которой выполняется утилита qtalk, то установку клавиш редактирования строки следует выполнить следующим образом
stty term=qnx </dev/ser1
Если бит ICANON не установлен, то говорят, что устройство находится в режиме нередактируемого ввода (raw). В этом режиме входное редактирование не выполняется, и все поступающие данные становятся немедленно доступными процессу QNX.
Примерами приложений QNX, работающими с устройствами в этом режиме, являются полноэкранные и последовательные коммуникационные программы.
При считывании данных из устройства в режиме нередактируемого ввода приложение может задать условия обработки входного запроса. Критерий доступа к вводимым нередактируемым данным определяется двумя элементами управляющей структуры termios: MIN и TIME.
Приложение может уточнить режим доступа к вводимым данным при выдаче запроса на чтение посредством функции dev_read(). Уточнение, задаваемое параметром TIMEOUT, обычно используется в протоколах записи, либо в приложениях реального времени. Обратите внимание на то, что для функции read() значение TIMEOUT всегда равно 0.
При выдаче процессом QNX запроса на чтение n байтов эти три параметра определяют, когда данный запрос должен быть выполнен, что приведено в следующей таблице.
MIN | TIME | TIMEOUT | Описание |
0 | 0 | 0 | Возвратить управление немедленно, считав столько байтов, сколько доступно в данный момент (до n байтов) |
М | 0 | 0 | Возвратить управление, считав до n байтов, только в том случае, если доступно по крайней мере M байтов |
0 | T | 0 | Возвратить управление, считав до n байтов, если доступен хотя бы один байт, либо если истекло T*0.1 секунд |
M | T | 0 | Возвратить управление, считав до n байтов, в том случае, если либо доступно не менее M байтов, либо если считан хотя бы один байт и интервал времени между последовательно считанными двумя любыми символами превысил T*0.1 секунд |
0 | 0 | t | Зарезервировано |
M | 0 | t | Возвратить управление, считав до n байтов по истечении t*0.1 секунд, либо в случае доступности не менее M байтов |
0 | T | t | Зарезервировано |
M | T | t | Возвратить управление, считав до n байтов в случае доступности не менее M байтов, либо по истечении t*0.1 секунд после получения последнего символа, либо при получении хотя бы одного байта и превышении интервала времени между двумя последовательными считываниями символов T*0.1 секунд |
На рис. 25 представлена типичная подсистема устройств QNX.
![]() |
Рис. 25 |
Администратор устройств (Dev) управляет потоками данных между прикладными процессами QNX. Аппаратным интерфейсом управляют специализированные драйверы. Данные, которыми обменивается администратор Dev и драйверы, проходят через наборы очередей в совместно используемой памяти, которые существуют для каждого периферийного устройства.
Каждое устройство имеет три очереди. Каждая из очередей организована по принципу "первым пришел - первым обслужен". С каждой очередью связана управляющая структура.
Принятые данные помещаются драйвером во входную очередь и передаются администратором Dev только тогда, когда прикладной процесс запросит данные. Обработчики прерываний, входящие в состав драйверов, обычно обращаются к библиотечной подпрограмме администратора Dev для добавления данных в очередь: это обеспечивает последовательную входную дисциплину и значительно сокращает количество возлагаемых на драйвер функций.
Dev помещает выходные данные в выходную очередь, затем драйвер обеспечивает физическую передачу данных устройству. Каждый раз при добавлении данных Dev вызывает подпрограмму, входящую в состав драйвера, и активизирует драйвер в том случае, если он не был еще запущен. Благодаря использованию выходных очередей, Dev обеспечивает запись данных для всех периферийных устройств. Процесс блокируется при записи только в случае переполнения выходных буферов.
Каноническая очередь полностью управляется Администратором Dev и используется при обработке входных данных в режиме редактируемого ввода. Размер этой очереди определяется максимальным размером входной редактируемой строки для каждого конкретного устройства.
Размер всех этих очередей устанавливается системным администратором; при этом единственным ограничением является то, что суммарный размер всех трех очередей не может превысить 64 Кбайта. Значения, используемые по умолчанию, обычно больше требуемых для реальных устройств, но их можно настроить для того, чтобы уменьшить размер выделяемой системной памяти или иметь возможность работать в нештатных режимах.
Драйверы устройств либо записывают принятые данные во входную очередь, либо получают данные из выходной очереди. Администратор Dev определяет, в каком случае требуется завершить передачу, требуется ли отображение вводимых данных на дисплее и т.д.
Для обеспечения высокой степени реактивности Администратор Dev должен выполняться с достаточно высоким приоритетом. Обычно администратору Dev не приходится сильно загружать процессор, поэтому он незначительно влияет на общую производительность системы.
Драйверы, подобно любым другим процессам QNX, могут выполняться с различными приоритетами в зависимости от особенностей обслуживаемых ими технических средств.
Управление устройствами на низшем уровне реализовано посредством вызова соответствующего драйвера по входу ioctl. Общий набор ioctl-команд поддерживается большинством драйверов, используемых непосредственно Администратором Dev. Кроме того, процессы QNX могут через Dev выдавать драйверам ioctl-команды, ориентированные на устройства (посредством функции Си qnx_ioctl()).
Системными консолями управляет процесс Dev.con. Консоль - это совокупность видеоадаптера, монитора и системной клавиатуры.
В системе QNX имеется возможность организации параллельной работы посредством виртуальных консолей. Драйвер консоли Dev.con обычно выполняет обработку нескольких наборов очередей ввода/вывода к Администратору Dev, что позволяет процессам пользователя иметь набор периферийных устройств с именами /dev/con1, /dev/con2 и т.д. С точки зрения приложения одновременно используется несколько консолей.
Конечно, в действительности, имеется только один физический монитор и клавиатура, поэтому в данный момент времени задействована только одна из виртуальных консолей. Клавиатура "подсоединена" к той виртуальной консоли, которая в этот момент видима.
Помимо стандартных терминальных функций QNX (см. Руководство пользователя) драйвер консоли работает со специфическими для консоли функциями, которые позволяют прикладным процессам взаимодействовать с драйвером консоли напрямую посредством сообщений. Связь устанавливается функцией Си console_open(). После установления связи процесс QNX имеет следующие возможности.
6.5.1. Управление устройствами
6.6. Консоль QNX
6.6.1. Специфические для консоли функции
Процесс может | Посредством функции Си |
Считывать данные непосредственно с экрана консоли | console_read() |
Выводить данные непосредственно на экран консоли | console_write() |
Быть асинхронно оповещенным о наступлении определенных событий (изменение отображаемых данных, перемещение курсора, изменение отображаемых размеров, смена видимой консоли и т.д.) | console_arm() |
Управлять размером консоли | console_size() |
Переключить видимую консоль | console_active() |
Драйвер консоли QNX выполняется как обычный процесс. Вводимые с клавиатуры данные преобразуются обработчиком прерываний клавиатуры и помещаются непосредственно во входную очередь. Выходные данные принимает и отображает драйвер Dev.con, пока он существует в качестве процесса.
Последовательными коммуникационными каналами управляет процесс Dev.ser. Этот драйвер может управлять несколькими физическими каналами, работая с периферийными устройствами, которые имеют имена /dev/ser1, dev/ser2 и т.д.
При запуске Dev.ser в командной строке можно задать аргументы, которые определяют типы и количество установленных последовательных портов. Для того, чтобы узнать, какие последовательные порты доступны, используйте утилиту ls
Dev.ser служит примером сервера ввода/вывода, управляемого только прерываниями. После инициализации аппаратного обеспечения процесс переходит в режим ожидания. Принимаемые прерывания помещают входные данные непосредственно во входную очередь. Первый выводимый символ передается через канал физическому устройству после запуска драйвера Администратором Dev. Последовательные символы передаются при поступлении соответствующих прерываний.
Параллельными портами принтера управляет драйвер Dev.par. При запуске Dev.par в командной строке задается аргумент, определяющий, какой параллельный порт установлен. Для того, чтобы узнать, доступен ли параллельный порт, используйте утилиту ls
Dev.par - это драйвер вывода, поэтому у него нет входных или канонических входных очередей. При запуске Dev.par размер выходного буфера задается с помощью аргументов командной строки. Можно создать выходной буфер очень большого размера, например, в случае создания программного буфера печати.
Dev.par является примером управляемого полностью без прерываний сервера ввода/вывода. Обычно этот процесс находится в RECEIVE-блокированном состоянии, ожидая появления данных в своей выходной очереди, и запускается администратором Dev. Когда данные становятся доступными для печати, Dev.par начинает выполняться в цикле активного ожидания (с относительно низким адаптивным приоритетом), ожидая приема данных принтером. Такой низкоприоритетный цикл активного ожидания не влияет на общую производительность системы, а в среднем обеспечивает максимально возможную пропускную способность для устройства с параллельным интерфейсом.
Управление потоком событий в подсистеме периферийных устройств организовано таким образом, что минимизируются накладные расходы и максимизируется пропускная способность для устройств, находящихся в нередактируемом (raw) режиме. Это достигается следующим образом:
Таким образом, в основе изящной модели ввода/вывода системы QNX лежит описанный выше механизм управления потоком событий в подсистеме периферийных устройств, а также присущие системе очень малые времена задержек прерываний и планирования.
6.7. Устройства с последовательным интерфейсом
ls /dev/ser*
6.8. Устройства с параллельным интерфейсом
ls /dev/par*
6.9. Производительность подсистемы периферийных устройств
Назад | Оглавление | Вперед |
Каталог | Индекс раздела |