Aracılığıyla paylaş


IoCompletion Yordamını Uygulama

Girişte, IoCompletion rutini bir Bağlam işaretçisi alır. Bir dağıtım yordamı IoSetCompletionRoutine'i çağırdığında, bir Bağlam işaretçisi sağlayabilir. Bu işaretçi, IoCompletion yordamının bir IRP'yi işlemek için gerektirdiği sürücü tarafından belirlenen bağlam bilgilerine başvurabilir. IoCompletion yordamı IRQL = DISPATCH_LEVEL'de çağrılabildiğinden bağlam alanı sayfalandırılamaz.

IoCompletion yordamları için aşağıdaki uygulama yönergelerini göz önünde bulundurun:

  • IoCompletion yordamı, G/Ç işleminin sonucunu belirlemek için IRP'nin G/Ç durum bloğunu denetleyebilir.

  • Dağıtım yordamı giriş IRP'sini IoAllocateIrp veya IoBuildAsynchronousFsdRequest kullanarak ayırdıysa, Tercihen özgün IRP tamamlanmadan önce IoCompletion yordamının bu IRP'yi serbest bırakmak için IoFreeIrp'i çağırması gerekir.

    • IoCompletion işlemi, sürücü tarafından IRP için tahsis edilen kaynakları, tercihen karşılık gelen IRP'yi boşaltmadan önce serbest bırakmalıdır.

      Örneğin, dağıtım yordamı IoAllocateMdl ile bir MDL ayırırsa ve ayırmış olduğu kısmi aktarım IRP'si için IoBuildPartialMdl'i çağırırsa, IoCompletion yordamının MDL'yi IoFreeMdl ile serbest bırakması gerekir. Özgün IRP'nin durumunu korumak için kaynakları ayırırsa, tercihen özgün IRP ile IoCompleteRequest'i çağırmadan önce ve denetimi döndürmeden önce bu kaynakları serbest tutması gerekir.

      Genel olarak bir IRP'yi serbest bırakmadan veya tamamlamadan önce IoCompletion yordamı, dağıtım yordamı tarafından ayrılan tüm IRP başına kaynakları serbest bırakmalıdır. Aksi takdirde, sürücü IoCompletion yordamı orijinal isteği tamamlamadan önce denetimin geri verilmesinden önce serbest bırakılacak kaynakların durumu hakkında bilgi korumalıdır.

    • IoCompletion yordamı özgün IRP'yi STATUS_SUCCESS ile tamamlayamazsa, özgün IRP'deki G/Ç durum bloğunu, IoCompletion yordamının özgün isteği başarısız olmasına neden olan sürücü tarafından ayrılan IRP'de döndürülen değere ayarlaması gerekir.

    • IoCompletion yordamı özgün isteği STATUS_PENDING ile tamamlarsa, IoCompleteRequest'i çağırmadan önce özgün IRP ile IoMarkIrpPending'i çağırması gerekir.

    • IoCompletion rutini, orijinal IRP’yi STATUS_XXX hatasıyla başarısız olarak işaretlemesi gerekiyorsa, hata kaydı yapabilir. Ancak, oluşan tüm cihaz G/Ç hatalarını günlüğe kaydetmek temel cihaz sürücüsünün sorumluluğundadır, bu nedenle IoCompletion yordamları genellikle hataları günlüğe kaydetmez.

    • IoCompletion rutini, sürücü tarafından ayrılan IRP'yi işleyip serbest ettiğinde, denetimi STATUS_MORE_PROCESSING_REQUIRED ile döndürmelidir.

      IoCompletion rutininden STATUS_MORE_PROCESSING_REQUIRED'ın döndürülmesi, sürücü tarafından ayrılan ve serbest bırakılmış bir IRP için G/Ç yöneticisinin tamamlama işlemini tutar. IoCompleteRequest'e yapılan ikinci bir çağrı, G/Ç yöneticisinin, STATUS_MORE_PROCESSING_REQUIRED döndüren yordamın hemen üzerindeki tamamlama yordamından başlayarak IRP'nin tamamlama yordamlarını çağırmaya devam etmesini sağlar.

  • IoCompletion yordamı gelen bir IRP'yi düşük sürücülere bir veya daha fazla istek göndermek ya da başarısız işlemler tekrar denendiğinde yeniden kullanıyorsa, IRP'nin her yeniden kullanımı veya yeniden denemesi hakkında IoCompletion yordamı tarafından tutulan bağlamı güncellemelidir. Ardından bir sonraki alt sürücünün G/Ç yığını konumunu yeniden ayarlayabilir, ioSetCompletionRoutine'i kendi giriş noktasıyla çağırabilir ve IRP için IoCallDriver'ı çağırabilir.

    • IoCompletion yordamı, IRP'nin her yeniden kullanımında veya yeniden denenmesinde IoMarkIrpPending'i çağırmamalıdır.

      Gönderme yordamı, özgün IRP'yi zaten beklemede olarak işaretledi. Zincirdeki tüm sürücüler IoCompleteRequest ile özgün IRP'yi tamamlayana kadar beklemede kalır.

    • Bir isteği yeniden denemeden önce , IoCompletion yordamının G/Ç durum bloğunu Durum için STATUS_SUCCESS ve Bilgi için sıfır ile sıfırlaması gerekir( büyük olasılıkla döndürülen hata bilgileri kaydedildikten sonra).

      Her yeniden deneme için IoCompletion yordamı genellikle dağıtım yordamı tarafından ayarlanan bir yeniden deneme sayısını azaltır. Genellikle, bazı sınırlı sayıda yeniden deneme başarısız olduğunda IRP'nin başarısız olması için IoCompletion yordamının IoCompleteRequest çağrısı yapması gerekir.

    • IoCompletion rutini, yeniden kullandığı veya yeniden denemekte olduğu bir IRP ile IoSetCompletionRoutine ve IoCallDriver yordamlarını çağırdıktan sonra STATUS_MORE_PROCESSING_REQUIRED döndürmelidir.

      IoCompletion yordamından STATUS_MORE_PROCESSING_REQUIRED döndürülmesi, G/Ç yöneticisinin yeniden kullanılan veya yeniden denenen bir IRP'yi tamamlamasını engeller.

    • IoCompletion yordamı özgün IRP'yi STATUS_SUCCESS ile tamamlayamazsa, IoCompletion yordamının IRP'yi başarısız olmasına neden olan yeniden kullanım veya yeniden deneme işlemi için alt sürücüler tarafından döndürülen G/Ç durum bloğunu bırakması gerekir.

    • IoCompletion yordamı özgün isteği STATUS_PENDING ile tamamlayacaksa, IoCompleteRequest'i çağırmadan önce özgün IRP ile IoMarkIrpPending'i çağırması gerekir.

    • IoCompletion rutininin özgün IRP'yi STATUS_XXX hatasıyla başarısız kılması gerekiyorsa, bir hata kaydedebilir. Ancak, oluşan tüm cihaz G/Ç hatalarını günlüğe kaydetmek temel cihaz sürücüsünün sorumluluğundadır, bu nedenle IoCompletion yordamları genellikle hataları günlüğe kaydetmez.

  • Bir IRP'de IoCompletion yordamı ayarlayıp ardından IRP'yi daha düşük bir sürücüye geçiren herhangi bir sürücü> yordamında IRP-PendingReturned bayrağını denetlemelidir. Bayrağı ayarlanırsa, IoCompletion yordamının IRP ile IoMarkIrpPending çağrısı yapması gerekir. Ancak, IRP'yi iletip ardından bir olayda bekleyen bir sürücü, IRP'yi gecikmiş olarak işaretlememelidir. Bunun yerine IoCompletion yordamı olaya işaret etmeli ve STATUS_MORE_PROCESSING_REQUIRED döndürmelidir.

  • IoCompletion yordamı, tercihen IoCompletion yordamı ioCompleteRequest'i özgün IRP ile çağırmadan önce ve kesinlikle IoCompletion yordamının özgün IRP'yi tamamlayarak denetimi döndürmeden önce özgün IRP'yi işlemek için ayrılan dağıtım yordamının tüm kaynakları serbest bırakması gerekir.

Herhangi bir üst düzey sürücü IoCompletion yordamını özgün IRP'de ayarlarsa, tüm alt düzey sürücülerin IoCompletion yordamları çağrılana kadar bu sürücünün IoCompletion yordamı çağrılmaz.

IoCompleteRequest Çağrılarında Öncelik Artışı Sağlama

En düşük düzeyli bir cihaz sürücüsü dağıtım rutini içerisinde bir IRP'yi tamamlayabilirse, IoCompleteRequest çağrısını PriorityBoost değerinin IO_NO_INCREMENT olduğu şekilde yapar. Sürücü, özgün istek sahibinin G/Ç işleminin tamamlanmasını beklemediğini varsayabileceğinden, çalışma zamanı öncelik artışı gerekmez.

Aksi takdirde, en düşük düzey sürücü, istek sahibinin cihaz G/Ç isteğinde beklediği süreyi telafi etmek için istek sahibinin çalışma zamanı önceliğini artıran sistem tanımlı ve cihaz türüne özgü bir değer sağlar. Yükseltme değerleri için bkz. Wdm.h veya Ntddk.h.

Üst düzey sürücüler, IoCompleteRequest'i çağırdığında ilgili temel cihaz sürücüleriyle aynı PriorityBoost'u uygular.

IoCompleteRequest Çağrısının Etkisi

Bir sürücü IoCompleteRequest'i çağırdığında G/Ç yöneticisi, IRP için çağrılacak bir IoCompletion yordamı ayarlayan bir sonraki üst düzey sürücüyü çağırmadan önce bu sürücünün G/Ç yığını konumunu sıfırlarla doldurur.

Üst düzey bir sürücünün IoCompletion yordamı, tüm düşük sürücülerin isteği nasıl işlediğini belirlemek için yalnızca IRP'nin G/Ç durum bloğunu denetleyebilir.

IoCompleteRequest çağıranı, yeni tamamlanan IRP'ye erişmeye çalışmamalıdır. Böyle bir girişim, sistem kilitlenmesine neden olan bir programlama hatasıdır.