Not
Bu sayfaya erişim yetkilendirme gerektiriyor. Oturum açmayı veya dizinleri değiştirmeyi deneyebilirsiniz.
Bu sayfaya erişim yetkilendirme gerektiriyor. Dizinleri değiştirmeyi deneyebilirsiniz.
Tüm sürücü geliştiricilerin kesme isteği düzeylerini (IRQL' ler) dikkate alması gerekir. IRQL, 0 ile 31 arasında bir tamsayıdır; PASSIVE_LEVEL, DISPATCH_LEVEL ve APC_LEVEL normalde sembolik olarak, diğerleri ise sayısal değerleriyle adlandırılır. IRQL'in yükseltilmesi ve düşürülmesi katı yığın disiplinini izlemelidir. İşlev, çağrıldığı IRQL'e geri dönmeyi hedeflemelidir. IRQL değerleri yığında azalmamalıdır. Ayrıca bir işlev, önce IRQL'i yükseltmeden indiremez. IRQL ek açıklamaları, bu kuralların uygulanmasına yardımcı olmak için tasarlanmıştır.
Sürücü kodunda IRQL ek açıklamaları olduğunda, kod çözümleme araçları bir işlevin çalışması gereken düzey aralığı hakkında daha iyi bir çıkarım yapabilir ve hataları daha doğru bulabilir. Örneğin, bir işlevin çağrılabileceği maksimum IRQL'i belirten ek açıklamalar ekleyebilirsiniz; bir işlev daha yüksek bir IRQL'de çağrılırsa, kod çözümleme araçları tutarsızlıkları tanımlayabilir.
Sürücü işlevlerine IRQL hakkında uygun olabilecek kadar fazla bilgi eklenmelidir. Ek bilgiler varsa, kod çözümleme araçlarının hem çağıran işlevi hem de çağrılan işlevi daha sonra denetlemesine yardımcı olur. Bazı durumlarda, bir açıklama eklemek hatalı pozitifleri bastırmanın iyi bir yoludur. Yardımcı program işlevi gibi bazı işlevler herhangi bir IRQL'de çağrılabilir. Bu durumda, IRQL ek açıklamasının olmaması uygun ek açıklamadır.
IRQL için bir işleve ek açıklama eklerken, yalnızca geçerli uygulamasını değil işlevin nasıl gelişebileceğini göz önünde bulundurmak özellikle önemlidir. Örneğin, uygulanan bir işlev tasarımcının amaçladığından daha yüksek bir IRQL'de düzgün çalışabilir. Kodun gerçekte ne yaptığına bağlı olarak işleve açıklama eklemek cazip olsa da, tasarımcı gelecekteki bazı geliştirmeler veya bekleyen sistem gereksinimleri için en yüksek IRQL'i düşürme gereksinimi gibi gelecekteki gereksinimlerin farkında olabilir. Ek açıklama, gerçek uygulamadan değil işlev tasarımcısının amacından türetilmelidir.
Bir işlev ve parametreleri için doğru IRQL'i belirtmek üzere aşağıdaki tabloda yer alan ek açıklamaları kullanabilirsiniz. IRQL değerleri Wdm.h içinde tanımlanır.
| IRQL yorumu | Açıklama |
|---|---|
| _IRQL_requires_max_(irql) | irql, işlevin çağrılabileceği maksimum IRQL'dir. |
| _IRQL_requires_min_(irql) | irql, işlevin çağrılabileceği en düşük IRQL'dir. |
| _IRQL_requires_(irql) | İşlev, irql tarafından belirtilen IRQL'de girilmelidir. |
| _IRQL_raises_(irql) | İşlev belirtilen irql'den çıkar, ancak yalnızca geçerli IRQL'i yükseltmek (daha düşük değil) için çağrılabilir. |
| _IRQL_saves_ | Açıklama ekleme parametresi, daha sonra geri yüklemek için geçerli IRQL'i kaydeder. |
| _IRQL_restores_ | Açıklama eklenen parametre, fonksiyon döndüğünde geri yüklenecek bir IRQL değeri içeren IRQL_saves'i içerir. |
| _IRQL_saves_global_(tür, param) | Geçerli IRQL, IRQL'in geri yükleneceği kod çözümleme araçlarının iç konumuna kaydedilir. Bu ek açıklama bir işleve açıklama eklemek için kullanılır. Konum türüne göre tanımlanır ve param tarafından daha da detaylandırılır. Örneğin, OldIrql türü olabilir ve FastMutex bu eski IRQL değerini tutan parametre olabilir. |
| _IRQL_restores_global_(tür, param) | IRQL'yi kaydetmek için IRQL_saves_global ile açıklanan işlevin kaydettiği IRQL, Kod Analizi araçlarının içsel bir konumundan geri yüklenir. |
| _IRQL_always_function_min_(değer) | IRQL değeri, işlevin IRQL'i düşürebileceği en düşük değerdir. |
| _IRQL_always_function_max_(değer) | IRQL değeri, işlevin IRQL'i yükseltebileceği maksimum değerdir. |
| _IRQL_requires_same_ | Ek açıklamalı işlevin aynı IRQL'de girip çıkması gerekir. işlevi IRQL'i değiştirebilir, ancak çıkmadan önce IRQL'i özgün değerine geri yüklemesi gerekir. |
| _IRQL_uses_cancel_ | Ek açıklamalı parametre, bir DRIVER_CANCEL geri çağırma işlevi tarafından geri yüklenmesi gereken IRQL değeridir. Çoğu durumda bunun yerine IRQL_is_cancel ek açıklamasını kullanın. |
DRIVER_CANCEL için ek açıklamalar
_IRQL_uses_cancel_ ile _IRQL_is_cancel_ ek açıklamaları arasında bir fark vardır. _IRQL_uses_cancel_ ek açıklaması, açıklamalı parametrenin bir DRIVER_CANCEL geri çağırma işlevi tarafından geri yüklenmesi gereken IRQL değeri olduğunu belirtir. _IRQL_is_cancel_ ek açıklaması, _IRQL_uses_cancel_ ve bir DRIVER_CANCEL geri çağırma yardımcı programı işlevinin doğru davranışını sağlayan diğer birkaç ek açıklamayı içeren bileşik bir ek açıklamadır. Tek başına, _IRQL_uses_cancel_ ek açıklaması yalnızca bazen yararlıdır; örneğin, _IRQL_is_cancel_ tarafından açıklanan yükümlülüklerin geri kalanı başka bir şekilde yerine getirilmişse.
| IRQL yorumu | Açıklama |
|---|---|
| _IRQL_is_cancel_ | Açıklamalı parametre, DRIVER_CANCEL geri çağırma işlevine yapılan çağrının bir parçası olarak geçirilen IRQL'dir. Bu açıklama, işlevin Cancel rutinlerinden çağrılan ve iptal spin kilidinin serbest bırakılması dahil olmak üzere DRIVER_CANCEL işlevlerinin gereksinimlerini tamamlayan bir yardımcı işlev olduğunu gösterir. |
IRQL ek açıklamaları nasıl etkileşim kurar?
IRQL parametresi ek açıklamaları diğer ek açıklamalardan daha fazla etkileşim kurar çünkü IRQL değeri, çağrılan çeşitli işlevler tarafından ayarlanır, sıfırlanır, kaydedilir ve geri yüklenir.
En Yüksek ve En Düşük IRQL Belirtme
_IRQL_requires_max_ ve _IRQL_requires_min_ ek açıklamaları, işlevin belirtilen değerden daha yüksek veya daha düşük bir IRQL'den çağrılmaması gerektiğini belirtir. Örneğin, PREfast IRQL'i değiştirmeyen bir işlev çağrıları dizisi gördüğünde, yakındaki bir _IRQL_requires_min_ değerinden daha düşük bir _IRQL_requires_max_ değerine sahip bir çağrı bulursa, karşılaştığı ikinci çağrıda bir uyarı verir. Hata aslında ilk çağrıda oluşabilir; iletisi, çakışmanın diğer yarısının nerede oluştuğuna işaret eder.
Bir işlevdeki ek açıklamalar IRQL'den bahsediyor ve _IRQL_requires_max_'i açıkça uygulamıyorsa, Code Analysis aracı bu ek açıklamayı örtük olarak _IRQL_requires_max_(DISPATCH_LEVEL) olarak uygular, bu genellikle, nadir istisnalarla birlikte, doğrudur. Bunu varsayılan olarak otomatik bir şekilde uygulamak, ek açıklama karmaşasını büyük ölçüde ortadan kaldırır ve istisnaları çok daha görünür hale getirir.
_IRQL_requires_min_(PASSIVE_LEVEL) açıklaması, IRQL daha düşük bir seviyeye inemeyeceği için her zaman zımni olarak kabul edilir; bu nedenle, minimum IRQL hakkında karşılık gelen açık bir kural yoktur. Çok az işlev hem DISPATCH_LEVEL dışında bir üst sınıra hem de PASSIVE_LEVEL dışında bir alt sınıra sahiptir.
Bazı işlevler, çağrılan işlevin IRQL'i bir üst sınırın üzerine güvenli bir şekilde yükseltemediği veya daha sık güvenli bir şekilde minimum düzeyin altına indiremeyeceği bir bağlamda çağrılır. _IRQL_always_function_max_ ve _IRQL_always_function_min_ ek açıklamaları PREfast'ın istemeden gerçekleştiği durumları bulmasına yardımcı olur.
Örneğin, DRIVER_STARTIO türü işlevlerine _IRQL_always_function_min_(DISPATCH_LEVEL) ile açıklanır. Bu, bir DRIVER_STARTIO işlevinin yürütülmesi sırasında DISPATCH_LEVEL altında IRQL'in düşürülmesine neden olan bir hata olduğu anlamına gelir. Diğer ek açıklamalar, işlevin DISPATCH_LEVEL'de girilmesi ve çıkılması gerektiğini belirtir.
Açık IRQL Belirtme
PREfast'in, IRQL'i bildiği için _IRQL_requires_max_ veya _IRQL_requires_min_ ek açıklamalarıyla tespit edilen bir tutarsızlığı daha iyi raporlamasına yardım etmek amacıyla _IRQL_raises_ veya _IRQL_requires_ ek açıklamasını kullanın.
_IRQL_raises_ ek açıklaması, bir işlevin IRQL değeri yeni bir değere ayarlanmış hâlde döndürdüğünü gösterir. _IRQL_raises_ ek açıklamasını kullandığınızda, _drv_maxFunctionIRQL ek açıklamasını da aynı IRQL değerine etkili bir şekilde ayarlar. Ancak, işlev IRQL'i son değerden daha yükseğe yükseltip son değere düşürürse, daha yüksek IRQL değerine izin vermek için _IRQL_raises_ ek açıklamasının ardından açık bir _IRQL_always_function_max_ ek açıklaması eklemeniz gerekir.
IRQL'i Yükseltme veya Düşürme
_IRQL_raises_ ek açıklaması işlevin yalnızca IRQL'i yükseltmek için kullanılması gerektiğini ve işlevin söz dizimi izin verse bile IRQL'i düşürmek için kullanılmaması gerektiğini belirtir. KeRaiseIrql, IRQL'i düşürmek için kullanılmaması gereken bir işlev örneğidir.
IRQL'i Kaydetme ve Geri Yükleme
_IRQL_saves_ ve _IRQL_restores_ ek açıklamalarını kullanarak geçerli IRQL'in (tam olarak mı yoksa yalnızca yaklaşık olarak mı bilinir) ek açıklamalı parametreye kaydedildiğini veya bu parametreden geri yüklendiğini belirtin.
Bazı işlevler IRQL'i örtük olarak kaydeder ve geri yükler. Örneğin, ExAcquireFastMutex sistem işlevi IRQL'i ilk parametrenin tanımlamış olduğu hızlı mutex nesnesiyle ilişkili opak bir konuma kaydeder; kaydedilen IRQL, bu hızlı mutex nesnesi için karşılık gelen ExReleaseFastMutex işlevi tarafından geri yüklenir. Bu eylemleri açıkça belirtmek için _IRQL_saves_global_ ve _IRQL_restores_global_ ek açıklamalarını kullanın. tür ve param parametreleri, IRQL değerinin nereye kaydedildiğini gösterir. Değeri kaydeden ve geri yükleyen ek açıklamalar tutarlı olduğu sürece, değerin kaydedildiği konumun kesin olarak belirtilmesi gerekmez.
Aynı IRQL'i Koruma
Sürücünüz tarafından oluşturulan ve IRQL'i değiştiren işlevlere, IRQL'deki değişikliğin beklendiğini belirtmek için _IRQL_requires_same_ açıklamasını veya diğer IRQL açıklamalarından birini kullanarak açıklama eklemelisiniz. IRQL'de herhangi bir değişikliği gösteren ek açıklamaların olmaması durumunda, kod çözümleme araçları işlevin girildiği aynı IRQL'den çıkmayan herhangi bir işlev için bir uyarı oluşturur. IRQL'deki değişiklik amaçlanıyorsa, hatayı engellemek için uygun ek açıklamayı ekleyin. IRQL'deki değişiklik amaçlanmamışsa kod düzeltilmelidir.
G/Ç İptal Yordamları için IRQL Kaydetme ve Geri Yükleme
Açıklamalı parametrenin DRIVER_CANCEL geri çağırma işlevi tarafından geri yüklenmesi gereken IRQL değeri olduğunu belirtmek için _IRQL_uses_cancel_ ek açıklamasını kullanın. Bu ek açıklama, işlevin iptal yordamlarından çağrılan bir yardımcı işlev olduğunu ve DRIVER_CANCEL işlevlerinde yapılan gereksinimleri yerine getirdiğini gösterir (yani, arayan için yükümlülüğü yerine getirir).
Örneğin, aşağıdaki DRIVER_CANCEL geri çağırma işlev türünün bildirimidir. Parametrelerden biri, bu işlev tarafından geri yüklenmesi gereken IRQL'dir. Ek açıklamalar, bir cancel işlevinin tüm gereksinimlerini gösterir.
// Define driver cancel routine type. //
__drv_functionClass(DRIVER_CANCEL)
_Requires_lock_held_(_Global_cancel_spin_lock_)
_Releases_lock_(_Global_cancel_spin_lock_)
_IRQL_requires_min_(DISPATCH_LEVEL)
_IRQL_requires_(DISPATCH_LEVEL)
typedef
VOID
DRIVER_CANCEL (
_Inout_ struct _DEVICE_OBJECT *DeviceObject,
_Inout_ _IRQL_uses_cancel_ struct _IRP *Irp
);
typedef DRIVER_CANCEL *PDRIVER_CANCEL;