Приемник служб и объекты группы служб

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

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

Подпрограмма службы прерывания драйвера минипорта (ISR) вызывает один из следующих методов уведомлений в драйвере порта:

IPortDMus::Notify

IPortMidi::Notify

IPortWaveCyclic::Notify

IPortWavePci::Notify

Метод уведомления принимает указатель на группу служб в качестве параметра вызова. Во время этого вызова драйвер порта вызывает метод IServiceSink::RequestService, который ставит в очередь отложенный вызов процедуры (DPC). При выполнении DPC он перенаправляет запрос службы всем объектам-членам в группе сервисов.

Код минипорт-драйвера обычно не требует вызова методов интерфейса IServiceGroup . Однако драйвер портов вызывает эти методы, чтобы добавить собственные объекты IServiceSink в группы служб, которые он получает от мини-драйвера. Минипорт-драйверы создают объекты группы служб по мере необходимости и связывают эти группы служб с минипортом и объектами потоков, которые требуют периодического обслуживания. Например, драйвер минипорт WaveCyclic ассоциирует объект потока с группой служб, которую он указывает в качестве выходного параметра методу IMiniportWaveCyclic::NewStream.

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

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

IMiniportDMus::Init

IMiniportMidi::Init

IMiniportWavePci::Init

Драйвер порта добавляет собственный объект IServiceSink в группу служб, которую он получает из вызова Init . Когда ISR драйвера минипорта позже вызывает Уведомление для отправки уведомлений в эту группу служб, группа служб ставит в очередь DPC, который перенаправляет уведомление в объект IServiceSink драйвера порта, который в свою очередь перенаправляет уведомление драйверу минипорта, вызвав один из следующих методов обслуживания:

IMiniportDMus::Service (не используется)

IMiniportMidi::Service

IMiniportWavePci::Service

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

IMiniportDMus::NewStream

IMiniportMidi::NewStream

IMiniportWaveCyclic::NewStream

IMiniportWavePci::NewStream

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

Следующие методы помогают драйверам портов MIDI и DMus предотвратить потерю аппаратных прерываний:

IPortMidi::RegisterServiceGroup

IPortDMus::RegisterServiceGroup

Во время выполнения метода Init драйвер MIDI или DMus минипорт обычно вызывает метод RegisterServiceGroup драйвера порта перед запуском синтезатора. Цель этого вызова состоит в том, чтобы позволить драйверу порта вставить объект приемника службы (содержащий его обработчик прерываний) в группу служб до начала генерации прерываний. Хотя метод Init выводит указатель группы служб на драйвер порта, драйвер порта может использовать этот указатель только после возврата из Init.

В случае драйвера портов WavePci объект порта добавляет собственный объект IServiceSink в группу служб, которую он получает из вызова IMiniportWavePci::NewStream . Когда ISR драйвера минипорта позже вызывает Notify, чтобы отправить уведомление в эту группу служб, группа служб ставит в очередь DPC, который перенаправляет уведомление в объект IServiceSink драйвера порта, который, в свою очередь, делает следующее:

  • Перенаправит уведомление в поток минипорта путем вызова метода службы IMiniportWavePciStream::Service.

  • Активирует все события позиции и /или часов на закреплении, которые готовы к срабатыванию.

Интерфейс IServiceSink поддерживает один метод:

IServiceSink::RequestService

Интерфейс IServiceGroup поддерживает следующие методы:

IServiceGroup::AddMember

IServiceGroup::CancelDelayedService

IServiceGroup::RequestDelayedService

IServiceGroup::RemoveMember

IServiceGroup::SupportDelayedService

Кроме того, системный драйвер PortCls предоставляет функцию PcNewServiceGroup для создания нового объекта группы служб. Однако для создания объекта служебного приемника не существует аналогичной функции. Драйвер порта просто добавляет интерфейс IServiceSink в реализацию своего основного объекта порта — при создании объекта создаётся и приемник службы. Драйвер порта может добавить интерфейс IServiceSink объекта порта в группу служб, полученную из метода Init или NewStream драйвера miniport. Для удобства файл заголовка Portcls.h определяет IMP_IServiceSink и IMP_IServiceGroup константы для добавления интерфейсов IServiceSink и IServiceGroup в объекты драйверов.