Поделиться через


Инициализация объекта устройства

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

IoCreateDevice задает поле StackSize только что созданного объекта устройства на одно. Драйвер низкого уровня может игнорировать это поле. Когда драйвер более высокого уровня вызывает IoAttachDeviceToDeviceStack для подключения к следующему нижнему драйверу, эта процедура автоматически устанавливает поле StackSize в объекте устройства на значение поля в объекте устройства следующего нижнего драйвера плюс единица. Однако для некоторых типов устройств драйвер более высокого уровня может потребоваться задать для поля StackSize большее значение, как указано в документации по устройству. Установка размера стека гарантирует, что irPs, отправленные драйверу более высокого уровня, будут содержать расположение стека ввода-вывода для конкретного драйвера, а также правильное количество расположений стека ввода-вывода для всех драйверов нижнего уровня в цепочке.

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

  1. Вычитает один из требований выравнивания устройства.

  2. Сравните результат шага 1 с текущим значением выравнивания объекта устройства.

  3. Если требование выравнивания устройства больше, установите AlignmentRequirement равным результату шага 1. В противном случае оставьте значение AlignmentRequirement заданным IoCreateDevice.

После того как любой драйвер более высокого уровня подключается к другому драйверу, вызвав IoGetDeviceObjectPointer, драйвер более высокого уровня должен задать поле AlignmentRequirement своего нового объекта устройства для объекта устройства следующего нижнего уровня. Как правило, драйвер более высокого уровня не должен изменять это значение. Если драйвер более высокого уровня вызывает IoAttachDevice или IoAttachDeviceToDeviceStack, эти подпрограммы автоматически задают поле AlignmentRequirement в объекте устройства так, чтобы оно соответствовало устройству драйвера нижнего уровня.

IoGetDeviceObjectPointer возвращает указатели как на объект устройства драйвера нижнего уровня, так и на связанный объект файла. Только FSD (или, возможно, другой драйвер верхнего уровня) может использовать указатель возвращаемого объекта файла. Промежуточный драйвер, вызывающий IoGetDeviceObjectPointer , должен сохранить этот указатель объекта файла, чтобы его можно было разыменовать, вызвав ObDereferenceObject при выгрузке драйвера.

После подключения FSD тома, содержащего объект файла, представляющий объект устройства более низкого драйвера, промежуточный драйвер не может цепочки между файловой системой и нижним драйвером путем вызова IoAttachDevice или IoAttachDeviceToDeviceStack. Кроме того, FSD может установить член SectorSize объекта устройства на основе геометрии базового оборудования тома, когда происходит монтаж. Для получения дополнительной информации см. DEVICE_OBJECT.

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

Настройка поля Flags объекта устройства с DO_DIRECT_IO или DO_BUFFERED_IO определяет, как диспетчер ввода-вывода предоставляет доступ к пользовательским буферам во всех запросах на передачу данных, которые впоследствии отправляются драйверу.

Затем драйвер может задать любые другие значения, зависящие от устройств, в объекте устройства. Например, драйверы, не являющиеся WDM, для съемных носителей должны установить член флагов объекта устройства с DO_VERIFY_VOLUME, если они обнаруживают (или подозревают) изменение носителя во время операций ввода-вывода. (Дополнительные сведения см. в разделе о поддержке съемных носителей.) Драйверы устройств, для которых требуется пусковой ток, должны установить битовый флаг DO_POWER_INRUSH в члене Flags, а драйверы устройств, которые не находятся на пути системного разбиения страниц, должны установить битовый флаг DO_POWER_PAGABLE в члене Flags. Драйверы функций и фильтров должны очистить флаг DO_DEVICE_INITIALIZING.

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