Aracılığıyla paylaş


IRP'leri İptal Ederken Dikkate Alınacak Noktalar

Bu bölümde Cancel rutini uygulama ve iptal edilebilir IRP'leri işleme yönergeleri açıklanmıştır. İptal edilebilir IRP'leri işleme hakkında daha fazla bilgi için bkz. Cancel-Safe IRP Kuyruk Yapısı Denetim Akışı.

Tüm İptal Yordamları için Genel Yönergeler

G/Ç yöneticisi, sürücünün İptal yordamını çağıran her durumda iptal döndürme kilidini tutar. Sonuç olarak, her Cancel yordamı şunları yapmalıdır:

  • Denetimi döndürmeden önce IoReleaseCancelSpinLock'u çağır.

  • IoAcquireCancelSpinLock çağrısı, IoReleaseCancelSpinLock çağrısı yapılmadıkça ilk olarak yapılmamalıdır.

  • IoAcquireCancelSpinLock'a yaptığı her çağrı için IoReleaseCancelSpinLock'a karşılıklı bir çağrı yapın.

Cancel yordamı IoReleaseCancelSpinLock'u her çağırışında, IoAcquireCancelSpinLock'a en son çağrı tarafından döndürülen IRQL'i geçirmesi gerekir. G/Ç yöneticisi tarafından alınan döndürme kilidi serbest bırakıldığında (ve İptal yordamı çağrıldığında tutulduğunda), İptalyordamının Irp-CancelIrql'i> geçmesi gerekir.

Kilitlenmeye yol açabileceği için, bir sürücü bir döndürme kilidini tutarken dış yordamları (örneğin IoCompleteRequest) çağırmamalıdır.

G/Ç Yöneticisi Tarafından Tanımlanan Kuyruğu Kullanma

Sürücü kendi iç IRP kuyruklarını yönetmediğinde, Cancel yordamı, aşağıdakilerden biri olabilecek bir gelen IRP ile çağrılır:

  • Giriş hedef cihaz nesnesindeki CurrentIrp

  • Hedef cihaz nesnesiyle ilişkili cihaz kuyruğundaki bir girdi

Bir sürücü kendi iç IRP kuyruklarını yönetmediği sürece , cancel yordamının hedef cihaz nesnesiyle ilişkili cihaz kuyruğunda bir giriş olup olmadığını test etmek için giriş IRP'siyle KeRemoveEntryDeviceQueue çağrısı yapması gerekir. Belirtilen IRP'nin cihaz kuyruğunda belirli bir konumda olduğunu varsayamadığından, sürücünün İptal yordamı KeRemoveDeviceQueue veya KeRemoveByKeyDeviceQueue'yiçağıramaz.

Giriş IRP'si Üzerindeki Mevcut Durum

Bir İptal yordamı, sürücünün G/Ç işlemini başlattığı bir IRP ile çağrılırsa ve istek yakında tamamlanacaksa, İptal yordamı sistemin iptal döndürme kilidini serbest bırakmalı ve kontrolü geri vermelidir.

Giriş IRP'sinin geçerli durumu Beklemede ise, İptal yordamı aşağıdakileri yapmalıdır:

  1. Giriş IRP'sinin G/Ç durum bloğunu Durum için STATUS_CANCELLED ve Bilgi için sıfır olarak ayarlayın.

  2. Sistem iptal spin kilidi de dahil olmak üzere, tuttuğu tüm spin kilitlerini serbest bırakın.

  3. Verilen IRP ile IoCompleteRequest'i çağırın.

IRP'leri İptal Edilebilir Durumda Tutma

bir IRP'yi iptal edilebilir durumda tutan herhangi bir sürücü yordamı IoMarkIrpPending'i çağırmalı ve IRP'deki cancel yordamı için giriş noktasını ayarlamak üzere IoSetCancelRoutine çağrısı yapmalıdır. Ancak o zaman bu sürücü rutini, IoStartPacket, IoAllocateController veya ExInterlockedInsertList gibi ek destek rutinlerini çağırabilir.

daha sonra iptal edilebilir IRP'leri işleyen tüm sürücü rutinleri, bir IRP'nin isteği karşılamaya yönelik işlemlere başlamadan önce iptal edilip edilmediğini kontrol etmelidir. Cancel yordamının IRP içindeki giriş noktasını NULL olarak sıfırlamak için yordamın IoSetCancelRoutine çağrısı yapması gerekir. Ancak o zaman bu yordam giriş IRP'sinin G/Ç işlemesine başlayabilir.

Bir rutin, başka sürücü rutinleri tarafından daha fazla işleme tabi tutulan IRP'leri gönderirse ve bu IRP'ler iptal edilebilir bir durumda tutulabilirse, bir IRP'deki İptal Et rutininin giriş noktasını sıfırlaması gerekebilir.

IRP'yi iptal edilebilir durumda tutan herhangi bir üst düzey sürücü, IRP'yi IoCallDriver ile sonraki alt sürücüye geçirmeden önce İptal giriş noktasını NULL olarak sıfırlamalıdır.

IRP'yi iptal etme

Üst seviye herhangi bir sürücü, daha alt seviyedeki sürücüler tarafından daha fazla işlenmesi için ayırdığı ve ilettiği bir IRP ile IoCancelIrp'yi çağırabilir. Ancak, böyle bir sürücü verilen IRP'nin düşük sürücüler tarafından STATUS_CANCELLED ile tamamlanacağını varsayamaz.

Senkronizasyon

Bir sürücü, tasarımına bağlı olarak, IRP'lerin iptal edilebilir durumunu izlemek için cihaz uzantısında ek durum bilgisi tutabilir veya tutmalıdır. Bu durum IRQL <= DISPATCH_LEVEL'de çalışan sürücü rutinleri tarafından paylaşılıyorsa, paylaşılan veriler sürücü tarafından tahsis edilip başlatılmış bir spinlock ile korunmalıdır.

Sürücü, sistem iptal spin kilidinin ve kendi spin kilitlerinin alımını ve bırakılmasını dikkatlice yönetmelidir. Mümkün olan en kısa aralıklar için sistem iptal döndürme kilidini tutmalıdır. İptal edilebilir bir IRP'ye erişmeden önce, böyle bir sürücü her zaman IoSetCancelRoutine'in dönüş değerini denetleerek Cancel yordamının zaten çalışıp çalışmadığını (veya çalışmak üzere olup olmadığını) belirlemelidir; varsa, cancel yordamının IRP'yi tamamlamasına izin vermelidir.

Bir cihaz sürücüsü, çeşitli sürücü yordamlarının ISR ile paylaştığı iptal edilebilir IRP'ler hakkında durum bilgilerini koruyorsa, bu diğer yordamlar paylaşılan duruma erişimi ISR ile eşitlemek zorundadır. Yalnızca sürücü tarafından sağlanan bir SynchCritSection yordamı, ISR ile paylaşılan durum bilgilerine çok işlemcili güvenli bir şekilde erişebilir.

Daha fazla bilgi için bkz. Eşitleme Teknikleri.