С какими компонентами операционной системы взаимодействует драйвер

Обновлено: 22.06.2024

Windows представляет собой операционную систему с гибридным ядром (см. лекцию 1 "Введение в операционные системы"). В ней основные системные функции по управлению процессами, памятью, устройствами, файловой системой и безопасностью реализованы в компонентах, работающих в режиме ядра; но существует ряд важных системных компонентов пользовательского режима, например системные процессы входа в систему, локальной аутентификации, диспетчера сеансов, а также подсистемы окружения.

Архитектура Windows представлена на рис.4.1 [5; 2].

Архитектура Windows

Компоненты пользовательского режима

В пользовательском режиме работают следующие виды процессов:

  • системные процессы (system processes) – компоненты Windows, отвечающие за решение критически важных системных задач (т. е. аварийное завершение одного из этих процессов вызывает крах или нестабильную работу всей системы), но выполняемые в пользовательском режиме. Основные системные процессы:
    • Winlogon.exe – процесс входа в систему и выхода из неё;
    • Smss.exe (Session Manager – диспетчер сеансов) – процесс выполняет важные операции при инициализации системы (загрузка необходимых DLL, запуск процессов Winlogon и Csrss и др.), а затем контролирует работу Winlogon и Csrss;
    • Lsass.exe (Local Security Authentication Subsystem Server – сервер подсистемы локальной аутентификации) – процесс проверяет правильность введенных имени пользователя и пароля;
    • Wininit.exe – процесс инициализации системы (например, запускает процессы Lsass и Services);
    • Userinit.exe – процесс инициализации пользовательской среды (например, запускает системную оболочку – по умолчанию, Explorer.exe);
    • Services.exe (SCM, Service Control Manager – диспетчер управления службами) – процесс, отвечающий за выполнение служб – см. ниже;
    • собственно Windows – при помощи данной подсистемы выполняются 32 разрядные приложения Windows (Win32), а также 16 разрядные приложения Windows (Win16), приложения MS DOS и консольные приложения (Console). За подсистему Windows отвечает системный процесс Csrss.exe и драйвер режима ядра Win32k.sys;
    • POSIX (Portable Operating System Interface for UNIX – переносимый интерфейс операционных систем UNIX) – подсистема для UNIX-приложений. Начиная с Windows Server 2003 R2 компонент, реализующий эту подсистему, называется SUA (Subsystem for UNIX-based Applications). Компонент не устанавливается в Windows по умолчанию.

    Все перечисленные процессы пользовательского режима (кроме подсистемы POSIX 1 Подсистема POSIX использует библиотеку Psxdll.dll. ) для взаимодействия с модулями режима ядра используют библиотеки Windows DLL ( Dynamic Link Library – динамически подключаемая библиотека). Каждая DLL экспортирует набор Windows API функций, которые может вызывать процесс.

    Windows API ( Windows Application Programming Interface , WinAPI) – это способ взаимодействия процессов пользовательского режима с модулями режима ядра. WinAPI включает тысячи функций и хорошо документирован [10].

    Основные Windows DLL следующие:

    • Kernel32.dll – базовые функции, в том числе работа с процессами и потоками, управление памятью и вводом выводом;
    • Advapi32.dll – функции, в основном связанные с управлением безопасностью и доступом к реестру;
    • User32.dll – функции, отвечающие за управление окнами и их элементами в GUI приложениях (Graphical User Interface – графический интерфейс пользователя);
    • Gdi32.dll – функции графического пользовательского интерфейса (Graphics Device Interface, GDI), обеспечивающие рисование на дисплее и принтере графических примитивов и вывод текста.

    Библиотека Ntdll. dll экспортирует в большинстве своем недокументированные системные функции, реализованные, в основном, в Ntoskrnl.exe. Набор таких функций называется Native API ("родной" API ).

    Библиотеки Windows DLL преобразуют вызовы документированных WinAPI функций в вызовы функций Native API и переключают процессор на режим ядра.

    Компоненты режима ядра

    Диспетчер системных сервисов ( System Service Dispatcher ) работает в режиме ядра, перехватывает вызовы функций от Ntdll. dll , проверяет их параметры и вызывает соответствующие функции из Ntoskrnl.exe.

    Исполнительная система и ядро содержатся в Ntoskrnl.exe (NT Operating System Kernel – ядро операционной системы NT) (по поводу использования термина " ядро " в Windows см. лекцию 1 "Введение в операционные системы").

    Исполнительная система ( Executive ) представляет собой совокупность компонентов (называемых диспетчерами – manager ), которые реализуют основные задачи операционной системы:

    • диспетчер процессов (process manager) – управление процессами и потоками (см. лекцию 6 "Процессы и потоки");
    • диспетчер памяти (memory manager) – управление виртуальной памятью и отображение её на физическую (см. лекцию 8 "Управление памятью");
    • монитор контроля безопасности (security reference monitor) – управление безопасностью (см. лекцию 9 "Безопасность");
    • диспетчер ввода вывода (I/O manager), диспетчер кэша (cache Manager), диспетчер Plug and Play (PnP Manager) – управление внешними устройствами и файловыми системами (см. лекцию 10 "Управление устройствами" и лекцию 11 "Файловая система NTFS");
    • диспетчер электропитания (power manager) – управление электропитанием и энергопотреблением;
    • диспетчер объектов (object manager), диспетчер конфигурации (configuration manager), механизм вызова локальных процедур (local procedure call) – управление служебными процедурами и структурами данных, которые необходимы остальным компонентам.

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

    Компонент Windows USER и GDI отвечает за пользовательский графический интерфейс (окна, элементы управления в окнах – меню , кнопки и т. п., рисование), является частью подсистемы Windows и реализован в драйвере Win32k.sys.

    Взаимодействие диспетчера ввода вывода с устройствами обеспечивают драйверы (drivers) – программные модули, работающие в режиме ядра, обладающие максимально полной информацией о конкретном устройстве (драйверы подробнее рассматриваются в лекции 10 "Управление устройствами").

    Однако, и драйверы, и ядро не взаимодействуют с физическими устройствами напрямую – посредником между программными компонентами режима ядра и аппаратурой является HAL ( Hardware Abstraction Layer ) – уровень абстрагирования от оборудования, реализованный в Hal . dll . HAL позволяет скрыть от всех программных компонентов особенности аппаратной платформы (например, различия между материнскими платами), на которой установлена операционная система .

    Резюме

    В лекции представлена архитектура операционной системы Windows и описаны основные компоненты пользовательского режима и режима ядра.

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

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

    Содержание

    Драйвер и операционная система


    (Рис. 1) Логическое позиционирование драйверов устройств

    Чтобы получить доступ к аппаратной части устройства, то есть к регистрам контроллера, драйвер устройства, как правило, должен быть частью ядра операционной системы, по крайней мере в существующих на сегодняшний день архитектурах. Но вообще-то можно создавать и драйверы, работающие в пространстве пользователя, используя при этом системные вызовы для чтения и записи регистров устройств. Такое решение позволит изолировать ядро от драйверов и драйверы друг от друга, устранив при этом основной источник системных сбоев — «сырые» драйверы, тем или иным образом мешающие работе ядра. Несомненно, это хороший выход из положения при создании высоконадежных систем.

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

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

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

    С наступлением эры персональных компьютеров с несметным количеством устройств ввода-вывода эта модель уже не работает. Лишь немногие пользователи способны перекомпилировать или перекомпоновать ядро, даже если у них будут исходные коды или объектные модули, что случается довольно редко. Вместо этого операционные системы, начиная с MS-DOS, перешли к модели, в которой драйверы стали динамически загружаться в систему в процессе работы. Управление загрузкой драйверов ведется в разных системах по-разному.

    Алгоритм работы

    Затем драйвер может проверить, используется ли устройство в данный момент. Если оно используется, запрос будет поставлен в очередь для последующей обработки. Если устройство простаивает, проверяется состояние аппаратуры, чтобы определить, может ли запрос быть обработан. Перед началом передачи данных может понадобиться включить устройство или запустить его двигатель. Как только устройство включится и будет готово к работе, им можно будет управлять.

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

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

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

    Функции программного обеспечения, не зависящего от конкретных устройств

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

    Предоставление унифицированного интерфейса для драйверов устройств


    Одной из острых проблем при создании операционных систем является придание всем устройствам и драйверам ввода-вывода более или менее однообразного вида.

    Один из аспектов этой проблемы — интерфейс между драйверами устройств и остальной операционной системой. На рис. 2 (а) показана ситуация, в которой у каждого драйвера устройства имеется собственный интерфейс с операционной системой. Это означает, что функции драйвера, доступные для вызова системой, различаются от драйвера к драйверу. Это может означать, что и функции ядра, в которых нуждается драйвер, различаются от драйвера к драйверу. Все вместе взятое это означает, что обеспечение интерфейса с каждым новым драйвером требует множества новых усилий по созданию программного кода.

    В противоположность этому на рис. 2 (б) показана другая конструкция, в которой у всех драйверов имеется одинаковый интерфейс. Теперь стало намного проще подключить новый драйвер, обеспечив его соответствие интерфейсу драйверов. Также это означает, что создатели драйверов знают, чего от них ожидают. Фактически не все устройства абсолютно одинаковы, но обычно приходится иметь дело лишь с небольшим количеством типов устройств, и даже они в целом практически одинаковы.

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

    Буферизация


    Буферизация по многим причинам также является актуальным вопросом как для блочных, так и для символьных устройств. Чтобы понять, в чем состоит одна из таких причин, рассмотрим процесс, которому необходимо прочитать данные, получаемые от ADSL-модема, который многие используют дома для связи с Интернетом. По одной из возможных стратегий работы с поступающими символами нужно заставить пользовательский процесс осуществить системный вызов READ и заблокироваться в ожидании одного символа. При этом прерывание возникает по случаю поступления каждого символа. Процедура обработки прерывания передает символ пользовательскому процессу и снимает с него блокировку. Поместив куда-нибудь символ, процесс переходит к чтению следующего символа и снова блокируется.

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

    В улучшенном варианте пользовательский процесс предоставляет буфер объемом N символов и выполняет чтение такого же количества символов. Процедура обработки прерывания помещает поступающие символы в этот буфер до тех пор, пока он не заполнится. Затем она возобновляет работу пользовательского процесса. Эта схема работает намного эффективнее предыдущей, но у нее есть один недостаток. Что получится, если буфер выйдет за границу страницы при поступлении очередного символа? Буфер будет зафиксирован в памяти, но если множество процессов начнет фиксировать страницы в памяти, то запас доступных страниц сократится и производительность резко снизится.

    Другой широко распространенной формой буферизации является использование кольцевого буфера. Он состоит из области памяти и двух указателей, один из которых указывает на следующее свободное слово, в которое можно поместить новые данные, а другой — на первое слово тех данных в буфере, которые еще не были из него выведены. Во многих случаях аппаратура по мере добавления данных (например, только что поступивших из сети) передвигает вперед первый указатель; операционная система, по мере того как она выводит из буфера и обрабатывает данные, перемещает вперед второй указатель. Оба указателя ходят по кругу, переходя обратно к нижним адресам буфера, как только достигнут его верхних адресов.

    Буферизация является широко используемой технологией, но у нее имеются и недостатки. Если данные будут подвергаться буферизации слишком часто, упадет производительность. Рассмотрим, к примеру, сеть, показанную на рис. 4. Здесь пользовательский процесс осуществляет системный вызов для записи данных по сети. Ядро копирует пакет данных в буфер ядра, позволяя пользовательскому процессу немедленно возобновить работу (шаг 1). Теперь пользовательская программа может использовать буфер повторно.


    Когда вызывается драйвер, он копирует пакет в контроллер для его последующего вывода (шаг 2). Причина, по которой он не осуществляет вывод в сеть непосредственно из памяти ядра, состоит в том, что как только будет запущена передача пакета, она должна продолжаться на постоянной скорости. Драйвер не может гарантировать, что он будет получать доступ к памяти на постоянной скорости, поскольку множество циклов обращения к шине могут отвлекать на себя каналы DMA и другие устройства ввода-вывода. Неудача при своевременном получении слова приведет к порче пакета. Эту проблему можно устранить за счет буферизации пакета внутри контроллера.

    После того как пакет будет скопирован во внутренний буфер контроллера, он копируется в сеть (шаг 3). Биты поступают получателю вскоре после их отправки, поэтому сразу же после отправки последнего бита этот бит поступает получателю, у которого пакет попадает в буфер контроллера. Затем пакет копируется в буфер ядра получателя (шаг 4). И наконец он копируется в буфер процесса получателя (шаг 5). Обычно после этого получатель посылает подтверждение. Когда отправитель получает подтверждение, он имеет возможность послать следующий пакет. Но при этом следует понимать, что операции копирования существенно снижают скорость передачи данных, поскольку шаги должны осуществляться последовательно.

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

    К одному из классов ошибок ввода-вывода относятся ошибки программирования. Они возникают в том случае, если процесс запрашивает что-нибудь невозможное, к примеру запись в устройство ввода информации или чтение из устройства вывода информации. Другие ошибки возникают при предоставлении неверного адреса буфера или указании неверного устройства. На такие ошибки следует весьма простая реакция: вызывающей программе отправляется код возникшей ошибки.

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

    Распределение и высвобождение выделенных устройств

    Некоторые устройства, в любой момент времени могут использоваться только одним процессом. Операционная система должна проверять запросы на использование и принимать их или отвергать в зависимости от доступности запрашиваемого устройства. Простой способ обработки этих запросов заключается в требовании к процессам непосредственно открывать специальные файлы для этих устройств с помощью системных вызовов OPEN. Если устройство недоступно, то системный вызов OPEN потерпит неудачу. Освобождение выделенного устройства происходит после его закрытия с помощью системного вызова CLOSE. Альтернативный подход заключается в использовании специальных механизмов для запроса и освобождения выделенных устройств. Попытка получить в свое распоряжение недоступное устройство приводит не к отказу, а к блокировке процесса, предпринявшего эту попытку. Заблокированные процессы помещаются в очередь. Рано или поздно запрашиваемое устройство станет доступным, и первому процессу из этой очереди будет позволено получить устройство и продолжить свою работу.

    Предоставление размера блока, не зависящего от конкретных устройств

    У разных дисков могут быть разные размеры секторов. Не зависимое от устройств программное обеспечение должно скрыть этот факт и предоставить расположенным выше уровням унифицированный размер блока, например, рассматривая несколько секторов в качестве одного логического блока. Таким образом, вышестоящие уровни будут работать только с абстрактными устройствами, использующими один и тот же размер логического блока, не зависящий от физического размера сектора. Аналогичным образом некоторые символьные устройства осуществляют побайтовую доставку данных, а другие устройства доставляют данные блоками более крупного размера. Эти различия также могут быть скрыты.

    Горячее подключение устройств

    Виртуальные драйверы

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

    Начнем с того, что в операционных системах Windows все физические устройства условно разделяются на две большие группы: поддерживающие технологию PnP или не поддерживаю щие ее. Соответственно, драйверы, поддерживающие технологию PnP, называют WDM драй верами, а драйверы, не поддерживающие эту технологию – NT драйверами. Это весьма упро щенный подход, но при первоначальном изучении данной темы этого достаточно. Оба типа драйверов в своей основе используют одни и те же функции, но WDM драйвер включает ряд дополнительных функций, позволяющих реализовать возможности технологии PnP (установ ка удаление без перезагрузки, управление энергопотреблением и т. д.). Кроме того, для уста новки и обновления WDM драйвера устройства используется стандартный мастер Windows, знакомый всем пользователям (рис. 7.4):


    Мастер обновления

    WDM драйвера устройства

    Для установки/обновления WDM драйвера требуется наличие INF–файла, в котором опи

    саны характеристики драйвера (имя файла, место установки, данные о производителе и т. д.).

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

    Основы функционирования драйверов

    Драйвер устройства операционной системы – это не обычная программа. Для пользова теля, привыкшего к разработке обычных приложений, технология разработки драйвера пока жется необычной. В драйвере нет точки входа в программу, как например, main в программе на языке C, хотя в момент начальной загрузки операционная система вызывает программу инициализации драйвера, известную под названием DriverEntry. Драйвер устройства можно представить как некий контейнер, в котором содержатся структуры данных и функции, что делает его в некотором смысле похожим на библиотеку динамической компоновки (dll). Обра щение к драйверу при выполнении операций с устройством – это обращение к одной из его функций.

    Это весьма упрощенное описание структуры драйвера, но оно дает представление о том, как работает драйвер устройства. Жизненный цикл функционирования драйвера устройства можно разделить (условно) на три этапа:

    2) выполнение операций по запросам операционной системы на ввод вывод данных

    (Менеджер ввода вывода);

    3) остановка и удаление из системы.

    Вначале драйвер устройства должен быть проинициализирован. Процесс инициализации в упрощенном виде показан на рис. 7.5:

    Схема инициализации драйвера устройства

    Драйвер устройства записан на диске в формате файла с расширением .sys. Для опера ционных систем Windows общепринято располагать файлы драйверов в катклоге windows\ system32\drivers, хотя это вовсе не обязательно. Сведения об установленных драйверах хра

    нятся в системном реестре Windows в ключе \registry\machine\system\currentcontrolset\ services. Исторически сложилось так, что записи о системных службах и драйверах хранятся в одном и том же разделе реестра (services). Помимо всего прочего записи содержат тип за пуска драйвера – по нему система определяет, когда нужно загружать драйвер. Здесь есть очень важный момент: при испытаниях работоспособности драйвера желательно не инициа лизировать драйвер в момент загрузки системы, иначе можно вообще не загрузиться, если в драйвере имеется какая либо ошибка.

    При инициализации драйвера операционная система загружает двоичный образ дискового

    файла в защищенную область памяти и передает управление функции DriverEntry. Основная задача этой функции – проинициализировать поля структур DriverObject и DeviceObject и выпол нить привязку устройства к пространству имен операционной системы, чтобы можно было обращаться к устройству из программы пользователя. Кроме этого, здесь же инициализиру ется массив указателей на функции вида IRP_MJ_XXX, где XXX обозначает операцию.

    Например, указатель IRP_MJ_CREATE может ссылаться на функцию, которая будет вызы

    ваться при создании (открытии) устройства (например, функцией CreateFile() из программы пользователя). Каждый драйвер может включать различные функции, в зависимости от на значения устройства. Например, в устройство можно только записывать данные, но нельзя читать – в этом случае можно не определять функцию для IRP_MJ_READ или сделать ее в виде программной «заглушки».

    Как в драйвере выбираются функции, которые должны выполнять в данный момент опе

    рацию с устройством? Для этого предусмотрен механизм пакетов запроса ввода вывода (I/O Request Packet, IRP). Например, если программа пользователя выполняет запись данных в устройство при помощи WINAPI функции WriteFile(), то Менеджер ввода вывода операцион ной системы формирует пакет запроса IRP_MJ_WRITE и посылает его драйверу устройства для выполнения. В свою очередь, драйвер устройства вызывает функцию, чей адрес указан при инициализации массива указателей и передает ей управление. Любой NT драйвер, тем не менее, должен обязательно включать обработчики пакетов запроса IRP_MJ_CREATE (откры тие устройства) и IRP_MJ_CLOSE (закрытие устройства).

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

    Взаимодействие драйвера устройства с программой пользователя рассмотрим на приме

    ре чтения данных из устройства ввода вывода (рис. 7.6).

    На этом рисунке показана в упрощенном виде операция чтения данных устройства из приложения пользователя. Приложение пользователя вызывает функцию ReadFile(), переда вая ей дескриптор открытого устройства. Затем Менеджер ввода вывода, работающий в ре жиме ядра, по дескриптору устройства определяет, для какого драйвера следует формиро вать запрос IRP_MJ_READ и подготавливает пакет запроса. Далее вызывается функция обра ботки, соответствующая полученному запросу, которая выполняет необходимые действия по чтению данных из устройства. Здесь нужно отметить, что даже драйвер никогда не выполняет напрямую операций с портами ввода вывода устройства, а передает управление уровню ап паратных абстракций, реализованному в виде библиотечных функций в библиотеке hal.dll. Фактически здесь «заканчивается» аппаратная «независимость» всех операций и операции проводятся на уровне конкретных аппаратных средств.

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

    Чтение данных из приложения пользователя

    Таким образом, мы, в общем, рассмотрели схему работы NT подобного драйвера устрой ства. Здесь не анализируются другие важнейшие аспекты функционирования драйверов (прерывания, потоки, синхронизация очередей и т. д.); заинтересованных читателей могу ото слать к документации, входящей в состав Windows DDK.

    Сейчас мы на практике посмотрим, как можно реализовать простые драйверы устройств и, чтобы почувствовать, как это работает, создадим простейший драйвер.

    Источник: Магда Ю. С. Компьютер в домашней лаборатории. – М.: ДМК Пресс, 2008. – 200 с.: ил.

    Драйверы –

    Что называют драйверами или по народному - "дровами"? Под данным термином понимают элементы, обеспечивающие стабильное и бесперебойное функционирование устройств операционной системы. Драйвером называют программу, идущую в комплекте с устройством, для которого она была разработана, обеспечивающая нормальное функционирование операционной системой путем достижения полного взаимодействия между ней и данным устройством. При этом любое устройство, как и операционная система, оснащено производителем драйверами, как расширенной, так и базовой комплектации. Базовые драйвера определяют тип и общий характер устройства, однако для некоторых моделей они не актуальны. Например, в случае отсутствия на компьютере драйвера видеокарты при ее установке операционная система использует более простой аналог VGA, отличающийся упрощенными свойствами и настройками. Однако данная программа вполне применима при выходе из строя видеокарты. Но в то же время следует учитывать, что в данном случае крайне затруднительно определение встроенной звуковой платы. Вообще, в связи с этим нужно сказать, что встроенные в плату устройства обычно поддаются распознаванию операционной системой сложно, о чем свидетельствуют отображаемые одним из разделов меню, названным диспетчером устройств, уведомления в случае неудачной попытки распознавания.

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

    1. При установке на новый персональный компьютер операционной системы. Данный этап является наиболее сложным в связи с необходимостью изучения составляющих элементов устройства и поиска соответствующих им драйверов. Наиболее распространен вариант поиска драйверов в интернете и скачивания их с сайтов производителей соответствующих устройств. Также можно найти и скачать драйвер по коду устройства на нашем сайте - driverslab.ru. Для доступа к интернету необходимо предварительно установить драйвер на сетевую карту. После установки драйвера на сетевой проводной или беспроводной адаптер у системы появится доступ к сети и если у Вас, например, Windows 10, то эта ОС может загрузить "дрова" в автоматической режиме.
      Кроме того, поиск и установку драйверов можно произвести автоматически посредством таких программ, как DriverPack Solution, DriverHab, Driver Updater и других, что значительно удобнее. Программа формируют список необходимых драйверов на основе анализа системы с целью обеспечения ее оптимальной работы. Затем программа автоматически устанавливает эти драйвера.
    2. В случае переустановки операционной системы, которая может быть вызвана утратой ее функциональных возможностей или желанием пользователя.
    3. В случае обновления операционной системы с целью расширения ее функциональных возможностей по практической необходимости или желанию пользователя.
    4. В случае отсутствия либо неправильного функционирования отдельных драйверов при установленной операционной системе. При этом прежде всего следует просмотреть состояние уже инсталлированных драйверов в диспетчере устройств. Через данное меню можно осуществить и загрузку недостающих драйверов.

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

    Читайте также: