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


Общие сведения о спин-блокировках

Блокировки спина — это механизмы синхронизации только в режиме ядра, экспортированные как непрозрачный тип: KSPIN_LOCK. Блокировка спина может использоваться для защиты общих данных или ресурсов от одновременного доступа. При выполнении в IRQL <= DISPATCH_LEVEL драйвер может использовать KeAcquireInStackQueuedSpinLock и KeReleaseInStackQueuedSpinLock, чтобы получить и освободить блокировку спина в виде блокировки в очереди.

Кроме того, вызывающие пользователи, работающие в IRQL >= DISPATCH_LEVEL могут вызывать KeAcquireSpinLockAtDpcLevel и KeReleaseSpinLockFromDpcLevel для повышения производительности драйвера.

Многие компоненты используют блокировки спина, включая драйверы. Любой тип драйвера может использовать одну или несколько исполнительных замков спина. Например, большинство файловых систем используют переблокированную рабочую очередь в расширении драйвера файловой системы (FSD) для хранения irPs, обрабатываемых как подпрограммами обратного вызова рабочей потока файловой системы, так и FSD. Заблокированная рабочая очередь защищена исполнительной блокировкой спина, которая разрешает конфликт между FSD, пытаясь вставить IRPs в очередь и любые потоки одновременно пытаются удалить IRP. В качестве другого примера драйвер контроллера системного контроллера использует две исполнительные замки спина. Одна исполнительная блокировка спина защищает заблокированную рабочую очередь, общую с выделенным устройством потока этого драйвера; другой защищает объект таймера, общий для трех подпрограмм драйвера.

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

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

Каждый драйвер, имеющий ISR, использует блокировку прерывания для защиты любых данных или оборудования, совместно используемых между isR и его подпрограммами SynchCritSection, которые обычно вызываются из подпрограмм StartIo и DpcForIsr. Блокировка прерывания связана с набором объектов прерываний, созданных при вызове Драйвера Io Подключение Interrupt, как описано в разделе "Регистрация ISR".

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

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

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

  • Вызовите каждую подпрограмму поддержки, которая использует блокировку спина в соответствующем IRQL, как правило, в <= DISPATCH_LEVEL для исполнительных спин-блокировок или в <= DIRQL для блокировки прерывания, связанной с объектами прерывания драйвера.

  • Реализуйте подпрограммы для выполнения как можно быстрее, пока они удерживают спин-блокировку. Подпрограмма не должна содержать блокировку спина дольше 25 микросекунд.

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

    • Вызвать исключения оборудования или вызвать исключения программного обеспечения.

    • Попытайтесь получить доступ к страницируемой памяти.

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

    • Попытка получить еще одну блокировку спина, если это может вызвать взаимоблокировку.

    • Вызов внешней процедуры, которая нарушает какие-либо из предыдущих правил.