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


Коллекции объектов платформы

Драйверы могут группировать объекты платформы в коллекции, представленные объектами коллекции платформ.

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

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

Драйвер также может создать коллекцию коллекций. То есть коллекция может состоять из набора объектов коллекции.

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

  • Создайте объект коллекции.

    Чтобы создать новую коллекцию, драйверы могут вызвать WdfCollectionCreate.

  • Добавление объекта в коллекцию.

    Чтобы добавить объекты в коллекцию, драйверы могут вызывать WdfCollectionAdd один или несколько раз. Каждый вызов WdfCollectionAdd добавляет объект в конец коллекции и увеличивает число ссылок добавленного объекта.

  • Удаление объекта из коллекции.

    Чтобы удалить объект из коллекции и уменьшать его число ссылок, драйверы могут вызывать WdfCollectionRemove или WdfCollectionRemoveItem. При удалении объекта все объекты после удаленного будут автоматически уменьшаться.

  • Получение количества объектов в коллекции.

    Чтобы определить количество объектов, содержащихся в коллекции, драйверы могут вызвать WdfCollectionGetCount.

  • Получение дескриптора объекта в коллекции.

    Если драйвер вызывает WdfCollectionGetItem, предоставляя значение индекса в качестве входного аргумента, драйвер получает дескриптор объекта, связанного со значением индекса. (Значение индекса, равное нулю, представляет первый объект в коллекции, значение индекса — второй объект и т. д., как связанный список. Когда драйвер удаляет элемент i из коллекции, элемент i+1 становится элементом i.)

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

  • Блокировка коллекции.

    Драйвер может вызвать WdfWaitLockAcquire для синхронизации доступа к коллекции в IRQL = PASSIVE_LEVEL или вызвать синхронизированный доступ WdfSpinLockAcquire в IRQL = DISPATCH_LEVEL. После того как драйвер получит блокировку, доступ к коллекции будет невозможен с помощью другого кода в драйвере, который также вызывает WdfWaitLockAcquire или WdfSpinLockAcquire. После завершения операции с коллекцией драйвер должен вызвать WdfWaitLockRelease.

    Вызов WdfWaitLockAcquire или WdfSpinLockAcquire не препятствует одновременному доступу к коллекции другим кодом в драйвере, если другой код не вызывает WdfWaitLockAcquire или WdfSpinLockAcquire.

  • Удаление коллекции.

    Чтобы удалить объект коллекции, драйверы могут вызвать WdfObjectDelete. Однако обычно драйверы указывают родительский объект при создании коллекции, а платформа удаляет объект коллекции при удалении родительского объекта.

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

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

Иногда драйверу необходимо проверить все объекты в коллекции. Следующий пример кода демонстрирует эту ситуацию:

WdfWaitLockAcquire(CollectionLockHandle, NULL);
ItemCount = WdfCollectionGetCount(CollectionHandle);
for (i=0; i<ItemCount; i++) {
    ObjectHandle = WdfCollectionGetItem(CollectionHandle, i);
    // 1. Call object-specific methods to obtain object properties.
    // 2. Perform object-specific operations.
    }
WdfWaitLockRelease(CollectionLockHandle);