- •Введение
- •Подсистема ввода-вывода: общие принципы построения и работы
- •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
Функция модуля service
Функция service периодически вызывается ядром операционной системой для обслуживания очередей, содержащих отложенные сообщения. Единственное действие, которое выполняет функция service, состоит в том, чтобы попытаться передать сообщение из очереди следующему модулю. Функция service последовательно передает сообщения из очереди, пока очередь сообщений не будет исчерпана, или пока следующий модуль не откажется принимать новые сообщения. После этого функция service завершается.
Алгоритм работы функции service показан на рис. .12.
Рис.12 Алгоритм работы функции service.
Структура сообщения
Данные между модулями потока передаются посредством сообщений. Когда процесс передает данные устройству с помощью системного вызова write или putmsg, ядро системы формирует сообщение, которое последовательно передается от модуля к модулю, вплоть до драйвера. При этом каждый модуль может изменять, наращивать или сокращать сообщение, в соответствии с логикой своей работы.
Получив данные от устройства, потоковый драйвер также формирует сообщение, которое аналогичным образом направляется вверх по потоку.
Помимо сообщений, связанных с передачей данных, модули могут генерировать и передавать другим модулям или устройству управляющие сообщения.
Сообщения могут буферизироваться в очередях модулей. Сообщения в очередях описываются двумя структурами данных: msgb – заголовок сообщения и datab – заголовок блока данных.
Структура заголовка сообщения определена следующим образом:
struct msgb { // указатель на следующее сообщение в очереди struct msgb* b_next; // указатель на предыдущее сообщение в очереди struct msgb* b_prev; // указатель на связанное сообщение struct msgb* b_cont; // первая позиция для чтения из буфера сообщения unsigned char* b_rptr; // первая позиция для записи в буфер сообщения unsigned char* b_wptr; // указатель на описатель буфера сообщения struct datab* b_datap; };
Данные сообщения хранятся отдельно от заголовка, в системной части адресного пространства. Для размещения данных каждого сообщения выделяется область памяти, описываемая структурой datab, определенной следующим образом.
struct datab { // адрес начала буфера unsigned char* db_base; // адрес первого байта за концом буфера unsigned char* db_lim; // счетчик ссылок на блок данных unsigned char db_ref; // тип сообщения unsigned char db_type; };
На один и тот же блок данных могут ссылаться различные сообщения. Поле db_ref структуры datab подсчитывает, сколько заголовков сообщения ссылаются на данный блок сообщения.
Сообщения связываются в двусвязный список через поля b_next, b_prev структуры msgb, как показано на рис. .13.
Рис.13. Общая структура списка сообщений
Сообщение последовательно проходит через модули потока, при этом может меняться объем данных сообщения, например, исходные пользовательские данные могут дополняться заголовками и управляющими данными, в соответствии с принятым сетевым протоколом. Ядро системы, выделяя буфер для данных сообщения, не знает алгоритмов работы модулей потока и не может учесть наращивание объема данных в ходе обработки, поэтому объем буфера данных, связанного с исходным сообщением, может быть недостаточен.
Поэтому необходим универсальный механизм, позволяющий связать с сообщением дополнительный объем данных. Заметим, что нельзя рассчитывать на возможность увеличения объема выделенной памяти за счет простого смещения конца буфера (за счет модификации поля db_lim в заголовке блока данных), т.к. неизвестно, как выполнялось распределения памяти и есть ли свободное место за текущим буфером.
Увеличение размера области данных сообщения выполняется при необходимости за счет создания нового сообщения, связанного с существующим сообщением через поле b_cont структуры msgb. Новое сообщение ссылается на новый заголовок блока данных, который адресует новый блок данных, как показано на рис. .13.