Драйвер может быть связан с виртуальным устройством
Первая статья про драйверы была уж совсем вводной, и мне подумалось, что её нельзя не дополнить рассказом про то, как устроены драйверы более современных устройств.
Для начала введём определение bus master: устройство, способное быть не только ведомым, но и ведущим на шине компьютера. То есть — не только отвечать на транзакции ввода-вывода, инициированные процессором, но и самостоятельно их инициировать — по собственной инициативе «ходить» в память.
История таких устройств уходит корнями в понятие DMA: ещё во времена прародителя микропроцессоров, микропроцессора 8080 (КР5080ИК80), появилось понимание, что процессор хорошо бы разгрузить от рутинной операции перетаскивания байтиков между устройствами в-в и памятью.
Контроллер DMA (Direct Memory Access) был внешней по отношению к устройству ввода-вывода подсистемой, которую нужно было явно запрограммировать — установить тип операции (пишем в память, читаем из памяти, копируем память-память), адрес(а) памяти, и пр. Собственно, я совершенно несправедливо пишу об этом в прошедшем времени — всё это вполне существует и сейчас, например, в микроконтроллерах.
Уже в режиме DMA работа драйвера выглядит сущственно иначе — от драйвера требуется не выполнять ввод-вывод, а подготовить настройки для устройства, активировать его, дождаться прерывания по окончанию ввода-вывода, и проверить успешность операции. Всё сказанное в предыдущей статье верно и для DMA устройств, но в дополнение к сказанному, драйвер должен понимать схему взаимодействия устройства и DMA контроллера, а иногда и явно аллоцировать и настраивать контроллер: если в старых устройствах привязка порта ввода-вывода к контроллеру DMA делалась фиксированно, то сейчас во многих случаях возможен полный роутинг или выбор канала DMA из 2-4 вариантов.
Отдельно следует заметить, что сама инициация очередной транзакции ввода-вывода может быть автоматической (DMA лупит с максимально возможной скоростью), автоматической с настройкой темпа (чтобы не съесть всю пропускную способность шины) или по событию.
При этом событием в развитых системах может быть прерывание, просто изменение состояния ножки микроконтроллера, или же источником события может быть другое устройство. Например, таймер. Это позволяет сопрячь воедино ЦАП, DMA engine и таймер так, чтобы подача очередного байта в ЦАП происходила с заданной (таймером) частотой. Есть и другие варианты агрегирования устройств, например, включение одного канала DMA по окончании работы другого. Без привлечения внимания процессора.
Уместно также сказать, что DMA контроллеры иногда умеют явно сопрягать пару каналов, чтобы обеспечивать непрерывность потока данных по окончании работы одного канала запускается второй и генерируется прерывание, по которому процессор снова загружает работой первый канал — для того же ЦАП это может быть жизненно важно.
Вернёмся из мира контроллеров во «взрослые» машины. Большинство современных подсистем ввода-вывода уже не базируются на внешнем DMA, а имеют его аналог прямо внутри.
Это устройства с режимом «мастер шины», bus master.
Проще всего их представить именно как устройства, имеющие встроенный в себя, личный и оптимально устроенный контроллер DMA.
Обычно такие устройства управляются через дерево дескрипторов в памяти: у устройства есть специальный регистр, в который процессор помещает адрес структуры в памяти, которая содержит задание для контроллера. Или, чаще, массив или список структур с такими заданиями. Контроллер самостоятельно читает из памяти задания и выполняет их шаг за шагом. Задание, как правило, состоит из идентификатора операции, адреса в памяти, где брать данные и дополнительных параметров, необходимых для выполнения операции. Например: < запись на диск, адрес на диске, адрес буфера в памяти >. Так устроены современные контроллеры всего: диска, USB, сетевого интерфейса.
Кроме структуры дескрипторов для такого устройства требуются ещё инструменты для обмена событиями: процессор должен уметь сообщить, что изменил или дополнил дескрипторы, а устройство — что закончило ввод-вывод частично или полностью. Второе выполняется, естественно, через прерывания, а для первого часто применяется регистр (дверной звонок — doorbell), в который процессор «стучится», чтобы обратить внимание устройства на изменения.
При этом есть опасность изменить именно то, что устройство сейчас обрабатывает, что накладывает дополнительные ограничения на структуру драйвера.
Отдельно в этом ряду стоят virtio устройства. Появились они как следствие победного шествия гипервизоров по миру. Традиционно гипервизор предлагал гостевой ОС некоторый набор виртуальных устройств, которые копировали то или иное популярное физическое устройство. Известную сетевую карту или дисковый контроллер. Но эмулировать «железное» устройство тяжело, неудобно и муторно — зачастую, приходится поддерживать совершенно не нужные в виртуальном мире свойства, при этом для целей виртуализации структура реального железного устройства, обычно, неоптимальна.
Это и навело авторов на то, чтобы спроектировать заведомо виртуальные устройства, которые никогда не будут (never say never © 007) реализованы в железе и нужны исключительно для общения гипервизора и гостевой ОС. Они созданы так, чтобы для большого числа разнотипных устройств можно было реализовать общую единообразную инфраструктуру, как в ядре гостевой ОС, так и в гипервизоре.
По сути драйвер virtio — это транспорт пакетов с запросами и ответами между гостевой ОС и гипервизором. Содержание пакета специфично для типа драйвера и его режима. Например, для сетевой карты это адрес пакета ethernet, а для диска — scatter-gather дескриптор с указанием типа дисковой операции и адреса на диске.
Кроме того, стандарт virtio поддерживает возможность стандартным образом ядру и устройству договариваться о режиме работ и поддерживаемых функциях. Например, сетевой драйвер virtio может уметь или не уметь считать и вставлять в отправляемые IP-пакеты контрольную сумму.
Нетрудно видеть, что стандарт virtio описывает довольно типовой обобщённый драйвер bus master устройства: мы передаём «устройству» запрос с адресом в памяти и параметрами запроса ввода-вывода, остальное происходит асинхронно.
На фоне вышесказанного говорить про DPC уже не так актуально, но раз в комментариях возникла дискуссия — дам краткое описание.
В некоторых ОС (Фантом «срисовал» это с NT, откуда они срисовали — не знаю) существует штатная поддержка запуска кода внутри «лёгких» нитей — Deferred Procedure Call. Это позволяет понизить время нахождения драйвера в прерывании: хендлер прерывания лишь фиксирует событие и, как максимум, считывает из устройства статус — один регистр. Остальное делается в DPC, которая быстро активируется и доделывает начатое.
Откровенно сказать, смысла в этом не так уж много — проще запустить в драйвере его собственную нить высокоприоритетную и делать ввод-вывод из неё. Однако, могут быть варианты. Можно выделить DPC группу приоритетов и гарантировать им приоритет всегда более высокий, чем у нити. Можно обеспечить сверхбыстрый шедулинг и передавать таким нитям процессор прямо сразу на выходе именно из того прерывания, которое этот DPC запросило, снизив латентность.
Отдельно отметим, что из DPC можно многое из того, что в прерывании нельзя. Что именно — зависит от ОС. В Фантоме внутри DPC можно всё, в том числе и заснуть на месяц. Грех, но — можно. NT, ЕМНИП, всё же, как-то ограничивает права DPC (то есть, это не обычные нити), но деталей я не помню.
Драйверы верхнего уровня и службы пользовательского режима отправляют IOCTL_IEEE1394_API_REQUEST для управления виртуальными устройствами 1394.
Драйвер предоставляет идентификатор устройства и идентификатор экземпляра в структуре IEEE1394_VDEV_PNP_REQUEST .
Для предоставления виртуального устройства на шине 1394 драйвер эмуляции выполняет следующие действия.
Отправьте запрос REQUEST_SET_LOCAL_HOST_PROPERTIES в драйвер шины с помощью члена u. сетлокалхостпропертиес. нлевел , установленного в ирб, в значение SET_LOCAL_HOST_PROPERTIES_MODIFY_CROM, чтобы добавить каталог единиц измерения в пзу конфигурации системы IEEE 1394. Этот запрос также добавляет любые другие необходимые данные конфигурации в ПЗУ конфигурации, чтобы предоставить возможность использования эмулятора устройства. Запрос должен быть отправлен с помощью виртуальной PDO, с которой связан драйвер эмуляции.
Выдайте сброс шины для уведомления узлов 1394, имеющихся на шине, на которой изменилось ПЗУ конфигурации системы.
Удаление устройств
Существует два способа удаления объекта физического устройства (PDO) виртуального устройства.
стандартный метод Plug and Play (PnP) для удаления устройства. Драйвер отправляет запрос IRP_MN_REMOVE_DEVICE на виртуальное устройство.
Стек ввода-вывода должен содержать следующие значения:
- Мажорфунктион = IRP_MJ_PNP
- Минорфунктион = IRP_MN_REMOVE_DEVICE
Пакет запроса ввода-вывода (IRP) типа IOCTL_IEEE1394_API_REQUEST: драйвер отправляет запрос IRP_MJ_DEVICE_CONTROL на виртуальное устройство.
Стек ввода-вывода должен содержать следующие значения:
- Мажорфунктион = IRP_MJ_DEVICE_CONTROL
- Parameters. DeviceIoControl. иоконтролкоде = IOCTL_IEEE1394_API_REQUEST
IRP должен содержать следующие значения:
- АссоЦикатедирп. систембуффер — > Систембуффер указывает на структуру IEEE1394_API_REQUEST
- Член рекуестнумбер IEEE1394_API_REQUEST = IEEE1394_API_REMOVE_VIRTUAL_DEVICE
Первый метод (IRP_MN_REMOVE_DEVICE) удаляет устройство, но если устройство постоянно, оно будет восстановлено при следующем запуске компьютера. Второй метод (IEEE1394_API_REMOVE_VIRTUAL_DEVICE) полностью удаляет устройство, поэтому оно больше не будет сохраняться при перезагрузке. При следующем запуске компьютера устройство не будет восстановлено.
Обратите внимание, что драйвер верхнего уровня или служба пользовательского режима могут определить с помощью обычного механизма PnP, что имеются виртуальные устройства. Этот механизм использует идентификатор GUID класса, указанный в INF-файле виртуального драйвера.
Виртуальные ПДОС и драйверы, загруженные выше, имеют тот же уровень доступа к DDI шины 1394, что функциональный драйвер, загруженный на PDO, имеет реальное оборудование. Однако, поскольку в случае виртуального драйвера отсутствует фактическое оборудование, драйвер шины 1394 должен обрабатывать определенные запросы как особые случаи. В этом разделе описываются запросы, поведение которых отличается от поведения виртуального PDO.
Когда драйвер шины получает запрос на PDO виртуального устройства, он использует идентификатор узла, предоставленный драйвером, который поступил запросом, а не пытается извлечь идентификатор узла из расширения устройства. Строго говоря, виртуальные устройства не имеют идентификаторов узлов, поэтому драйверы, отправляющие запросы виртуальным устройствам, должны предоставлять альтернативный идентификатор узла. По соглашению виртуальные устройства используют идентификатор узла контроллера узла компьютера.
Когда драйвер виртуального устройства выделяет память, он указывает, что он будет принимать все пакеты, отправляемые на шину 1394. Затем драйвер определяет пакеты, проверяя идентификатор узла контроллера узла в каждом полученном пакете.
Виртуальные устройства не имеют размера пакета или сведений о скорости передачи, записанных в расширениях устройств, так как это параметры оборудования. В случае виртуальных устройств драйвер шины использует сведения о размере пакета и скорости передачи, которые хранились в объекте устройства для порта.
Драйверы для виртуальных устройств должны устанавливать флаг ACCESS_FLAGS_TYPE_BROADCAST в члене ФУЛАКЦЕССТИПЕ ИРБ при выделении памяти с помощью запроса REQUEST_ALLOCATE_ADDRESS_RANGE. Так как у виртуальных устройств нет фактических номеров узлов, у драйверов виртуальных устройств нет средств получения запросов, если они не получают пакеты в широковещательном режиме. Если несколько узлов выделили один и тот же диапазон адресов, только один из них будет принимать асинхронные запросы, адресованные в этот диапазон. Если драйверы для виртуального устройства и физического устройства одновременно выделяют один и тот же диапазон адресов, физическое устройство имеет приоритет над виртуальным устройством, а физическое устройство получает пакеты. Если несколько виртуальных устройств распределяют один и тот же диапазон адресов, первый драйвер для выделения диапазона имеет приоритет.
Виртуальные устройства не имеют соответствующего узла оборудования и не имеют собственного идентификатора узла. Драйверы виртуальных устройств возвращают идентификатор узла контроллера узла каждый раз, когда он получает этот запрос, а не идентификатор узла физического узла на шине.
Этот запрос не поддерживается для виртуальных устройств, так как отсутствует соответствующий узел оборудования, с которого нужно получить идентификатор узла.
Для всех остальных запросов поведение виртуальных и физических устройств идентично.
Узнайте о написании драйвера источника HID, который сообщает данные HID в операционную систему.
Устройство ввода HID, например клавиатура, мышь, перо, сенсорный ввод или кнопка, отправляет различные отчеты в операционную систему, чтобы он смог понять назначение устройства и выполнить необходимые действия. Отчеты представлены в виде коллекций HID и использования HID. Устройство отправляет эти отчеты по различным транспортам, некоторые из которых поддерживаются Windows, например HID через I2C и HID через USB. В некоторых случаях транспорт может не поддерживаться Windows, или отчеты могут не сопоставляться напрямую с реальным оборудованием. Это может быть поток данных в формате HID, который отправляется другим программным компонентом для виртуального оборудования, например для кнопок или датчиков, отличных от GPIO. Например, рассмотрим данные акселерометра с телефона, который ведет себя как игровой контроллер, отправленный беспроводной на компьютер. В другом примере компьютер может получать удаленные входные данные с устройства Miracast с помощью протокола UIBC.
В предыдущих версиях Windows для поддержки новых транспортных средств (реального оборудования или программного обеспечения) необходимо было написать мини-накопитель транспорта HID и привязать его к драйверу класса, предоставленному корпорацией Майкрософт, Hidclass.sys. Пара классов и мини-драйверов предоставила коллекции HID, такие как коллекции верхнего уровня для драйверов верхнего уровня и приложений в пользовательском режиме. В этой модели задача была написана мини-driver, которая может быть сложной задачей.
Начиная с Windows 10, новая виртуальная платформа HID Framework (VHF) устраняет необходимость записи мини-накопителя транспорта. Вместо этого можно написать исходный драйвер HID с помощью программных интерфейсов KMDF или WDM. Платформа состоит из статической библиотеки, предоставляемой корпорацией Майкрософт, которая предоставляет элементы программирования, используемые драйвером. Он также включает встроенный драйвер Корпорации Майкрософт, который перечисляет одно или несколько дочерних устройств и переходит к созданию виртуального дерева HID и управлению им.
В этом выпуске VHF поддерживает драйвер источника HID только в режиме ядра.
В этом разделе описывается архитектура платформы, дерево виртуальных устройств HID и сценарии конфигурации.
Дерево устройств Виртуального HID
На этом изображении в дереве устройств отображаются драйверы и связанные с ними объекты устройств.
Драйвер источника HID (драйвер)
Исходный драйвер HID ссылается на Vhfkm.lib и включает Vhf.h в свой проект сборки. Драйвер можно записать с помощью Windows driver Model (WDM) или Kernel-Mode Driver Framework (KMDF), который является частью платформы драйверов Windows (WDF). Драйвер можно загрузить в качестве драйвера фильтра или драйвера функции в стеке устройств.
Статическая библиотека VHF (vhfkm.lib)
Статическая библиотека включена в пакет драйверов Windows (WDK) для Windows 10. Библиотека предоставляет программные интерфейсы, такие как подпрограммы и функции обратного вызова, используемые драйвером источника HID. Когда драйвер вызывает функцию, статическая библиотека перенаправит запрос драйверу VHF, который обрабатывает запрос.
Драйвер VHF (Vhf.sys)
Драйвер, предоставляемый корпорацией Майкрософт. Этот драйвер должен быть загружен в качестве драйвера нижнего фильтра под драйвером в стеке исходного устройства HID. Драйвер VHF динамически перечисляет дочерние устройства и создает объекты физических устройств (PDO) для одного или нескольких устройств HID, указанных драйвером источника HID. Он также реализует функциональные возможности мини-драйвера транспорта HID для перечисленных дочерних устройств.
Пара драйверов класса HID (Hidclass.sys, Mshidkmdf.sys)
Пара Hidclass/Mshidkmdf перечисляет коллекции верхнего уровня (TLC), аналогичные перечислению этих коллекций для реального устройства HID. Клиент HID может продолжать запрашивать и использовать TLCs так же, как реальное устройство HID. Эта пара драйверов устанавливается в качестве драйвера функции в стеке устройств.
В некоторых сценариях клиенту HID может потребоваться определить источник данных HID. Например, система имеет встроенный датчик и получает данные от удаленного датчика того же типа. Системе может потребоваться выбрать один датчик, который будет более надежным. Чтобы различать два датчика, подключенные к системе, клиент HID запрашивает идентификатор контейнера TLC. В этом случае драйвер источника HID может предоставить идентификатор контейнера, который передается как идентификатор контейнера виртуального устройства HID VHF.
Клиент HID (приложение)
Запрашивает и использует TLCs, которые передаются стеком устройств HID.
Требования к заголовкам и библиотекам
В этой процедуре описывается, как написать простой драйвер источника HID, который передает кнопки гарнитуры в операционную систему. В этом случае драйвер, реализующий этот код, может быть существующим звуковым драйвером KMDF, который был изменен для работы в качестве кнопок гарнитуры отчетов о источнике HID с помощью VHF.
Включите Vhf.h, включенный в WDK для Windows 10.
Ссылка на vhfkm.lib, включенная в WDK.
Создайте дескриптор отчета HID, который устройство хочет сообщить операционной системе. В этом примере дескриптор отчета HID описывает кнопки гарнитуры. В отчете указывается входной отчет HID размером 8 бит (1 байт). Первые три бита предназначены для кнопок середины гарнитуры, громкости и уменьшения громкости. Остальные биты не используются.
Создание виртуального устройства HID
Инициализируйте структуру VHF_CONFIG , вызвав макрос VHF_CONFIG_INIT , а затем вызовите метод VhfCreate . Драйвер должен вызывать VhfCreate в PASSIVE_LEVEL после вызова WdfDeviceCreate , как правило, в функции обратного вызова EvtDriverDeviceAdd драйвера.
В вызове VhfCreate драйвер может указать определенные параметры конфигурации, такие как операции, которые должны обрабатываться асинхронно или задавать сведения об устройстве (идентификаторы поставщика или продукта).
Например, приложение запрашивает TLC. Когда пара драйверов класса HID получает этот запрос, пара определяет тип запроса и создает соответствующий запрос HID Minidriver IOCTL и перенаправит его в VHF. После получения запроса IOCTL VHF может обрабатывать запрос, полагаться на драйвер источника HID для его обработки или завершить запрос с помощью STATUS_NOT_SUPPORTED.
VHF обрабатывает следующие ioCTLs:
Если запрос — GetFeature, SetFeature, WriteReport или GetInputReport, а драйвер источника HID зарегистрировал соответствующую функцию обратного вызова, VHF вызывает функцию обратного вызова. В этой функции драйвер источника HID может получить или задать данные HID для виртуального устройства HID. Если драйвер не регистрирует обратный вызов, VHF завершает запрос с состоянием STATUS_NOT_SUPPORTED.
VHF вызывает функции обратного вызова событий, реализованные драйвером HID, для этих ioCTLs:
Если драйвер хочет обработать политику буферизации при отправке буфера для получения входного отчета HID, он должен реализовать evtVhfReadyForNextReadReport и указать указатель в члене EvtVhfAsyncOperationGetInputReport . Дополнительные сведения см. в разделе "Отправка входного отчета HID".
Если драйвер хочет получить или задать отчет о функциях HID асинхронно, драйвер должен реализовать функцию EvtVhfAsyncOperation и указать указатель на функцию реализации get или set в элементе VHF_CONFIG EvtVhfAsyncOperationGetFeature или EvtVhfAsyncOperationSetFeature.
Если драйвер хочет получить входной отчет HID асинхронно, драйвер должен реализовать функцию EvtVhfAsyncOperation и указать указатель на функцию в элементе EvtVhfAsyncOperationGetInputReportVHF_CONFIG.
Если драйвер хочет получить отчет ввода HID асинхронно, драйвер должен реализовать функцию EvtVhfAsyncOperation и указать указатель на функцию в элементе EvtVhfAsyncOperationWriteReportVHF_CONFIG.
Для любого другого мини-driver HID IOCTL VHF завершает запрос с помощью STATUS_NOT_SUPPORTED.
Виртуальное устройство HID удаляется путем вызова VhfDelete. Обратный вызов EvtVhfCleanup требуется, если драйвер выделил ресурсы для виртуального устройства HID. Драйвер должен реализовать функцию EvtVhfCleanup и указать указатель на нее в элементе EvtVhfCleanupVHF_CONFIG. EvtVhfCleanup вызывается до завершения вызова VhfDelete . Дополнительные сведения см. в разделе "Удаление виртуального устройства HID".
После завершения асинхронной операции драйвер должен вызвать VhfAsyncOperationComplete , чтобы задать результаты операции. Метод можно вызвать из обратного вызова события или позже после возвращения из обратного вызова.
Отправка входного отчета HID
Отправьте входной отчет HID, вызвав VhfReadReportSubmit.
Как правило, устройство HID отправляет сведения об изменениях состояния, отправляя входные отчеты через прерывания. Например, устройство гарнитуры может отправлять отчет при изменении состояния кнопки. В таком случае вызывается подпрограмма обслуживания прерываний драйвера (ISR). В этой подпрограмме драйвер может запланировать отложенный вызов процедуры (DPC), который обрабатывает входной отчет и отправляет его в VHF, который отправляет сведения в операционную систему. По умолчанию VHF буферизирует отчет и драйвер источника HID может начать отправку входных отчетов HID по мере их поступления. Это устраняет необходимость реализации сложной синхронизации в исходном драйвере HID.
Драйвер источника HID может отправлять входные отчеты, реализовав политику буферизации для ожидающих отчетов. Чтобы избежать дублирования буферизации, драйвер источника HID может реализовать функцию обратного вызова EvtVhfReadyForNextReadReport и отслеживать, вызван ли этот обратный вызов VHF. Если он был вызван ранее, драйвер источника HID может вызвать VhfReadReportSubmit для отправки отчета. Он должен дождаться вызова EvtVhfReadyForNextReadReport , прежде чем он сможет снова вызвать VhfReadReportSubmit .
Удаление виртуального устройства HID
Удалите виртуальное устройство HID, вызвав VhfDelete.
VhfDelete можно вызывать синхронно или асинхронно, указав параметр Wait. Для синхронного вызова метод должен вызываться в PASSIVE_LEVEL, например из EvtCleanupCallback объекта устройства. VhfDelete возвращается после удаления виртуального устройства HID. Если драйвер асинхронно вызывает VhfDelete , он немедленно возвращается, а VHF вызывает EvtVhfCleanup после завершения операции удаления. Метод может вызываться не более DISPATCH_LEVEL. В этом случае драйвер должен зарегистрировать и реализовать функцию обратного вызова EvtVhfCleanup , когда она ранее называлась VhfCreate. Ниже приведена последовательность событий, когда драйвер источника HID хочет удалить виртуальное устройство HID:
- Драйвер источника HID перестает инициировать вызовы в VHF.
- Источник HID вызывает VhfDelete с параметром Wait с значением FALSE.
- VHF прекращает вызов функций обратного вызова, реализованных драйвером источника HID.
- VHF начинает сообщать устройству о том, что устройство отсутствует в диспетчере PnP. На этом этапе вызов VhfDelete может вернуться.
- Если устройство сообщается как отсутствующий, VHF вызывает EvtVhfCleanup , если драйвер источника HID зарегистрировал свою реализацию.
- После возврата EvtVhfCleanup VHF выполняет очистку.
Установка исходного драйвера HID
В INF-файле, который устанавливает исходный драйвер HID, убедитесь, что вы объявляете Vhf.sys в качестве драйвера более низкого фильтра в драйвере источника HID с помощью директивы AddReg.
Как уважаемый хабрапользователь наверняка знает, «драйвер устройства» — это компьютерная программа управляющая строго определенным типом устройства, подключенным к или входящим в состав любого настольного или переносного компьютера.
Основная задача любого драйвера – это предоставление софтового интерфейса для управления устройством, с помощью которого операционная система и другие компьютерные программы получают доступ к функциям данного устройства, «не зная» как конкретно оно используется и работает.
Обычно драйвер общается с устройством через шину или коммуникационную подсистему, к которой подключено непосредственное устройство. Когда программа вызывает процедуру (очередность операций) драйвера – он направляет команды на само устройство. Как только устройство выполнило процедуру («рутину»), данные посылаются обратно в драйвер и уже оттуда в ОС.
Любой драйвер является зависимым от самого устройства и специфичен для каждой операционной системы. Обычно драйверы предоставляют схему прерывания для обработки асинхронных процедур в интерфейсе, зависимом от времени ее исполнения.
Любая операционная система обладает «картой устройств» (которую мы видим в диспетчере устройств), для каждого из которых необходим специфический драйвер. Исключения составляют лишь центральный процессор и оперативная память, которой управляет непосредственно ОС. Для всего остального нужен драйвер, который переводит команды операционной системы в последовательность прерываний – пресловутый «двоичный код».
Как работает драйвер и для чего он нужен?
Основное назначение драйвера – это упрощение процесса программирования работы с устройством.
Он служит «переводчиком» между хардовым (железным) интерфейсом и приложениями или операционными системами, которые их используют. Разработчики могут писать, с помощью драйверов, высокоуровневые приложения и программы не вдаваясь в подробности низкоуровневого функционала каждого из необходимых устройств в отдельности.
Как уже упоминалось, драйвер специфичен для каждого устройства. Он «понимает» все операции, которые устройство может выполнять, а также протокол, с помощью которого происходит взаимодействие между софтовой и железной частью. И, естественно, управляется операционной системой, в которой выполняет конкретной приложение либо отдельная функция самой ОС («печать с помощью принтера»).
Если вы хотите отформатировать жесткий диск, то, упрощенно, этот процесс выглядит следующим образом и имеет определенную последовательность: (1) сначала ОС отправляет команду в драйвер устройства используя команду, которую понимает и драйвер, и операционная система. (2) После этого драйвер конкретного устройства переводит команду в формат, который понимает уже только устройство. (3) Жесткий диск форматирует себя, возвращает результат драйверу, который уже впоследствии переводит эту команду на «язык» операционной системы и выдает результат её пользователю (4).
Как создается драйвер устройства
Для каждого устройства существует свой строгий порядок выполнения команд, называемой «инструкцией». Не зная инструкцию к устройству, невозможно написать для него драйвер, так как низкоуровневые машинные команды являются двоичным кодом (прерываниями) которые на выходе отправляют в драйвер результат, полученный в ходе выполнения этой самой инструкции.
При создании драйвера для Линукса, вам необходимо знать не только тип шины и ее адрес, но и схематику самого устройства, а также весь набор электрических прерываний, в ходе исполнения которых устройство отдает результат драйверу.
Написание любого драйвера начинается с его «скелета» — то есть самых основных команд вроде «включения/выключения» и заканчивая специфическими для данного устройства параметрами.
И чем драйвер не является
Часто драйвер устройства сравнивается с другими программами, выполняющими роль «посредника» между софтом и/или железом. Для того, чтобы расставить точки над «i», уточняем:
- Драйвер не является интерпретатором, так как не исполняется напрямую в софтовом слое приложения или операционной системы.
- Драйвер не является компилятором, так как не переводит команды из одного софтового слоя в другой, такой же.
Ну и на правах рекламы – вы всегда знаете, где скачать новейшие драйвера для любых устройств под ОС Windows.
Читайте также: