Чем отличаются драйверы друг от друга? Какой драйвер выбрать? Подбор драйверов для Nvidia. на официальный Nvidia на страницу выбора драйверов

Изучение эффективности драйверов Intel ATA

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

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

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

Для большинства пользователей встроенные IDE контроллеры начались с чипсетов для процессора Intel Pentium серии Intel 430 (FX, VX, HX, TX). Эти контроллеры отличались простотой и надежностью. Они поддерживали все существующие на тот момент стандарты передачи данных по шине IDE (PIO, DMA, MWDMA). Драйверы были встроены в Windows 95 и хотя они не поддерживали режим Bus Master работы контроллера, интерес к фирменным драйверам от Intel (которые он, конечно, выпустил) был невелик. Одной из причин этого было то, что самые быстрые режимы передачи с участием процессора (PIO4) и без него (MWDMA2) обеспечивали примерно одинаковую скорость передачи в 16MB/sес. И только когда потребовалась мощность процессора одновременно с чтением с дисков (это произошло с распространением цифрового MPEG видео на ПК), пользователи стали обращать внимание на преимущества режима Bus Master работы с диском. В версию Windows 95 OSR2 уже были встроены драйверы с поддержкой режима DMA работы дисков, которые существенно снижали загрузку процессора при выполнении дисковых операций. И опять драйверы от Intel опоздали:) — не каждый захочет менять что-то в хорошо работающей системе. Отметим, что сами по себе они в то время были не очень красивы внешне — практически постоянное состояние в бета версиях, непонятный инсталлятор, очень объемные рекомендации по установке с множеством ветвлений, на большинство проблем в работе одинаковый ответ — «удалите драйвер» и все такое.

Однако с тех времен многое изменилось: скорости шины IDE достигли 100MB/sec, необходимость в использовании Bus Master драйверов возросла с появлением MPEG2 и MPEG4, да и чипсеты Intel уже сменили пару поколений. Хотя и сегодня Microsoft в своих последних версиях операционных систем предлагает встроенные драйверы для всех чипсетов Intel, включая i815 (точнее, они просто совместимы с последними ICH серии 82801xx), с поддержкой режима DMA. Тем не менее, нам было интересно сравнить последнюю версию драйверов от Intel для своих IDE контроллеров (теперь они называются Intel Ultra ATA Storage Driver) со стандартными драйверами Microsoft.

Конфигурация стенда:

  • материнская плата ASUS CULS2-LS (i815, ICH2);
  • процессор Intel Pentium III 800EB (133×6);
  • память 2×128Mb PC133;
  • системный диск IBM DTLA 15Gb, тестируемый диск Quantum FB Plus AS 30 Gb;
  • видео NVidia GeForce2 GTS 64Mb.

Операционные системы: Windows ME и Windows 2000 Pro.

  • ZDLabs Winstone 2001;
  • ZDLads Winbench 99 1.2;
  • Intel IOmeter.

Тестировался диск Quantum с двумя вариантами драйверов — со стандартными драйверами Microsoft (на диаграммах с индексом “MS”) и с драйверами Intel ATA 6.10.

При использовании драйверов Intel ATA диск работал в режиме UDMA100, что подтверждается программой-конфигуратором из состава самих драйверов, а также программой HDTach — скорость чтения из буфера диска составляла более 80 MB/sec.

При тестировании со стандартными драйверами Microsoft было предпринято несколько дополнительных шагов. Для включения режима UDMA в Windows ME был установлен флаг «DMA» в свойствах диска. По умолчанию он был выключен. При его активизации диски работали в режиме UDMA100, что также подтверждается HDTach. Для обеспечения работы режима UDMA100 с драйверами Microsoft под Windows 2000 использовался hotfix Q260233. То, что он действительно позволяет работать диску в UDMA100 вместо UDMA66, снова было проверено тестом HDTach 2.61. Скорость чтения из буфера без hotfixа — 57.6 MBps (UDMA66), с hotfixом — 85.5 MBps (UDMA100).

Диск был установлен мастером на второй канал встроенного IDE контроллера. IOmeter — диски не размечаются совсем. ZDLabs — один раздел FAT32 (Windows ME) или NTFS (Windows 2000) на весь диск.

Windows ME

Первая часть тестов проводится под операционной системой Windows ME. Поскольку тест IOMeter под этой системой не работает, то ограничимся тестами ZDLabs.

В новой версии своих пакетов Winstone 2001 компания отказалась от раздельного тестирования подсистем ПК и поэтому эти результаты немного менее информативны. Зато они используют реальные приложения. Посмотрим, что получается:

Итак, скорость работы с различными драйверами отличается совсем незначительно. Теперь сравним загрузку процессора (к сожалению, этот параметр измеряется только для серии Business):


И по этому параметру результаты практически совпадают. Можно рассчитать параметр «эффективности» — отношение скорости (в единицах Winstone) к % загрузки процессора:


По результатам этих тестов можно сказать, что никакого заметного эффекта от использования драйверов Intel ATA не наблюдается.

Теперь посмотрим на цифры ZDLabs Winbench 99 1.2. В этом (последним из серии Winbench) тесте моделируется работа приложений с жестким диском, но без использования реальных программ. Скорее всего, используются шаблоны, рассчитанные на основании статистики работы приложений с диском. На первой диаграмме приведено изменение скорости в % при использовании драйверов Intel ATA:


Как мы видим, по интегральным оценкам Business и High End Disk Winmark отличий практически нет. Что касается приложений, то заметен прирост в 10% для FrontPage 98 (эта программа характерна использованием множества небольших файлов) и падение в 8% для Sound Forge 4.0 (скорее всего, оперирующей с несколькими большими файлами).

Winbench 99 также измеряет загрузку процессора при прохождении тестов. Сами цифры загрузки CPU заметно не отличаются, а нам интереснее сравнить эффективность — отношение Disk Winmark (в тысячах байт в секунду) к % занятости процессора:



Как мы видим, снова использование драйверов Intel ATA не помогает добиться большей скорости или меньшей загрузки процессора, а для High End теста даже снижает эффективность работы диска.

Отметим, что результаты теста чтения с поверхности диска и времени доступа для обоих драйверов были идентичными. Похоже, что плотность записи и время доступа не полностью определяют скорость дисковой подсистемы — буквально у нас на глазах появился еще один загадочный фактор — драйвера. Эффект в +10%, -8% уже значителен, что бы на него обращать внимание.

По результатам проведенных тестов сделаем вывод — использование драйверов Intel ATA для операционной системы Windows ME не приводит к заметному улучшению характеристик дисковой системы ПК и рекомендуется оставлять встроенный драйвер операционной системы, включив в свойствах диска режим DMA.

Windows 2000

Теперь посмотрим на работу с системой Windows 2000 Pro. Эта система рассчитана на более профессиональное использование, чем Windows ME. Она поддерживает работу с двумя процессорами, файловую систему NTFS и, конечно, технологии Windows NT по защите информации.

Для систем класса Windows NT характерно требование 32-разрядных драйверов для всего используемого оборудования, в отличие от Windows 9x, где иногда возможно использование драйверов реального режима, а к дискам вообще допускается обращаться через прерывание BIOS. Конечно, Microsoft включило в состав своей операционной системы много стандартных драйверов для системных устройств (например шин PCI, ISA, AGP), дисковых контроллеров (IDE и SCSI), сетевых карт, видеокарт. С одной стороны, это гарантирует работоспособность стандартного оборудования, а с другой — дает возможность производителю оборудования предложить свой собственный драйвер, обеспечивающий лучшую производительность или расширенные возможности по управлению устройством. В качестве примера можно привести драйверы для видеоконтроллеров компании ATi — входящие в состав Windows NT драйверы позволяют включить высокое разрешение и цветность, но не обеспечивают никаких операций по ускорению вывода трехмерной графики. Еще одним примером являются чипсеты компании ServerWorks — несмотря на поддержку нескольких шин PCI 64 и других нетривиальных возможностей, они прекрасно работают со встроенными драйверами Microsoft, а ServerWorks, похоже, даже не пытается что-то написать (хотя бы inf файлы для корректного отображения своих чипов в диспетчере устройств).

Таким образом, установка драйверов от производителя часто используется для повышения производительности системы. И поэтому эффект от установки Intel ATA драйверов представляет значительный интерес.

Конечно, можно возразить, что использование IDE дисков не к лицу в высокопроизводительных системах, однако, я думаю, что Windows 2000 вполне уместна на любом рабочем столе, современные IDE диски догоняют SCSI (особенно при работе в одиночестве), а «выжать» еще немного скорости из своей системы, тем более с использованием бесплатных драйверов, хочется каждому:)

Отметим и еще два небольших отличия от Windows ME: Windows 2000, во-первых, по умолчанию пытается использовать режим UDMA, а во-вторых, позволяет проверить его текущий статус, что делает драйверы в ней более удобными в использовании.

Как и с Windows ME, начнем с ZDLabs Winstone 2001:


В целом картина аналогична Windows ME — разница практически отсутствует. Отметим здесь, что несмотря на использование NTFS, общие результаты в Windows 2000 заметно больше этих показателей в Windows ME. Еще один повод покупать Windows 2000 вместо ME:)


Забавно, драйверы Intel ATA даже немного больше нагружают процессор, чем встроенные.

И аналогично рассчитанная эффективность:


И снова разница в результатах настолько незначительная, что даже 2.5MB дискового пространства для Intel ATA драйверов на диске становится жалко:)

Теперь ZDLabs Winbench 99 1.2. На первой диаграмме, как и в прошлый раз, представлено изменение скорости в % относительно встроенных драйверов при использовании Intel ATA:


Увы, удручающая картина. Падение скорости достигает 20% в некоторых тестах. Странно, что на Winstone 2001 такого эффекта не было. Возможно, это является следствием «искусственности» тестов Winbench. Однако, с другой стороны, «в каждой шутке есть доля шутки» и поэтому списывать эти цифры на особенности построения теста нельзя. А тест Winbench сам по себе можно рассматривать как приложение, именно так работающее с диском, что наблюдается снижение скорости от Intel ATA. Посмотрим, что у нас с эффективностью:



Меньшая скорость с драйверами Intel ATA и меньшая загрузка процессора с ними также почти сравняли показатели эффективности. Да, похоже, что Winbench это не тот тест, где заметна польза от использования «родных» драйверов от производителя. Скорее даже наоборот. Помните историю с 3D Winbench, когда новые «Turbo» драйверы компании ATi сильно поднимали результаты, а на реальных играх такого эффекта не было? Видимо, история повторяется, но в другую сторону. Результат похож на некоторую несовместимость тестов с драйверами. По результатам тестов ZDLabs видно, что или для тестов выбраны неудачные приложения, или Intel оптимизировал драйверы для своего набора неизвестных приложений.

Поскольку тест Intel IOmeter тоже использует шаблоны, то его результаты очень интересны в свете таких разных результатов Winstone и Winbench. Напомним используемые установки:

block size % of size % reads % random
File Server
512 10 80 100
1024 5 80 100
2048 5 80 100
4096 60 80 100
8192 2 80 100
16384 4 80 100
32768 4 80 100
65536 10 80 100
Workstation
8192 100 80 80
Database
8192 100 67 100
Data Streaming Read
8192 100 100 0
Data Streaming Write
8192 100 0 0
Data Random Read
8192 100 100 100
Data Random Write
8192 100 0 100

Важным параметром также является значение Queue Depth, для него были выбраны значения 1, 32, 64, 128, 256. Этот параметр позволяет смоделировать мощность нагрузки на диск, например, как запуск нескольких приложений одновременно, работу по сети с несколькими пользователями и т.п. Время выполнения каждого шаблона было установлено в 10 минут. Графики по IOps (операций в секунду) и MBps (Мегабайт в секунду) очень похожи, поэтому приводим только вторые. Также приводятся графики эффективности — отношении IOps к % загрузки процессора.

Еще одним отличием IOmeter от тестов ZDLabs является то, что он работает с физическим диском, а не размеченным на разделы. Однако в любом случае работа ведется через драйвер контроллера, так что от него тоже многое зависит.

Все шаблоны я разбил на 3 части — случайное чтение/запись, последовательное чтение/запись и интегральные шаблоны File Server, Workstation, Database.

Начнем со случайного чтения/записи.


Мы видим, что при увеличении нагрузки скорость работы с драйверами Intel ATA практически не меняется, а со стандартными драйверами Microsoft заметно возрастает. Отметим, что рост скорости с увеличением нагрузки характерен также и для IDE контроллеров VIA, Promise, а также для SCSI контроллеров. Таким образом, использование Intel ATA в данном случае качественно меняет картину. Посмотрим, что с эффективностью:


Драйверы Intel ATA показывают здесь большую эффективность работы. Отметим, что в этих тестах средняя загрузка процессора составляет 0.8% и 0.4% для драйверов Microsoft и Intel соответственно. Я думаю, что выгода в 0.4% загрузки процессора такой ценой в падении скорости никому не нужна.

Вторая часть — последовательное чтение-запись.


На последовательно чтение драйверы от Intel не произвели сколь видимого эффекта, а вот с записью проблемы: скорость заметно (в 2 раза!) падает при увеличении нагрузки.


Рост эффективности и в этом случае заметен, но если снова сравнить среднюю загрузку процессора, то она упала для чтения с 25% до 20%, для записи с 21% до 13%. С одной стороны, это означает улучшение на 20 и 40 процентов соответственно, а с другой, на фоне 100% разница между ними заметна.

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


Увы, картина аналогична случайному чтению/записи — при увеличении нагрузки скорость практически не возрастает. Что, в общем-то, и ожидаемо — в шаблонах File Server и Database обращения к диску полностью случайны, а в Workstation — случайны на 80%.


В целом все повторяется. Падение средней загрузки процессора произошло с 0.77% до 0.46%.

Ну что ж, по результатам IOmeter в принципе видно, что Intel ATA добавляют эффективности к работе дисковой подсистемы, но цена слишком велика. Кстати, если привести графики отношения MBps к % загрузки CPU (другой вариант расчета эффективности), то мы не увидим такого большого (иногда почти 100%) прироста эффективности от использования драйверов от Intel.

Если из всех результатов выделить суть, то получается, что такое падение скорости вызвано двумя причинами — худшей обработкой случайных запросов чтения/записи и последовательных запросов записи при возрастании нагрузки. Очень похоже, что драйверы хотят сделать какую-то оптимизацию этих операций, но это у них не выходит. Особенно неприятно выглядит падение скорости при последовательной записи. Казалось бы — запросы идут последовательно, информация пишется также последовательно, неужели нельзя просчитать такую ситуацию и хотя бы не мешать? Тем более, что работа идет на физическом уровне и даже нет никаких отвлекающих моментов типа записи в FAT или MFT.

В результате проведенных исследований, мы выяснили, что использование драйверов Intel ATA в тестах IOmeter приводит скорее к ухудшению результатов. По крайней мере, считать такое значительно падение скорости ценой за меньшее использование процессора нельзя. Больше даже расстраивает факт, что поведение графиков скорости (IOps и MBps) с драйверами Intel ATA приобретает совсем другой характер — рост скорости с увеличением нагрузки заметно снижается или даже становится отрицательным. Получается, что выгода от использования Intel ATA в Windows 2000 также очень сомнительна. Да и списать такое поведение на то, что тест IOmeter использует обращения к физическому диску, нельзя, Все равно все идет через драйвер, а IOmeter специально построен для детального исследования работы дисковой подсистемы и не является каким-то обособленным приложением с редко встречающимися алгоритмами работы с диском.

Объяснить такое поведение драйверов сложно. Поэтому мы связались с разработчиками и получили несколько комментариев этой ситуации. Приведем их:

  • драйверы Intel ATA являются не просто связующим звеном между контроллером и операционной системой, они также выполняют некоторую оптимизацию запросов на запись, а также упреждающее чтение. Таким образом в них встроены некоторые «интеллектуальные» алгоритмы, которые могут влиять на результаты низкоуровневых тестов типа IOmeter;
  • драйверы оптимизированы для процессора Intel Pentium 4 и могут обеспечить на нем прирост скорости дисковой подсистемы;
  • драйверы оптимизированы больше для FAT32, чем NTFS.

Действительно, некоторые объяснения кажутся вполне правдоподобными. Однако «оптимизация», которая не видна на тестах ZDLabs Winstone (использующих реальные приложения!), а при проверке в Winbench даже приводящая к ухудшению результатов, кажется не очень-то полезной для пользователей. Получается, что она дает где-то рост производительности, а вот назвать конкретный положительный пример никто не может. Оптимизация для Pentium 4, безусловно, необходима, поскольку человек, купивший этот процессор, хочет иметь на своем ПК хотя бы одно приложение, использующее особенности P4, за которые он уже заплатил:) Однако есть множество систем, на которых продолжает использоваться Pentium 3, а на них это работать не будет. Ориентация драйверов на использование файловой системы FAT32 в целом не вызывает претензий, поскольку можно считать, что использование NTFS это высокопроизводительные ПК со SCSI контроллерами и дисками.

Таким образом, вырисовывается интересный образ пользователя, для которого предназначены эти драйверы: домашний пользователь с ПК на базе Pentium 4. У него установлена операционная система Windows ME, жесткий диск размечен одним большим разделом на FAT32. И драйверы Intel ATA он установил исключительно для возможности посмотреть в программе Intel Ultra ATA Companion, как быстро работает его жесткий диск.

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

Рано или поздно наступает момент, когда полная переустановка Windows становится неизбежной. А это автоматически означает, что придется заново устанавливать не только саму операционную систему, но и все необходимые драйверы и приложения, что у любого пользователя отнимает немало времени, поскольку установку последних приходится проводить по очереди (причем с выполнением множества рутинных операций) и с разных дисков. Данный процесс можно существенно ускорить и даже в той или иной мере автоматизировать, если воспользоваться специальными драйверными утилитами и программами-автоустановщиками. Какими? Именно об этом и пойдет речь в данной статье.

Драйверные утилиты

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

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

Представленные на рынке утилиты для резервирования драйверов схожи по функциональности, поэтому в качестве примеров решений данного плана мы выбрали лишь наиболее популярные: платные Driver Genius Professional и Driver Magician и бесплатные DriverMax и Double Driver. Первые две представляют собой полноценные решения для управления драйверами и наряду с их резервированием и восстановлением могут обновлять драйверы и при необходимости деинсталлировать их. Стоит также отметить, что при резервировании эти утилиты умеют создавать резервные копии в виде EXE-файлов, что позволяет в дальнейшем проводить восстановление драйверов без инсталляции самих утилит. Тот же функционал, за исключением возможности создания самостоятельного инсталлятора и деинсталляции, имеется и в DriverMax. Что касается Double Driver, то ее возможности скромнее и ограничены резервным копированием и восстановлением, зато данная утилита гораздо проще в применении.

Driver Genius Professional 2008 8.0.0.316

Разработчик : Driver-Soft, Inc.

Размер дистрибутива: 11,3 Мбайт

Работа под управлением: Windows 98/Me/2000/XP/Vista

Способ распространения: http://www.driver-soft.com/products/drvgenpro.exe)

Цена: 29,95 долл.

Driver Genius Professional - удобное решение для управления драйверами. Утилита автоматически производит сканирование имеющихся в системе устройств и установленных драйверов и формирует древовидный отчет, в котором данные оказываются представленными в двух разделах - Out of date drivers и Up to date drivers (рис. 1). В первом фигурируют устройства с устаревшими драйверами, а во втором - те, драйверы которых не нуждаются в обновлении. По каждому из устройств отображается текущая версия драйвера (вместе с указанием времени ее создания) и самая последняя версия этого же драйвера, если такая существует. При этом утилита тут же предлагает указать устройства, для которых новые драйверы должны быть обновлены, и производит их обновление.

Рис. 1. Отчет об установленных драйверах в Driver Genius Professional

Driver Genius Professional обеспечивает создание резервной копии всех либо конкретных драйверов (рис. 2) и может сохранять создаваемую копию драйверов не только в ZIP- или саморазархивирующемся архиве, но и в виде EXE-файла, что позволит в дальнейшем устанавливать сразу все драйверы одним кликом мыши. В случае создания копии в виде архива степень сжатия регулируется.

Рис. 2. Резервирование драйверов в Driver Genius Professional

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

Driver Magician 3.45

Разработчик : GoldSolution Software, Inc.

Размер дистрибутива: 3,75 Мбайт

Работа под управлением: Windows 98/Me/2000/XP/Server 2003/Vista/7

Способ распространения: shareware (15-дневная демо-версия - http://www.drivermagician.com/download.htm)

Цена: 29,95 долл.

Driver Magician представляет собой удобный инструмент для управления драйверами. При запуске утилита автоматически выявляет и отображает все установленные в системе драйверы (рис. 3) за исключением тех, что поставляются Microsoft, поскольку последние и так устанавливаются автоматически при установке ОС (при желании программу можно настроить на поиск всех драйверов без исключения). По каждому из драйверов приводится подробное описание, включая номер версии, название устройства, для которого этот драйвер предназначен, дату создания, производителя и класс драйвера, определяющий тип подключенного устройства.

Рис. 3. Отображение установленных драйверов в Driver Magician

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

Рис. 4. Резервное копирование драйверов в Driver Magician

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

DriverMax 4.92

Разработчик : Innovative Solutions

Сайт программы : http://www.innovative-sol.com/drivermax/

Размер дистрибутива: 2,9 Мбайт

Работа под управлением: Windows XP/2003/Vista

Способ распространения: freeware (http://small.drivermax.com/soft/dmx/drivermax.exe)

Цена: бесплатно

DriverMax - простая и удобная утилита для резервирования драйверов и их обновления. Она выявляет установленные в системе драйверы и генерирует на базе полученной информации наглядный отчет в виде TXT- или HTML-файла (рис. 5) с отображением типа устройства и названия драйвера вместе с указанием его версии, времени создания, имени производителя и наличия/отсутствия у драйвера цифровой подписи.

Рис. 5. Фрагмент HTML-отчета об установленных драйверах в DriverMax

Утилита позволяет экспортировать все либо только конкретные драйверы (рис. 6) в виде файлов драйверов в отдельных папках либо сжатого файла в формате ZIP и затем может восстанавливать их из созданной копии.

Рис. 6. Резервирование драйверов в DriverMax

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

Double Driver 2.1

Разработчик : Budy Setiawan Kusumah

Размер дистрибутива: 1,79 Мбайт

Работа под управлением: Windows 2K/XP/Vista

Способ распространения: freeware (http://www.boozet.org/download.htm)

Цена: бесплатно

Double Driver - компактная бесплатная утилита для резервного копирования драйверов. С ее помощью несложно провести сканирование компьютера и выявить перечень установленных в системе драйверов с указанием номеров их версий, дат создания и производителей (рис. 7). А также выполнить полное либо выборочное резервирование драйверов от Microsoft и/или иных производителей (рис. 8). Создаваемая резервная копия сохраняется в виде файлов драйверов в отдельных папках либо в архиве (ZIP или самораспаковывающемся) - восстановить драйверы из нее в дальнейшем не составит никакого труда.

Рис. 7. Результат сканирования в Double Driver

Рис. 8. Резервное копирование драйверов в Double Driver

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

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

Предлагаемых на рынке утилит данного плана совсем немного - нам удалось найти всего три достойных внимания решения: MultiSet, RoboSetup и Maestro AutoInstaller. Все они позволяют автоматизировать процесс установки приложений, а утилита MultiSet дополнительно еще может быть использована для автоматизации установки Windows. Данные утилиты не требуют ручного создания сценариев (хотя RoboSetup и позволяет разрабатывать сценарии вручную) и знания тонкостей программного кода, а потому представляют интерес не только для администраторов, но и для широкого круга пользователей.

Создать сценарий автоустановки в одной из этих утилит несложно - достаточно запустить утилиту и вручную провести инсталляцию приложения. В ходе данного процесса утилита запомнит все действия пользователя с мышью и клавиатурой и в дальнейшем сможет выполнять их самостоятельно. Однако при проведении инсталляции необходимо выполнять ряд правил (в противном случае результат работы утилиты по сценарию окажется неутешительным):

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

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

В MultiSet и RoboSetup возможно также создание сценариев другим способом - путем указания ключа автоматической установки. При запуске с таким ключом инсталлятор не задает вопросов, не демонстрирует лицензионное соглашение, а устанавливает программу со значениями по умолчанию (рис. 9). Правда, тут есть свои сложности. Дело в том, что не у каждого типа инсталляторов существуют ключи автоустановки, а если такие и имеются, то у разных типов инсталляторов они будут свои, причем разработчиками эти ключи чаще всего не указываются и их приходится подбирать. Например, для инсталлятора типа Inno Setup подходит ключ /verysilent (setup.exe /verysilent), для инсталлятора типа WISE Installer - ключ /s (setup.exe /s) и т.д. Вместе с тем если вы знаете, какой инсталлятор используется для установки конкретного приложения и его ключ (предполагаем, что он существует), то, применив данный метод, можно настроить автоматическую установку приложения гораздо быстрее, чем при непосредственной его установке.

Рис. 9. Окно инсталлятора, работающего в режиме автоматической установки

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

MultiSet 6.6

Разработчик : Almeza Research, LLC (http://www.almeza.ru/)

Размер дистрибутива: 5,5 Мбайт

Работа под управлением: Windows 98/Me/2000/XP/2003 Server/Vista

Способ распространения: http://www.almeza.com/download/multiset.exe)

Цена: 99,95 долл.; для русскоязычных пользователей: домашняя лицензия - 695 руб., корпоративная лицензия - 4500 руб.

MultiSet - удобное решение, предназначенное для создания готовых дистрибутивов для автоматической установки Windows и приложений. Данная программа обеспечивает запись сценариев двумя способами: путем запоминания выполненных в ходе установки действий пользователя (рис. 10) и через указание ключей автоустановки. Созданные сценарии можно редактировать.

После создания нужного набора сценариев для очередной установки соответствующего приложения потребуется лишь запустить MultiSet, выбрать нужное в списке доступных приложений (то есть тех, для которых сценарии были предварительно созданы) и нажать кнопку «Установить выделенные приложения» (рис. 11). Требуемое приложение установится автоматически без какого-либо участия пользователя. Естественно, таким способом за один раз можно установить не только одно, но и сразу несколько приложений.

Рис. 10. Запись установки приложения
FastStone Image Viewer в MultiSet

Рис. 11. Автоматическая инсталляция приложения FastStone Image Viewer из MultiSet

Предусмотрено также создание установочных самозагружающихся дисков (CD/DVD/Flash/Hard Drive), которые будет удобно использовать для быстрой автоматической установки сразу всех или только избранных приложений. При вставке подобного CD/DVD-диска в накопитель (либо в случае Flash Drive или Hard Drive подключения его к компьютеру) на экране появляется предложение выбрать все либо только конкретные приложения для их последующей установки (рис. 12). После сделанного пользователем выбора все указанные приложения автоматически устанавливаются.

Рис. 12. Автоматическая установка приложений
с самозагружающегося диска в MultiSet

RoboSetup 2.0.1

Разработчик : High Mountain Group (http://www.robosetup.com/)

Размер дистрибутива: 4,9 Мбайт

Работа под управлением: Windows 98/NT/Me/2000/XP/2003/Vista

Способ распространения: shareware (30-дневная функционально ограниченная демо-версия - http://robosetup.com/robosetup.exe)

Цена: Personal Licence - 19,95 долл., Business Licence - 99,95 долл.; для русскоязычных пользователей: персональная лицензия - 485 руб., бизнес-лицензия - 499 руб. (Allsoft.Ru)

Программа RoboSetup представляет собой инструмент для создания так называемых рободисков (обычно их записывают на CD/DVD-диски или Flash-носители) с автоматически устанавливающимся софтом. При вставке такого диска в привод открывается меню, в котором для установки соответствующих приложений пользователю достаточно будет указать инсталлируемый софт и нажать кнопку «Установить» (рис. 13). Предусмотрено также формирование сетевой версии рободиска, с помощью которой автоматическая установка программ окажется доступной для всех пользователей сети.

Рис. 13. Автоматическая инсталляция приложений
с самозагружающегося диска в RoboSetup

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

Рис. 14. Генерация сценария установки приложения
FastStone Image Viewer в RoboSetup

Maestro AutoInstaller 1.4.1

Разработчик : Shebanitsa Ivan (http://www.maestro-kit.ucoz.ru/)

Размер дистрибутива: 1,55 Мбайт

Работа под управлением: Windows 98/Me/2000/XP/2003/Vista

Способ распространения: freeware (http://maestro-kit.ucoz.ru/index/download/MaestroSetup_full.rar)

Цена: бесплатно

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

Рис. 15. Запись установки приложения
FastStone Image Viewer в Maestro AutoInstalle

Установка приложений по созданным сценариям предельно проста и потребует запуска утилиты с последующим указанием в ней папки с нужным набором пакетов, выделением интересующих пакетов и активированием самого процесса установки щелчком по кнопке «Установить» (рис. 16).

Рис. 16. Автоматическая инсталляция нескольких приложений
в Maestro AutoInstaller

Возможно создание прообразов инсталляционных загрузочных дисков - прообразы таких дисков в среде утилиты записываются на жесткий диск и включают файлы autorun и три папки: папку с программой Maestro AutoInstaller, папку со сценариями автоустановки и папку с дистрибутивами устанавливаемых приложений. Полученные прообразы записывают на перезаписываемый CD/DVD-диск с помощью привычного приложения для прожига дисков. Тут, правда, нужно отметить, что одной записи прообраза на диск для его корректной работы недостаточно - у каждого пакета придется вручную изменять свойства, указывая конкретные файлы уже на CD/DVD-диске.

Заключение

Переустановка драйверов и приложений - занятие, на которое любой пользователь затрачивает немало времени. А это время можно провести с куда большей пользой, если воспользоваться одной из рассмотренных драйверных утилит, а также специальной утилитой для автоматической установки приложений. В качестве программы-автоустановщика теоретически можно выбрать любую, хотя в MultiSet и RoboSetup процесс автоматической установки организовать быстрее и проще благодаря более простой технологии подготовки установочных самозагружающихся дисков. Что касается драйверных утилит, то в плане резервирования/восстановления драйверов более эффективно применение программ Driver Genius Professional и Driver Magician, поскольку в них предусмотрена возможность сохранения резервной копии в виде самостоятельного инсталлятора, что обеспечивает более быстрый вариант установки драйверов.

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

Отличия драйверов ШД

Основные отличия драйверов заключаются в их характеристиках и схемотехнике, в наличии или отсутствии определенных опций.

Базовые различающиеся характеристики:

  • Электротехнические параметры - выходное напряжение, ток. Эти параметры должны подходить под ШД, которым будет управлять драйвер. Кроме того, драйвер должен позволять менять эти характеристики, для более точной настройки системы. Чем шире диапазон - тем больше возможностей драйвер вам предоставит.
  • Поддерживаемые протоколы - STEP/DIR, CW/CCW и т.д. Стандартом де-факто является протокол STEP/DIR/ENABLE , поэтому лучше выбирать драйвер, поддерживающий именно его.
  • Деление шага . Как правило, для плавной работы ШД и высокой разрешающей способности требуются деления от 1/8 до 1/32. Деления шага на бОльшие значения не приводят ни к повышению механической точности, ни к более плавному ходу, но при этом требуется подавать очень большую частоту STEP на драйвер.
  • Функция подавления резонанса. Важнейшая функция современных драйверов ШД, поскольку резонанс возникает на шаговых двигателях всегда. Её наличие повышает стоимость драйвера, но позволяет избежать большого количества проблем с пропуском шагов. Всегда выбирайте драйверы с подавлением резонанса, если есть такая возможность.
  • Морфинг . Использование микрошага позволяет добиться более плавного хода передачи, но снижает максимальный момент, развиваемый шаговым двигателем, поскольку суммарный ток в обмотках никогда не достигает максимальных величин. Технология изменения фазовых токов(морфинг) позволяет "выжать" дополнительную мощность из шагового двигателя на высоких оборотах.
  • Дампер . Дампер относится к защитным элементам и защищает драйвер от обратной ЭДС двигателя, генерируемой им при торможении. Настоятельно рекомендуем использовать драйверы с встроенным дампером.
  • Режим AUTO-SLEEP. Наличие режима AUTO-SLEEP означает, что ток в обмотках ШД автоматически снижается при простое, что позволяет уменьшить нагрев ШД.
  • Плавный пуск ШД. При включении драйвера с этой опцией ток в обмотках ШД нарастает постепенно, благодаря чему исключается характерный удар на валу ШД.
  • Встроенный генератор частоты STEP – удобная функция для пробного запуска драйвера без подключения к ПК.
  • Разнообразные защитные механизмы: защиту от перегрузок по току, от перегрева, от переполюсовки питающего напряжения. Естественно, чем больше встроенных защит, тем дольше проживет Ваш драйвер.

Схемотехнически драйверы тоже могут сильно различаться. Существуют драйверы, выполненные в виде одной микросхемы(например, разновидности микросхем TB6560). Такие микросхемы обычно используют для создания бюджетных многоканальных драйверов без каких-либо дополнительных опций. Единственным драйвером с подавлением резонанса на микросхемах Toshiba является драйвер Purelogic PLC330b.

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

Компания Purelogic также применяет передовую схемотехнику для своих драйверов нового поколения.

Выбор драйвера

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

  • Используйте драйверы с подавлением резонанса.
  • Подбирайте драйверы и ШД с запасом по мощности

В процессе эксплуатации ШД мы вывели некоторые закономерности и рекомендуем:

  1. Для ШД с размером фланца 42мм (NEMA 17) использовать драйверы типа PLD330, PLD545, PLD57 с источником питания NES-350-27 (27В/13А)
  2. Для ШД с размером фланца 57мм (NEMA 23) использовать драйверы типа PLD330, PLD545, PLD57 с источником питания NES-350-27 (27В/13А) или NES-350-48 (48В/7А). Напряжение питания зависит от желаемой максимальной скорости вращения ШД и длины ШД.
  3. Для ШД с размером фланца 86мм (NEMA 34) использовать драйверы типа PLD880, PLD86 с источником питания NES-350-48 (48В/7А) или собрать источник на напряжение 70В. Напряжение питания зависит от желаемой максимальной скорости вращения ШД и длины ШД.
  4. Для ШД с размером фланца 110мм (NEMA 43) использовать драйверы типа PLD880, PLD86 или PLD8220. Напряжение питания от 70В. Напряжение питания зависит от желаемой максимальной скорости вращения ШД и длины ШД.
  5. Для ШД с размером фланца 130мм использовать драйвер типа PLD8220.

Нежелательно использовать для ШД с размером фланца 57мм (NEMA 23) мощные драйверы типа PLD880, PLD86 и наоборот - для ШД с размером фланца 86мм (NEMA 34) драйверы типа PLD545, PLD57. Основная причина - настройка цепи устранения среднечастотного резонанса. Элементы схемы подавления среднечастотного резонанса оптимизированы для конкретного размера ШД и на других размерах подавление резонанса будет не оптимально.

Структура загружаемого драйвера

Наименование параметра Значение
Тема статьи: Структура загружаемого драйвера
Рубрика (тематическая категория) Компьютеры

Драйвер - это еще одна разновидность программ в дополнение к уже изученным нами программам формата COM и EXE. Иногда говорят, что драйверы - это разновидность COM-программ, но это не так. Скорее способ получения загрузочного модуля драйвера похож на способ получения программы в формате COM. Есть еще одно сходство драйверов и программ в формате COM (ĸᴏᴛᴏᴩᴏᴇ как раз и появляется из-за одинакового способа их получения) - загрузочные модули этих программ являются точным отображением исходного текста на языке ассемблера без добавления каких-либо управляющих блоков в начало файла, как это происходит в программах формата EXE. (К сожалению, драйвер должен быть написан на языке ассемблера. Авторам этой книги не известны способы составления драйверов на других языках программирования).

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

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

Τᴀᴋᴎᴍ ᴏϬᴩᴀᴈᴏᴍ, можно говорить и о сходстве драйвера с программами в формате EXE, так как в начале загрузочного модуля драйвера имеется управляющий блок. Только данный управляющий блок в отличие от заголовка EXE-файла является принадлежностью самой программы и загружается вместе с ней в память. Заголовок EXE-программы используется при загрузке EXE-программы, но после загрузки операционная система убирает его из памяти.

Не стоит пытаться запускать драйвер как программу в формате COM, так как управление будет передано в область памяти, содержащую заголовок драйвера, а там нет правильных машинных команд. По этой причине обычно файлы драйверов имеют расширения имени, отличные от COM или EXE. Чаще всœего используются расширения SYS, DRV, иногда BIN. На самом делœе расширение имени можно задавать любое, так как при описании драйвера в файле CONFIG.SYS указывается его полное имя.

Для драйвера никогда не создается префикс программного сегмента PSP. В начале исходного текста программы-драйвера не ставится директива ORG 100H, как это делается для COM-программы, так как не нужно резервировать место для PSP.

Что же представляет из себя загрузочный модуль драйвера?

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

Как уже было сказано, всœе драйверы связаны в цепочку. Самый первый драйвер находится сразу за векторной таблицей связи. Поле next заголовка драйвера указывает на следующий драйвер (на его заголовок). Это поле имеет формат DWORD-указателя и состоит из компоненты адреса сегмента и смещения. Признаком того, что данный драйвер последний в цепочке, служит значение 0FFFFh в компоненте смещения поля next.

Программист, когда он составляет программу-драйвер, заносит в это поле либо 0FFFFh:0FFFFh, в случае если исходный текст содержит только один драйвер, либо адрес следующего драйвера (в виде дальней ссылки на метку заголовка следующего драйвера). В случае если исходный текст содержит несколько драйверов, то в заголовке последнего в поле next должно находиться значение 0FFFFh:0FFFFh.

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

Обычно исходный текст программы содержит один драйвер, и поле next задается следующим образом:

Next DD 0FFFFFFFFh

Следующее поле в заголовке драйвера - поле атрибутов драйвера atrib.

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

Следует специально отметить, что всœе драйверы можно разделить на две группы - драйверы символьных устройств и драйверы блочных устройств. Первые обслуживают устройства посимвольного ввода/вывода, такие как принтеры, клавиатура, контроллеры последовательной передачи данных RS232C и т.д., вторые ориентированы на ввод/вывод блоками - это диски.

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

Блочные драйверы могут Вам потребоваться в основном для обслуживания своих нестандартных дисковых устройств. К примеру, можно использовать более плотную запись информации на дискетах для повышения их емкости, можно через аппаратуру связи персонального компьютера и ЭВМ серии ЕС создавать псевдо-винчестеры на дисках ЕС (такие "винчестеры" будут восприниматься DOS как обычные стандартные диски). С помощью блочных драйверов можно организовать защиту информации на дисках от несанкционированного доступа, в случае если Ваш драйвер будет шифровать записываемую на диск информацию и предоставлять ее по предъявлению пароля.

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

Приведем назначение отдельных битов слова атрибутов символьного драйвера:

Бит Назначение
1 - драйвер обслуживает стандартное устройство ввода; 0 - данный драйвер не обслуживает стандартное устройство ввода
1 - драйвер обслуживает стандартное устройство вывода; 0 - драйвер не обслуживает стандартное устройство вывода
1 - это драйвер стандартного устройства NUL; 0 - драйвер не обслуживает устройство NUL
1 - драйвер обслуживает часы
Зарезервировано, бит должен быть равен 0
1 - разрешено использование драйвером функций GENERIC IOCTL (для версий DOS, более поздних, чем 3.2); 0 - функции GENERIC IOCTL не поддерживаются
7-10
1 - поддерживаются функции открытия/закрытия устройства (OPEN/CLOSE) для символьных устройств; 0 - функции OPEN/CLOSE для символьных устройств не поддерживаются
Зарезервировано, бит должен быть равен 0
1 - для символьных устройств поддерживается функция вывода до получения состояния занятости устройства; 0 - функция вывода до состояния занятости не поддерживается

Для драйверов блочных устройств формат слова атрибутов другой:

Бит Назначение
Зарезервировано, бит должен быть равен 0
1 - драйвер поддерживает 32-битовую адресацию сектора (для версий DOS, начиная с 4.00 и более поздних); если установлен данный бит, поле номера сектора всœех запросов является двойным словом, добавляемым в конец заголовка запроса, старое поле номера сектора должно содержать -1); 0 - используется 16-битовая адресация сектора
2-5 Эти биты зарезервированы и должны быть равны 0
1 - поддерживаются логические устройства (используется блочными драйверами для управления "виртуальными" флоппи-дисками, создаваемые драйвером DRIVER.SYS в DOS версии 3.2 и более поздних версиях); 0 - логические устройства для блочных драйверов не поддерживаются;
7-10 Эти биты зарезервированы и должны быть равны 0
1 - единица в данном бите означает, что драйвер поддерживает функцию проверки замены носителя данных в устройстве (к примеру, замены дискеты); используется для DOS версий 3.00 и более поздних; 0 - для блочных устройств функция проверки замены носителя данных не поддерживается
Зарезервировано, бит должен быть равен 0
1 - драйвер не использует стандартное IBM-устройство, и крайне важно выдать запрос на построение блока параметров BIOSBIOS BPB; 0 - используется IBM-устройство
1 - поддерживаются функции IOCTL; 0 - функции IOCTL не поддерживаются
1 - символьное устройство; 0 - блочное устройство

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

Attrib DW 8000h

После слова атрибутов драйвера находятся два очень важных поля: смещение программы стратегии драйвера strateg и смещение программы обработки прерывания interrupt.

Эти две программы используются DOS для организации обращения к драйверу. Для обращения к драйверу DOS формирует в своей области данных запрос, состоящий из заголовка стандартного формата и переменной части запроса, длина и формат которой зависят от типа запроса. После этого DOS считывает из заголовка драйвера значение смещения программы стратегии и передает ей управление, записав в регистры ES:BX адрес заголовка запроса.

Задача программы стратегии - запомнить данный адрес внутри тела драйвера для дальнейшего использования или организовать очередь запросов обслуживания.

Сразу после вызова программы стратегии DOS вызывает программу обработки прерываний, определив ее адрес из поля interrupt заголовка драйвера.

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

Результаты выполнения функции программа прерывания записывает в специально отведенные поля заголовка запроса, и на этом процедура обращения DOS к драйверу завершается.

Формат заголовка запроса будет приведен ниже, а сейчас покажем, как в заголовке драйвера задаются смещения программ стратегии и прерывания:

Strateg DW strateg_procinterrupt DW interrupt_proc

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

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

Dev_name DB "AUX "

Для блочных устройств первый байт поля dev_name содержит количество устройств, обслуживаемых данным драйвером, остальные семь байтов не используются:

Dev_name DB 1 DB 7 dup(?)

Τᴀᴋᴎᴍ ᴏϬᴩᴀᴈᴏᴍ, мы выяснили, что драйвер содержит в самом начале заголовок, и где-то дальше должны располагаться программы стратегии и прерывания. (Не следует путать программу прерывания драйвера с программой обслуживания аппаратных или программных прерываний. Хотя программа прерывания драйвера немного похожа на обработчик программных прерываний, назначение этой программы и механизм ее использования совершенно другой).

Что еще может находиться в программе-драйвере?

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

На длину драйвера накладывается такое же ограничение, как и на длину COM-программ - 64 килобайта͵ то есть один сегмент.

Структура загружаемого драйвера - понятие и виды. Классификация и особенности категории "Структура загружаемого драйвера" 2017, 2018.

Как мы знаем, на аппаратном уровне современный компьютер состоит из функциональных узлов, представляющих собой те или иные электронные компоненты. Широкому кругу пользователей персональных компьютеров знакомы такие функциональные блоки как: процессор, память, видеокарта, звуковая карта, жесткий диск, контроллер ввода-вывода (обеспечивающий работу клавиатуры, мыши, джойстика, USB-носителей (флешек)), принтер, сканер и некоторые другие. На физическом уровне данные устройства взаимодействуют между собой посредством специальных шин и протоколов, создавая совокупностью своего взаимодействия симбиоз операций, который, в общем случае, характеризует функционирование компьютера. Но разве компьютер представляет собой только лишь набор электронных компонентов? Конечно же нет, ведь один из основных аппаратных модулей, центральный процессор, спроектирован для выполнения машинных инструкций, из последовательностей которых, как мы знаем, состоят программы, в свете этого было бы уместно упомянуть еще об одном уровне - программном. Теперь давайте вернемся в не столько далекое прошлое; на заре компьютерной эры код программ (которые часто писались непосредственно в машинных кодах/на низкоуровневых языках) мог легко взаимодействовать с аппаратурой напрямую, поскольку аппаратная архитектура была относительно простой. Однако со временем технологии развивались, аппаратный и программный уровни эволюционировали взаимосвязано, и первый пришел к появлению большого многообразия устройств, а второй к появлению огромного разнообразия программных модулей, обусловивших, в дальнейшем, появление операционных систем. Операционная система явилась ключевой вехой в истории развития компьютерной индустрии, поскольку именно она, среди прочего, выполняла роль связующего звена, своеобразного координатора (диспетчера), обеспечившего взаимодействие между устройствами и программами: принимала запросы от программного слоя (например, пользовательских программ) на обмен данными с тем или иным устройством и наоборот, то есть фактически выполняла роль сопряжения между аппаратной и программной частями. Операционные системы тоже не стояли на месте, и если по началу взаимодействие операционной системы с аппаратурой компьютера было относительно простым, то по мере усложнения архитектуры и введения новых аппаратных возможностей, усложнялась и структура операционной системы. На протяжении всего времени развития операционных систем, разработчики пытались создать код, обеспечивающий полноценное взаимодействие с максимально возможным количеством имеющимся на рынке аппаратных устройств. Тем не менее, подобный подход, по мере усложнения архитектуры персональных компьютеров x86, привел к появлению концепции обособленного программного слоя, носящего название драйвер, ответственного за взаимодействие с тем или иным классом/типом устройств. Концепция драйвера оказалась настолько удачной, что помимо основного направления - поддержки физических устройств, была экстраполирована и на некоторые категории логических/виртуальных устройств. В данной статье мы будем рассказывать про то, что же из себя представляет драйвер Windows .

Теория

Давайте немного отойдем от концепции драйвера и рассмотрим общую теорию. Для того, чтобы понять что же представляет собой драйвер в системе, сначала необходимо пройти минимум теории по общей архитектуре x86-64. Почему x86, да потому что именно эта платформа: а) выбрана мной для экспериментов, б) является наиболее распространенной в клиентском сегменте операционных систем Windows. Озвученные в данном разделе особенности дадут нам понимание многих аспектов работы как непосредственно операционной системы, так и, соответственно, драйверов в её составе.

Режимы работы процессора

Внутренняя структура любой операционной системы базируется на аппаратных особенностях платформы, на которой она работает. Центральным звеном является процессор, у процессоров архитектуры x86-64 имеются несколько режимов работы:

  • Реальный режим (Real mode);
  • Виртуальный режим (Virtual mode);
  • Защищенный режим (Protected mode);
  • Длинный режим (Long mode).

На заре эры развития персональных компьютеров архитектуры x86, процессор работал в реальном режиме. Тем не менее, реальным режим постепенно ушел в прошлое, поскольку имел ряд особенностей, делающих невозможным дальнейшее развитие технологий: 16-битную шину данных и 20-битную шину адреса (ограничение по адресации), сегментную адресацию с размерами сегментов в 64 килобайта (неудобство использования адресного пространства), отсутствие разграничений доступа к адресному пространству. С целью снятия существовавших ограничений был разработан защищенный режим, который предоставлял ряд важных для развития операционных систем особенностей: "многозадачность", механизм защиты (доступ к привилегированным командам), обеспечивающий контроль доступа различных участков кода (программ) друг к другу, модель виртуальной памяти. В защищенном режиме процессоров Intel архитектуры x86 реализованы так называемые кольца защиты или уровни привилегий. Всего их четыре: 0 (наиболее привилегированный), 1, 2 и 3 (наименее привилегированный). Уровни привилегий призваны защитить код режима ядра от пользовательских программ и пользовательских программ друг от друга, поскольку это может привести к нарушению работоспособности. Однако операционная система Windows не использует все перечисленные уровни, в ней задействованы лишь два из них: 0-й и 3-й.
Для наглядности понимания этого приведем упрощенную схему взаимодействия компонентов Windows:

Как вы видите, внутренняя среда операционной системы Windows разделена на две части и поддерживает два режима выполнения:

  • Пользовательский режим - непривилегированный режим, сопоставленный с аппаратным 3-им кольцом защиты процессора;
  • Режим ядра - привилегированный режим, сопоставленный с аппаратным 0-м кольцом защиты процессора;

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

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

  • Изолированными (не пересекающимися) виртуальными адресными пространствами: пространство пользовательского режима занимает нижнюю часть (адреса с по), пространство режима ядра занимает верхнюю (адреса с по);
  • Разными привилегиями доступа кода к ресурсам (памяти, процессору, устройствам и прч).

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

Подсистема Описание
Процессы обеспечения работоспособности системы (System Support Processes)
  • Процесс входа в систему Winlogon (winlogon.exe )
  • Процесс локального сервера проверки подлинности lsass (lsass.exe )
  • Процесс диспетчера управления службами (services.exe )
  • Процесс диспетчера сессий (smss.exe )
  • Процесс консоли (conhost.exe )
  • Процесс диспетчера локальных сессий (lsm.exe )
  • . . .
Процессы служб/сервисов (Service Processes)
  • Хост-процесс для служб (svchost.exe )
  • Процесс диспетчера очереди печати (spoolsv.exe )
  • Процесс управления службой WMI (winmgmt.exe )
  • . . .
Приложения (Applications)
  • Пользовательские приложения (все приложения, не входящие в остальные категории).
  • Диспетчер задач (taskmgr.exe )
  • Проводник (explorer.exe )
  • Консоль управления (mmc.exe )
  • . . .
Подсистемы окружения (Environment Subsystems)
  • Подсистема Win32 (csrss.exe , kernel32.dll , advapi32.dll , user32.dll , gdi32.dll , ...)
  • Подсистема Linux (lxss.sys , lxcore.sys )
  • Подсистема POSIX (psxss.exe , psxrun.exe , posix.exe , psxdll.dll )
  • Подсистема OS/2 (os2.exe , os2ss.exe , os2srv.exe )
  • Подсистема WOW/WOW64 (wow64win.dll , wow64.dll , wow64cpu.dll )
  • . . .
Интерфейс к функциям ядра
  • Обеспечивает передачу управления в ядро для функций, которым это необходимо. Поддерживается библиотекой ntdll.dll

В режиме ядра выполняются:

Подсистема Описание
Исполнительная система (Executive)
  • Диспетчер ввода-вывода
  • Диспетчер процессов
  • Диспетчер потоков
  • Диспетчер виртуальной памяти
  • Диспетчер объектов
  • Диспетчер PnP
  • Диспетчер питания
  • Диспетчер окон
  • . . .
Ядро (Kernel) инициализация критических для системы драйверов этапа загрузки, межпроцессорная синхронизация, планирование и диспетчеризация процессов/потоков/прерываний, обработка/диспетчеризация исключений/ошибок и некоторые другие функции (ntoskrnl.exe , ntkrnlmp.exe , ntkrnlpa.exe , ntkrpamp.exe ).
Драйверы устройств (Device Drivers) драйверы физических/логических/виртуальных устройств: драйверы файловых систем, сети, дисков и прч.
Оконная/графическая подсистема (Windowing And Graphics System) Подсистема поддержки окон и графики, обеспечивающая поддержку функций графического пользовательского интерфейса (Graphic User Interface, GUI). (win32k.sys )
Уровень абстрагирования от оборудования (Hardware Abstraction Layer, HAL) обеспечивает независимость от аппаратной части платформы, изолирует компоненты ядра от специфики аппаратного обеспечения. (hal.dll )

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

Остается открытым вопрос: действительно все компоненты режима ядра взаимодействуют с оборудованием исключительно через уровень HAL? имеются ли исключения? В Сети во многих источниках приводятся схемы, на которых драйвера графического адаптера взаимодействуют с видеокартами как бы "напрямую", в обход HAL. Насколько я помню, графике в некоторых версиях Windows отводился наивысший приоритет, поэтому она была выделена в отдельную категорию устройств, работающую напрямую с графическим адаптером, и сделано это с целью ускорения графического интерфейса системы.

Уровни запросов прерываний (IRQL)

Среди ключевых внутренних механизмов, определяющих функционирование операционной системы Windows, имеется достаточно важная для понимания принципов работы драйверов тема, обойти которую стороной вряд ли получится. Механизм этот носит название уровня запросов прерываний (Interrupt Request Level, IRQ Level, IRQL) и достаточно сложен для понимания, поэтому углубленное его изучение выходит далеко за рамки излагаемого материала, однако в данной статье мы предпримем попытку краткого изложения (ну а в будущем выделим под него отдельную статью). Откровенно говоря, сам я до сих пор путаюсь в концепции IRQL, поэтому буду излагать собственное понимание планомерно, шаг за шагом, с опорой на знания, полученные на каждом из этапов.
Термин прерывание всегда ассоциировался у меня с реальным режимом работы процессора, перенося во времена операционной системы MSDOS, в которой все было достаточно просто: существовал набор из 256 прерываний, доступных через таблицу векторов прерываний. Часть этих прерываний были аппаратными, соответственно генерировались самостоятельно по каким-либо внешним аппаратурным событиям, другие же являлись программными, соответственно могли вызываться из кода приложений. Записи в таблице прерываний могли быть переопределены, то есть вектор обработчика прерывания был доступен для изменения по своему усмотрению на собственную процедуру обработки. Таких понятий как уровень запросов прерываний не существовало, все было просто и понятно. Однако, с эволюцией процессоров и операционных систем появился сначала защищенный режим, а затем уже и Windows, с этого момента все начало стремительно усложняться.
Буквально внезапно, в первых же версиях Windows 95/NT, появилась какая-то таблица (состоящая из 32 уровней запросов прерываний), уровни которой градируются от самого низкого 0 (passive) до самого высокого 31 (high):

Имя Класс Назначение Уровень Intel x86-64
HIGH Аппаратный Наивысший уровень. Немаскируемое прерывание и другие типы. 31
POWER Аппаратный События сбоя питания 30
IPI Аппаратный Межпроцессорный сигнал. Сигналы межпроцессорного взаимодействия. 29
CLOCK Аппаратный Такт системного таймера 28
PROFILE Аппаратный Контроль производительности. Таймер профилирования ядра (механизм измерения производительности системы). 27
DEVICE Аппаратный DIRQL (Devices IRQL). Аппаратные прерывания устройств. 3-26
DISPATCH Программный Операции планировщика/отложенные вызовы процедур (DPC). 2
APC Программный Асинхронные вызовы процедур. 1
PASSIVE Программный Пассивный уровень. Нет прерываний. Обычный уровень выполнения кода режима пользователя 0

Как можно заметить, в приведенной таблице присутствует очень интересная особенностью: вместе сведены и программные и аппаратные уровни (0-2 это программные уровни, а с 3-31 это аппаратные).

IRQL - собственный программный атрибут, введенный разработчиками Microsoft. Никакой аппаратной поддержки со стороны процессора у этого механизма нет. Система самостоятельно управляет всеми типами возникающих прерываний через механизм отображения уровней прерывания аппаратного контроллера прерываний (PIC) и собственных программных уровней в единую аппаратно-независимую таблицу уровней прерываний.

Из этого утверждения следует, что модель собственная, программная, и уровни в ней не привязаны к какой-либо спецификации оборудования, это позволяет системе собрать в единую иерархию приоритетов аппаратные и не аппаратные типы прерываний. Низшие (не аппаратные/программные) уровни IRQL (PASSIVE, APC, DPC/DISPATCH) используются для синхронизации программных подсистем операционной системы: запуска операций планирования, таких как переключение потоков или обработка завершения ввода/вывода. Давайте рассмотрим их подробно:

  • 0-й (низший) приоритет IRQL (PASSIVE): является типовым уровнем запроса прерываний, на котором производится работа в операционной системе, как в пользовательском режиме, так и в режиме ядра. Код (программа), выполняющийся на данном уровне, может быть элементарно прерван (вытеснен) всем чем угодно: например потоки, исполняющиеся с уровнем IRQ PASSIVE подвергаются вытеснению планировщиком по истечении кванта времени, выделенного для них.
  • Уровни IRQL APC и DPC/DISPATCH - программные уровни прерываний, связанные с планировщиком.
  • 1-й уровень IRQL (APC): На этом уровне выполняются так называемые APC-процедуры, то есть процедуры, выполняющиеся асинхронно в контексте конкретного потока, другими словами организующие асинхронный ввод-вывод, или обращающиеся/ждущие освобождения каких-либо (внешних, глобальных) системных объектов. Использование APC-функций (например WaitForSingleObjectEx) в коде не приводит к мгновенному выполнению функции, вместо этого поток (в контексте которого функция выполняется) переходит в специальный статус и генерируется программное прерывание APC, вызов функции ставится во внутреннюю очередь. В следующий раз, когда подошло время выполняться этому потоку, то запланированная APC-функция выполняется на уровне APC. Потоки, работающие на уровне APC, соответственно не получают запросы своего же уровня АРС, которые система использует для операций завершения ввода/вывода.
  • 2-й уровень IRQL (DPC/DISPATCH):
    • используется для обработки отложенных вызовов процедур (Deferred procedure call, DPC): Отложенные вызовы процедур - это подпрограммы обратного вызова, которые отложены для выполнения до того момента, когда произойдет переключение на уровень IRQL DISPATCH; Обычно DPC запрашиваются с высоких уровней IRQL с целью осуществления дополнительной работы, для которой затрачиваемое процессорное время не критично. Это довольно важная для производительности стадия, и сейчас я объясню почему. Драйверы устройств стараются выполнять минимально-возможное количество операций внутри собственных подпрограмм обработки прерывания (ISR), чтобы не занимать продолжительное время на уровне DIRQL, тем самым не блокируя остальные прерывания и не тормозя, в итоге, всю систему.

      Чем выше уровень IRQL, тем меньше возможности процесса. Это побуждает разработчиков на высоком уровне IRQL выполнять только самые необходимые операции, а все остальные действия производить на низком.

      Если драйвер понимает, что требуется выполнение дополнительной работы, которая занимает существенное процессорное время, то он запрашивает DPC и перекладывает на него эту задачу. Когда уровень IRQL опускается до DISPATCH, происходит обратный вызов отложенной функции драйвера, которая и выполняет оставшуюся часть обработки. Реализуя подобный алгоритм на уровне IRQL DISPATCH, драйвер проводит на уровне DIRQL меньшее количество времени, и соответственно, уменьшает время задержки на обработку собственного прерывания, тем самым освобождая его для других устройств системы.

    • используется для выполнения задач планировщика: Как вы знаете, в операционных системах линейки Windows NT реализована вытесняющая многозадачность, которая означает, что каждому процессу, выполняющемуся в операционной системе, выделяется для выполнения определенное время. Поскольку IRQL планировщика потоков и DPC равен 2, то он выше приоритета пользовательских потоков (исполняемых на уровне 0). В свою очередь приоритет планировщика ниже чем приоритет аппаратных прерываний (прерываний от устройств), то есть он может быть прерван аппаратными прерываниями.

Хорошо, но я так и не понял, почему нельзя было отказаться от всех этих уровней и сделать "плоскую" модель очередей, либо выполнять все эти типы задач по мере поступления? Давайте смоделируем рабочую ситуацию:
представим какой-либо код, например небольшую программу, написанную "на коленке". Вот мы запустили её на выполнение, соответственно в системе сформировался процесс для нашей программы, в контексте которого начал выполняться основной поток. Типовой поток (режима пользователя или режима ядра) исполняется на самом низшем уровне IRQL PASSIVE. На протяжении всего времени выполнения потока, часы (микросхема таймера) периодически генерирует собственные прерывания для отсчета временных интервалов, которые используются для указания операционной системе о прохождении заданного промежутка времени. Процедура обработки прерывания часов выполняется на уровне IRQL CLOCK, который (если посмотреть в таблицу) выше по приоритету большинства уровней: и уровня DISPATCH, на котором выполняется планировщик, и уровня PASSIVE, на котором выполняется наша программа. Таким образом таймер постоянно вытесняет работу и планировщика и нашей программы. С каждым переданным тиком таймера, процедура обработки прерывания таймера уменьшает остающийся у выполняющегося в данный момент нашего пользовательского потока квант времени. В момент, когда квант времени выполняющегося потока уменьшается до нуля, программа обработки прерывания часов генерирует прерывание уровня DISPATCH, тем самым вызывая запуск планировщика для выбора им следующего потока для выполнения. По факту генерирования прерывания уровня DISPATCH, процедура обработки прерывания таймера заканчивает исполнение своего кода и управление возвращается ядру системы. Ядро находит в очереди запросов следующее прерывание с наиболее приоритетным уровнем, находящееся в режиме ожидания. Каждое прерывание обслуживается по очереди. Когда все прерывания выше уровня DISPATCH обслужены, то выполняется процедура обработки прерывания уровня DISPATCH. Эта программа обработки прерывания обрабатывает список DPC и затем вызывает планировщик. Планировщик обнаруживает, что квант времени текущего потока исчерпан, то есть уменьшен до нуля, после чего Планировщик выполняет алгоритм планирования для выбора следующего потока на выполнение. Код поставленного на выполнение потока будет выполнен когда система опустится на уровень IRQL PASSIVE.
Таким вот образом реализуется приоритеты, и, соответственно, вытесняющая многозадачность. Теперь представьте, что вы уберете из системы иерархию уровней запросов прерываний, как в этом случае будет вести себя система? В этой ситуации было бы непонятно что и когда выполнять, система выполняла бы все поступающие задачи в порядке очереди, что привело бы к тому, что потоки запросто могли бы вытеснить планировщик и тем самым вообще разрушить или полностью вывести из стоя вытесняющую многозадачность, что повлекло бы за собой непредсказуемую работу ОС. Таким образом:

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

соответственно:

IRQL указывает приоритет кода, исполняющегося на процессоре по отношению к прерываниям и другим асинхронным (внезапным) событиям.

Назначение уровней IRQL в системе следующие:

  1. Маскировка: повышение уровня прерывания позволяет отрезать (замасировать) низлежащие уровни аппаратных прерываний на контроллере PIC. Это позволяет на время проигнорировать прерывания, возникающие на более низких уровнях, тем самым выигрывая время на выполнение процедуры обработки аппаратного прерывания на данном уровне.
  2. Аппаратная синхронизация: синхронизация данных между потоками, выполняющимися на разных процессорах/ядрах в многопроцессорной системе.
  3. Программная синхронизация: для определения когда различные APC/DPC-процедуры могут быть обслужены, для определения когда могут быть обслужены приложения пользовательского режима.

Тем самым, на глобальном уровне механизм IRQL позволяет подпрограмме операционной системы:

  • Управлять повторной входимостью (реентерабельность)
  • Гарантировать, что она может продолжать работу без приоритетного прерывания (вытеснения) некоторыми другими действиями.

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

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

Код драйвера может выполняться на разных уровнях IRQL.

И отсюда следует два достаточно важных вывода:

  1. Код драйвера является вытесняемым и прерываемым. Как и любой другой код в системе, он может быть прерван в любой момент по окончании выделенного кванта времени;
  2. Код драйвера должен использовать те или иные наборы системных функций в зависимости от уровня IRQL, на котором он выполняется.

Представьте ситуацию, когда код драйвера выполняется на низком уровне IRQL, модифицирует какой-либо объект (например, файл file.txt ), затем другой код на более высоком уровне IRQL внезапно прерывает его выполнение и модифицирует тот же файл file.txt другими данными. Когда управление вернется к нашему драйверу, он продолжит модификацию файла своими данным, тем самым затерев данные, поступившие от другого источника. Таким образом файл войдет в рассогласованное состояние. Для решения подобных проблем были введены различные системные объекты синхронизации. Для того, что бы код уровня ядра мог модифицировать определенные типы данных, объекты взаимного исключения, он должен сперва получить владение блокировками.

Концепция драйвера

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

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

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

то же, но другими словами:

Драйвер - интерфейс между кодом пользовательского режима, режима ядра и функциями физического/логического/виртуального устройства.

Одно из приведенных определений отмечает немаловажную особенность драйвера: ошибочно представлять драйвер исключительно во взаимодействии с физическим устройством, поскольку драйвер не обязательно должен предоставлять доступ к функциям какого-либо оборудования, он может обеспечивать и исключительно программные функциональные особенности. Примерами подобных решений являются драйвера, устанавливаемые в систему антивирусами, системами шифрования данных, системами мониторинга. Общий алгоритм работы любого драйвера следующий: приложения посредством функций специального пользовательского интерфейса (в Windows это API Win32) или запросов ввода-вывода опосредовано/напрямую обращаются к функциям драйвера некоего устройства. Драйвер, в свою очередь, предоставляет доступ к функциональным особенностям интересующего устройства, а так же контролирует процесс взаимодействия между запросами приложений и непосредственно устройством. Естественно, что в драйвере должны быть определены (описаны) все принципы взаимодействия с обслуживаемым (подчиненным, собственным) устройством, должен присутствовать набор данных об управляемом объекте, инструкции (набор команд), с помощью которых системный/пользовательский код может корректно инициализировать устройство и начать с ним взаимодействие.

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

Очень интересно было бы увидеть, на какой именно стадии загрузки операционной системы начинает загружается и начинает выполняться первый драйвер Windows? Однако в детальном изложении процесс этот достаточно нетривиален и для глубокого понимания требует реверсинга кода многих компонентов загрузки, в дополнение ко всему необходимо учитывать множество сопутствующих моментов, как то: последовательность загрузки, обусловленную зависимостью между драйверами, по причине которой драйвера могут группироваться в так называемые "группы загрузки", сама загрузка драйверов может разделяться на несколько этапов и прочее. При этом, следует учесть, что в Сети имеется большое количество материалов относительно устаревших уже операционных систем, поэтому мы попытаемся актуализировать процесс загрузки драйверов Windows на примере (наиболее близкой мне по духу) операционной системы Windows 7. И для начала не мешало бы рассказать об основных компонентах ядра Windows, активно участвующих в процессе загрузки драйверов:

  • Диспетчер (менеджер) ввода/вывода (I/O Manager) - модуль режима ядра, входящий в состав исполнительной подсистемы, управляющий процессами ввода/вывода, обеспечивающий абстракцию физических и логических устройств для пользовательских приложений и системных компонентов, связывающий приложения пользовательского режима с драйверами. Контролирует стадии процесса взаимодействия с драйверами. Весь обмен данными менеджера ввода-вывода с драйверами осуществляется через обращение к процедурам обратного вызова драйвера (callback) и передачи им стандартизованной структуры данных IRP, в которой описана вся суть обращения к драйверу;
  • Диспетчер (менеджер) Plug-and-Play (PnP Manager) - модуль режима ядра и пользовательского режима, входящий в состав исполнительной подсистемы, отвечающий за добавление, распознавание, удаление устройств в операционной системе. Часть режима ядра взаимодействует с остальными компонентами системы и драйверами в процессе установки (загрузки) программного обеспечения, необходимого для обслуживания имеющихся в системе устройств. Часть пользовательского режима отвечает за взаимодействие с программами режим пользователя (для интерактивного взаимодействия с пользователем) в ситуациях, требующих установки новых драйверов или настройки рабочих параметров в существующих. Управляет распределением аппаратных ресурсов в системе, так же умеет распознавать устройства, реагировать на их подключение/отключение, загружать соответствующие драйвера при обнаружении новых устройств;
  • Диспетчер (менеджер) управления службами (Service Control Manager, SCM) - системный процесс, ответственный за создание, удаление, запуск и остановку служб и драйверов операционной системы. Так же обеспечивает: функционирование журнала событий, поддержку технологии удалённого вызова процедур (remote procedure call, RPC);

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

  1. Bootmgr(.efi) загружает модуль winload(.efi) и передает ему управление.
  2. Winload(.efi) сканирует куст реестра HKEY_LOCAL_MACHINE\System\services и получает список всех установленных в системе драйверов. В этом кусте реестра присутствуют разделы, сопоставляемые с конечными драйверами, в них присутствуют разнообразные относящиеся к драйверам параметры, такие как Group , Start , Type , LoadOrderGroup , DependOnGroup , DependOnServices , определяющие те или иные критерии загрузки драйвера.
  3. Winload(.efi) загружает драйвера, критичные для начальной стадии загрузки/функционирования операционной системы, такие как драйвера контроллеров накопителей, драйвера файловых систем. Очевидно, что подобные драйвера имеют наивысший приоритет, поскольку создают базис для загрузки остальных драйверов, поэтому в следствии этих а так же иных причин должны находиться в памяти в момент передачи управления ядру. Соответственно, маркируются они специальным типом SERVICE_BOOT_START . Драйвера на данном этапе начинают загружаться в зависимости от групп, к которым они принадлежат.
  4. Winload(.efi) загружает непосредственно ядро из файла ntoskrnl.exe и передает ему управление.
  5. Ядро загружает Менеджер ввода-вывода и PnP-менеджер.
  6. Менеджер ввода-вывода создает глобальный каталог. Этот каталог, в дальнейшем, используется для регистрации объектов устройств.
  7. PnP-менеджер стартует драйвера, уже загруженные в память на предыдущем этапе (имеющие тип SERVICE_BOOT_START), вызывая процедуру DriverEntry каждого драйвера. На данном этапе загружаются и зависимые драйвера.
  8. PnP-менеджер строит дерево устройств системы, обходит его начиная с корня и загружает драйвера устройств, которые еще не были загружены.
  9. PnP-менеджер загружает оставшиеся незагруженными драйвера устройств, вне зависимости от значения параметра Start . Многие из подобных драйверов имеют тип SERVICE_DEMAND_START .
  10. PnP менеджер загружает драйвера расширенного функционала. К таким драйверам относятся драйвер видеоадаптера, драйвера внешних устройств, драйвера стека TCP/IP. Такие драйвера имеют тип SERVICE_SYSTEM_START .
  11. Ядро загружает Менеджер (диспетчер) управления сеансами/сессиями (Session Manager Subsystem Service, SMSS), который, в свою очередь, загружает Менеджер (диспетчер) управления службами (SCM). SCM сканирует куст реестра (HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services ) и на основе полученной информации монтирует внутреннюю базу данных служб/драйверов, формирует программный интерфейс для обслуживания установленных служб/драйверов. SCM загружает "автозапускаемые" не-PnP драйвера (имеющие тип SERVICE_AUTO_START), а также все драйвера, от которых они зависят.

Из всего этого алгоритма загрузки драйверов нам необходимо уяснить следующие основные правила: драйвер может быть загружен (в зависимости от стадии/класса драйвера) при помощи PnP-менеджера, либо с помощью SCM, а вот в процессе функционирования драйвера активно принимает участие Менеджер ввода-вывода.

Структура драйвера Windows

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

Драйвер - это своего рода "библиотека режима ядра", обычный файл DLL, у которого в PE-заголовке (структура IMAGE_NT_HEADERS , подструктура OptionalHeader) значение поля Subsystem = 1 (IMAGE_SUBSYSTEM_NATIVE).

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

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

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

  • Объекты. Блоки данных, содержащие записи свойств той или иной сущности операционной системы. Управляются диспетчером (менеджером) объектов. Многие объекты имеют дескрипторы (описатели), при помощи которых объект становится доступным для приложений.
  • Структуры данных. Блоки данных, содержащие записи свойств той или иной сущности операционной системы. Управляются ядром. Отличаются от объектов, однако (по инерции) так же называются объектами

Поэтому (с большим натягом) все внутренние структуры операционной системы Windows называют объектами.
Теперь вернемся к процедурам драйвера, на деле так называемые "процедуры" драйвера являются COM-объектами обратного вызова, которые обрабатывают поступающие от соответствующих объектов инфраструктуры операционной системы события, говорится что драйвер предоставляет ядру операционной системы COM-интерфейс, заданный серией процедур, реализуемых драйвером. Экспорт, то есть публикация (объявление) процедур драйвера для дальнейшего обращения к ним извне, выполняется путем регистрации в основной процедуре драйвера (стандартной для всех драйверов), носящей название DriverEntry .

Основное назначение функции DriverEntry состоит в том, чтобы разработчик драйвера реализовал в ней заполнение объекта (записей структуры) драйвера указателями на различные внутренние процедуры драйвера, обеспечивающие тот или иной функционал. В процедуре DriverEntry можно задавать (менять) имя объекта устройства, которое впоследствии используется приложениями для открытия дескриптора устройства и отправки пакетов запросов ввода-вывода (IRP).

Функция DriverEntry фактически является функцией глобальной инициализации и выполняется единожды на этапе загрузки драйвера. Эта функция может быть как предельно простой, так и содержать расширенный функционал (дополнительные подпрограммы), такой, например, как создание дополнительных объектов устройств, опрос устройства, дополнительные фазы конфигурации и инициализации устройств(а).
После публикации собственных функций драйвер становится "видимым" ядром операционной системы. Дабы не усложнять и без того достаточно непростую теорию, будем считать, что с точки зрения ядра Windows любое устройство является неким абстрактным "виртуальным устройством", оперирующим стандартизированным набором команд, и доступным через внутренние интерфейсы. Как было уже сказано выше, в ядре операционной системы Windows присутствует специальный модуль исполнительной системы, называемый диспетчером (менеджером) ввода-вывода , обеспечивающий единый интерфейс взаимодействия для всех драйверов режима ядра, включая драйверы физических устройств, драйверы логических устройств и драйверы файловых систем. Соответственно, система ввода-вывода ядра управляет драйверами, или можно сказать, что драйверы используют интерфейс диспетчера ввода-вывода для обеспечения функционирования в операционной системе. С дургой стороны, драйвер обеспечивает преобразование (конвертацию) "стандартных команд", поступающих от операционной системы, в команды, которые "понимает" подконтрольное ему устройство (если оно имеется), и наоборот. Менеджер ввода-вывода определяет набор (множество) стандартных процедур, которые могут быть реализованы в драйвере, поскольку:

Драйвер содержит набор процедур обратного вызова, которые обеспечивают различные стадии процесса ввода-вывода.

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

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

  • Инициализация - Менеджер ввода-вывода запускает процедуру инициализации (носит название DriverEntry), которая предназначается для проведения действий по начальной настройке объекта драйвера, регистрации всех иных процедур драйвера, конфигурированию подчиненного устройства и выполнении иных действия в интересах разработчика.
  • Добавление устройства - добавление (дополнительного) объекта "устройство". В данной процедуре драйвер обычно создает объекты "устройство" для каждого устройства, обслуживаемого драйвером. Обычно используется для Plug-and-Play драйверов.
  • Обработка - набор процедур диспетчеризации (обработки различных состояний). Открытие, закрытие, чтение, запись в устройство, обработка состояний питания, событий PnP и состояний системы, а так же некоторые иные виды взаимодействия описываются в процедурах диспетчеризации. Фактически это основные процедуры, поскольку через процедуры диспетчеризации обрабатываются типовые операции ввода-вывода.
  • Запуск (начало) ввода-вывода - вторая стадия обработки запроса ввода-вывода к устройству, непосредственно стартующая ввод-вывод устройства. Эта процедура может использоваться для начала передачи данных в/из устройства.
  • Процедура обслуживания прерывания - когда устройство генерирует прерывание, диспетчер прерываний передает управление на данную процедуру.
  • Обработка отложенных вызовов процедур - Процедура DPC берет на себя основную работу по обработке прерывания после выполнения ISR. Отложенные вызовы процедур выполняются на низких уровнях IRQL (DPC/DISPATCH) чем сама процедура ISR. Реализуется подобный алгоритм для исключения блокировки других прерываний.
  • Процедура завершения ввода-вывода - многоуровневый драйвер может иметь процедуры завершения ввода-вывод, которые уведомляют о завершении обработки IRP низкоуровневым драйвером.
  • Процедуры отмены ввода-вывода - если операции ввода-вывода могут быть прерваны, драйвер может определить одну или несколько подобных процедур. Когда драйвер получает IRP-пакет для запроса ввода-вывода, который может быть отменен, он назначает процедуру отмены IRP, и пакет IRP проходит через различные стадии обработки, которые эта процедура может изменить или убрать, если текущая операция не отменяема.
  • Процедура быстрой отправки - Драйвера, которые активно используют Менеджер кеша, такие как драйвера файловых систем, обычно предоставляют подобные процедуры для обеспечения возможности обхода ядром типовых алгоритмов обработки ввода-вывода.
  • Процедура выгрузки - должны быть реализованы в каждом драйвере, который работает (освобождают/занимают) с системными ресурсами, для того, чтобы Диспетчер ввода-вывода выгрузить драйвер из памяти.
  • Процедура предупреждения о завершении - позволяет драйверу освободить все занимаемые ресурсы при завершении работы системы.

Становится очевидным, что в процессе разработки драйвера Windows не стоит задачи реализовать весь набор описанных выше процедур, каждый драйвер уникален и разработчик волен обеспечивать собственный набор реализаций, поддерживаемых драйвером. Когда драйвер при помощи PnP-менеджера или SCM загружается в систему, диспетчер ввода-вывода создает в пространстве имен объект "драйвер" (driver object) и вызывает процедуру инициализации драйвера (обычно это DriverEntry), которая выполняет дальнейшие действия по инициализации.

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

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

  • PnP-драйверы создают объекты "устройство" с помощью своих процедур добавления устройств, когда PnP-менеджер информирует их о присутствии управляемого ими устройства.
  • не-PnP-драйверы создают объекты "устройство" при вызове менеджером ввода-вывода их процедур инициализации.

При создании объекта типа "устройство" (device), драйверу требуется присвоить данному объекту имя. Затем этот вновь созданный объект помещается в пространство имен диспетчера объектов (Object Manager), который, как и диспетчер (менеджер) ввода-вывода, является частью исполнительной подсистемы ядра. Менеджер объектов предназначается для ведения базы всех ресурсов операционной системы, представленных в качестве объектов. Имя объекта может определяться самим драйвером в явном виде, либо генерироваться автоматически менеджером ввода-вывода. По соглашению, объекты "устройство" должны размещаться в каталоге \Device пространства имен менеджера объектов, недоступном приложениям через Win32 API. А для того, чтобы объект "устройство" стал доступным для приложений, драйвер должен создать в каталоге \GLOBAL?? символьную ссылку на имя этого объекта в каталоге \Device . Драйверы, не поддерживающие технологию Plug-and-Play, и драйверы файловой системы обычно создают символьную ссылку с общеизвестным именем (скажем, \Device\VMwareKbdFilter). Только после всех перечисленных действий драйвер становится "виден" в системе и доступен для вызова пользовательскими приложениями.

Взаимодействие с драйвером

Каким же образом пользовательская программа может взаимодействовать с драйвером в системе? На этот случай имеется два способа:

  1. Неявный -- вызов типовой функции Win32 API;
  2. Явный -- прямой запрос ввода-вывода к драйверу;

Ну с первым случаем все достаточно просто, в прикладной программе вызывается какая-либо ординарная функция Win32 API (например, CreateFile), которая, затем, в зависимости от целевого объекта (файла, каталога) может вызвать в цепочке своих вызовов функцию обмена с драйвером. Фактически, в этом случае код приложения не ставит своей задачей взаимодействовать с каким-либо драйвером, просто по цепочке вызовов процедур, на определенном этапе выполнение уходит в режим ядра и там происходит вызов функции драйвера. Все это остается сокрытым от разработчика, однако возможно отследить взаимодействие при помощи отладочных средств.
Второй случай более интересен, он возникает когда под вызовом драйвера подразумевается не косвенный вызов (посредством вызова типовой функции), а передача при помощи специальной функции (например, DeviceIoControl) так называемого запроса ввода/вывода (I/O control request), который, в дальнейшем, инициирует формирование блока данных под названием пакета запроса ввода-вывода.

Пакет запроса ввода-вывода (IRP, I/O Request Packet) - структура данных ядра Windows, содержащая информацию, описывающую запрос ввода-вывода.

Формально IRP это пакет, но фактически это объект ядра, то есть структура (блок) данных с набором процедур для менеджера ввода-вывода, обеспечивающая обмен данными между программой и драйвером, либо между драйвером и драйвером. Как мы уже упоминали, архитектура Windows построена таким образом, что в ней запрещено прямое взаимодействие программы режима пользователя и драйвера, поэтому подобный обмен сводится к посылке программой кода IOCTL, который уже приводит к формированию менеджером ввода-вывода IRP пакета запроса. Именно менеджер ввода-вывода, как ответственный за взаимодействие с драйверами, оперирует пакетами IRP. Менеджер ввода-вывода получается запрос на ввод-вывод от пользовательской программы, затем формирует IRP и передает его соответствующему драйверу.
Пакет IRP состоит из двух частей:

  • постоянной части;
  • стека размещения ввода-вывода.

В постоянной части IRP содержит старший и (не всегда) младший код функции. Старшие коды: IRP_MJ_CREATE , IRP_MJ_CLOSE , IRP_MJ_READ , IRP_MJ_WRITE , IRP_MJ_CLEANUP , IRP_MJ_DEVICE_CONTROL , IRP_MJ_INTERNAL_DEVICE_CONTROL , IRP_MJ_SCSI , IRP_MJ_SYSTEM_CONTROL , IRP_MJ_POWER , IRP_MJ_PNP , IRP_MJ_SHUTDOWN . Пакет так же содержит стек размещения ввода-вывода - специальную структуру IO_STACK_LOCATION , содержащую определенные параметры: это набор устройств, которые обработают данный IRP пакет. Причем по стеку этот пакет передается последовательно от устройства к устройству. Более чем одно размещение стека говорит о том, что IRP может быть обработан несколькими драйверами. "Ячейки стека" IRP и предназначены для хранения "переменной" информации при хождении пакета IRP по стеку драйверов. Пакет IRP проходит по опубликованным процедурам каждого драйвера, каждая из которых извлекает из "своей" ячейки стека размещения ввода-вывода необходимую ей информацию. Процедуры драйвера традиционно называются "процедуры обратного вызова" (callback). Как мы уже упоминали, функция инициализации драйвера DriverEtnry сообщает ядру (публикует) имена этих процедур и позже ядро само вызывает ту или иную процедуру при определенных обстоятельствах.
В отличие от штатной программы, драйвер не является классическим процессом со своим адресным пространством и не имеет потока исполнения. Вместо этого, функция драйвера выполняется в контексте того потока и процесса, в котором она была вызвана. Контекст (пространство выполнения кода) драйвера зависит от того, кто производит обращение (вызывает) к драйверу. Обращение может быть инициировано:

  1. Прикладной программой (программой пользовательского режима). В этом случае контекст исполнения драйвера точно известен, и он совпадает контекстом прикладной программы;
  2. Другим (сторонним) драйвером. В этом случае контекст исполнения определить сложнее, он может быть как известным, так и случайным, это зависит от контекста исполнения функции вызывающего драйвера.
  3. Аппаратным/программным прерыванием. В этом случае контекст исполнения случайный, поскольку прерывание (и, соответственно, переключение на код драйвера) может произойти при выполнении абсолютно любого кода в операционной системе.

Опять же, в отличии от штатной программы, драйвер не может вызывать стандартные функции Win32 API, может лишь оперировать доступными в ядре функциями, которые начинаются с префиксов Ex.. , Hal.. , Io.. , Ke.. , Ks.. , Mm.. , Ob.. , Po.. , Ps.. , Rtl.. , Se.. , Zw.. и некоторых других.

Виды (типы) драйверов Windows

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

  • Драйверы классов (Class driver) - драйверы, разработанные Microsoft для определенного класса устройств.
  • Драйверы файловых систем (File System Drivers) - драйверы, реализовывающие файловые системы на различного рода носителях информации.
  • Унаследованные драйвера (Legacy drivers) - "устаревшие" (совместимые по структуре со старыми версиями ОС) драйверы режима ядра, самостоятельно напрямую контролирующие подчиненное устройство без каких-либо дополнительных драйверов устройства. Почему они носят такое название? Потому, что это тип драйверов, сохранившийся от первых версий ОС линейки Windows NT.
  • Драйвер шины (Bus driver) - Драйверы, обеспечивающие функционал какой-либо шины компьютера (ISA,PCI,USB,IEEE1394 и прочих);
  • Фильтрующие драйверы (Filter driver) - драйверы, использующиеся для мониторинга/изменения логики другого драйвера путем работы с данными, проходящими через него.
    • Верхние фильтрующие драйверы (Upper-filter drivers) - подтип фильтрующих драйверов, находящийся выше функционального драйвера по стеку. Через верхние фильтрующие драйверы проходят все запросы, а это значит, что они могут изменять и/или фильтровать информацию, идущую к функциональному драйверу, ну и далее, возможно, к устройству. Примерами могут являться фильтр-драйвер, который отслеживает/фильтрует трафик, шифрует/перехватывает запросы чтения/записи. Такие драйверы используются в брандмауэрах.
    • Нижние фильтрующие драйверы (Lower-filter drivers) - подтип фильтрующих драйверов, находящийся ниже функционального драйвера по стеку. Через подобные нижние фильтрующие драйверы проходит, как правило, меньше запросов по сравнению с остальными фильтрующими драйверами, потому как большинство запросов выполняет и завершает сам функциональный драйвер.
  • Функциональные драйверы (Function driver) - драйверы, функционирующие самостоятельно и определяющие все аспекты, связанные с устройством.
  • PnP драйвер (PnP Driver) - драйвер, поддерживающий технологию Plug-and-Play;
  • Минидрайвер (минипорт, миникласс) (Miniport driver, Minidriver, Miniclass driver) - драйверы, которые используют драйвера класса для управления устройством. Действуют как одна из частей пары драйверов, в которой данная категория действует как драйвера конечных устройств, выполняющая специфичные задачи устройства.

По уровню компонетизации драйверы бывают:

  • Одноуровневые - обработка ввода/вывода реализуется в рамках одного исполняемого модуля (драйвера).
  • Многоуровневые - обработчка ввода/вывода распределяется между несколькими драйверами.

PnP драйвера под Windows подразделяются на:

  • Функциональный Драйвер
  • Драйвер шины (шинный драйвер)
  • Драйвер-фильтр (фильтр-драйвер)

По режиму выполнения драйверы Windows градируются:

  • Драйвер пользовательского режима.
  • Драйвер режима ядра.

Модели драйверов

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

Модель WDM

Когда-то очень давно существовало две основных направления развития драйверной концепции Windows:

  1. в Windows 95/98 применялась модель VxD (Virtual Device Driver);
  2. в Windows NT3.51 параллельно развивалась модель NT-драйвер (драйвер в стиле NT, NT Driver).

Однако, начиная с версии Windows 98/NT4.0 разработчики предприняли попытку унифицировать (универсализировать) разработку драйверов, в следствии чего на смену упомянутым моделям пришла новая модель WDM.

WDM (Модель драйвера Windows, Windows Driver Model) - единая среда разработки (фреймворк) для драйверов устройств операционной системы Windows. Была создана для уменьшения кода стандартизации требований к драйверам.

Модель WDM являлся этапом переопределения классического стека драйвера Windows с целью обеспечения поддержки являющихся в то время революционными технологий Plug-and-Play и ACPI. Модель дает возможность загружать/выгружать драйверы "на лету", без необходимости в перезагрузке операционной системы, разрабатывать драйвера в виде расширений (фильтров) к стандартным системным драйверам, более гибко управлять энергосбережением и конфигурацией устройств и прочее.
В рамках модели WDM любое аппаратного устройство поддерживается, как минимум, двумя драйверами:

  • Функциональный драйвер (Function driver) - ответственен почти за все функциональные особенности обслуживаемого устройства: операции ввода-вывода, обработка прерывания и управление устройством;
  • Драйвер шины (Bus driver) - ответственен за обслуживание соединения между устройством и компьютером, фактически поддержкой связующей шины (например, PCI, USB и прочие).

Модель WDF

На протяжении всего времени развития, модель WDM претерпевала множество изменений, существенно разрастаясь. Начиная с Windows Vista была предпринята очередная попытка развития концепции драйвера Windows, в сущности уже существовавшей на тот момент модели WDM, результатом чего явилось новой модели (надстройки над WDM) под названием WDF.

WDF (Основа драйверов Windows, Windows Driver Foundation) - среда разработки (набор инструментальных средств), облегчающих разработку драйверов устройств для операционных систем Windows (Windows 2000 и более поздних).

Связано это было с тем неоспоримым фактом, что разработчикам не удалось достичь достаточного уровня абстракции модели WDM, а именно недостаточной интеграцией подсистемы ввода-вывода с технологией Plug-and-Play и управлением питанием. Это приводило к тому, что на разработчике драйвера лежала громадная нагрузка по синхронизации этих самых запросов ввода-вывода с событиями Plug-and-Play и запросами энергопотребления. Очевидно, требовалось дальнейшее упрощение драйверной модели. WDF пришла на смену WDM и считается наиболее современной моделью.
WDF реализует следующие возможности:

  1. "Вынесение" некоторых некритичных к режиму исполнения классов драйверов в пользовательский режим, что дало сокращение общего количества сбоев в ядре.
  2. Большая часть обработки взаимодействия подсистемы ввода-вывода с Plug-and-Play и управлением электропитанием выполняется теперь встроенными механизмами модели WDF.
  3. Предоставление новых внутренних интерфейсов модели WDF, которые позволяют абстрагироваться от более сложных для понимания системных интерфейсов; В модели WDM/legacy довольно сложно реализовать логику некоторых частей взаимодействия с драйвером, не изучив все азы сложной архитектуры ядра, WDF же позволяет автоматизировать многие виды взаимодействия; Большое количество кода при разработке WDM-драйвера теперь может быть заменено вызовами процедур WDF.
  4. Возможность создания "канонического" драйвера. Присутствие шаблонов, которые предоставляют стороннему разработчику возможность переопределения уникальных для его драйвера критериев, тем самым сокращая время на разработку.

Модель WDF подразделяется на два направления:

  • UMDF (Kernel-Mode Driver Framework) - среда разработки драйвера режима ядра.
  • KMDF (User-Mode Driver Framework) - среда разработки драйвера режима пользователя.

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