- •Введение
- •Подсистема ввода-вывода: общие принципы построения и работы
- •1.1. Взаимодействие процессора с внешними устройствами
- •1.2. Прямой доступ к памяти
- •Драйверы
- •Роль драйверов в операционной системе
- •Взаимодействие драйверов с компонентами операционной системы и пользовательскими программами
- •Стек обработки запросов ввода-вывода
- •Основы организации и работы подсистемы ввода-вывода unix
- •2.1. Драйверы в операционных системах семейства unix
- •Стратегическая функция драйвера блочного устройства
- •Функция обработки прерывания
- •Функция опроса устройства
- •Другие функции драйверов
- •Буферизация в символьных драйверах
- •Терминальный драйвер
- •2.2. Потоковая подсистема ввода-вывода в unix
- •Архитектура и принципы работы подсистемы streams
- •Архитектура и работа модулей потока
- •Функция модуля put
- •Функция модуля service
- •Структура сообщения
- •Основы организации и работы подсистемы ввода-вывода windows
- •3.1. Классификаций драйверов Windows
- •Драйверы пользовательского режима
- •Драйверы режима ядра
- •3.2. Объекты подсистемы ввода-вывода
- •Объект файл
- •Объект устройство
- •Объект драйвер
- •Объект пакет запроса ввода-вывода
- •Объект блок стека запросов ввода-вывода
- •3.3. Передача данных между пользовательским адресным пространством и пространством ядра
- •Буферизированный ввод-вывод
- •Прямой ввод-вывод
- •Ввод-вывод под управлением драйвера
- •3.4. Обработка запросов ввода-вывода
- •Прохождение запроса ввода-вывода вниз через стек обработки запросов ввода-вывода
- •Обработка прерывания по завершению ввода-вывода
- •Обратное прохождение запроса ввода-вывода вверх через стек запросов ввода-вывода
- •3.5. Буферизация запросов ввода-вывода
- •Системная очередь запросов
- •Очереди запросов под управлением драйвера
- •3.6. Диспетчер Plug-And-Play, установка и запуск драйверов
- •3.7. Диспетчер электропитания
- •3.8. Среда сетевых драйверов ndis
- •Драйверы среды ndis Минипорт-драйверы сетевых адаптеров
- •Драйверы протоколов
- •Промежуточные драйверы
- •Структура ndis пакета
- •Запросы к сетевым адаптерам
- •3.9. Порты завершения ввода-вывода
- •Заключение
- •Библиографический список
- •Оглавление
- •394026 Воронеж, Московский просп., 14
Буферизация в символьных драйверах
Символьные устройства ориентированы на побайтную передачу данных, при этом для выполнения каждого запроса на ввод-вывод байта требуется определенное время.
Если программа инициирует запросы ввода-вывода быстрее, чем устройство может их обслужить, процесс, исполняющий такую программу, будет приостанавливаться после каждого запроса ввода-вывода и скорость его выполнения существенно замедлится.
Часто процессы генерируют запросы ввода-вывода пакетами по несколько запросов, как показано на рис. .5.
Рис.5. Группировка запросов ввода-вывода
При этом средняя интенсивность запросов (среднее количество запросов в единицу времени) может быть небольшой, меньше чем средняя пропускная способность устройства, но при передаче пакета частых запросов процесс все равно должен будет блокироваться после каждого запроса.
Повысить производительность системы в такой ситуации может буферизация, как показано на рис. .6.
Рис.6. Буферизация запросов ввода-вывода
В UNIX не предусмотрен общесистемный механизм буферизации для символьных устройств, подобный системному кэшу для блочных устройств, но буферизация может при необходимости выполняться на уровне драйвера.
Основная проблема состоит в том, как организовать буферную память при априорно неизвестном объеме буферизированных данных. Если в этих условиях использовать в качестве буферной памяти циркулярный буфер, то угадать его оптимальный размер будет почти невозможно, и либо буферизация будет неэффективной из-за слишком малого объема буфера, либо потери памяти будут слишком велики. Поэтому нужно найти такую организацию буферной памяти, которая позволила бы динамически изменять размер буфера с минимальными накладными расходами.
В UNIX системах символьным драйверам предоставляется стандартный механизм буферизации, основанный на структурах clist и cblock.
Структура clist является заголовком буфера и определена следующим образом.
struct clist { // число символов в буфере int c_cc; // указатель на первый блок символов struct cblock* c_cf; // указатель на последний блок символов struct cblock* c_cl; };
Экземпляры структуры cblock образуют связанный список блоков данных, каждый из которых может хранить группу символов.
Структура cblock определена следующим образом
struct cblock { // указатель на следующий блок данных struct cblock* c_next; // данные блока char c_data[CBSIZE]; };
Таким образом, используется структура буфера, показанная на рис. 7.
Рисунок 7. Структура буфера символьного драйвера
Если объем буферизированных данных растет, выделяются новые блоки cblock, при сокращении объема данных – высвобождающиеся блоки возвращаются системе.
Драйвер может создать экземпляр структуры clist, инициализировать его нулями и использовать системную поддержку символьной буферизации. Ядро предоставляет функции для работы с буфером, например putc(char, clist*) для записи символа в буфер или int getc(clist*) для чтения символа. При этом драйверу не надо заботиться о выделении или освобождении блоков, все эти операции автоматически выполняются ядром при добавлении удалении символов.