Olay Nesnesi Tanımlama ve Kullanma

Olay nesnesi kullanan herhangi bir sürücü, olayı beklemeden, ayarlamadan, temizlemeden veya sıfırlamadan önce KeInitializeEvent, IoCreateNotificationEvent veya IoCreateSynchronizationEvent'i çağırmalıdır. Aşağıdaki şekilde, iş parçacığına sahip bir sürücünün eşitleme için bir olay nesnesini nasıl kullanabileceği gösterilmektedir.

bir olay nesnesi beklenmeyi gösteren diyagram.

Önceki şekilde gösterildiği gibi, böyle bir sürücü, yerleşik olması gereken olay nesnesi için depolama alanı sağlamalıdır. Sürücü, sürücü tarafından oluşturulan bir cihaz nesnesinin cihaz uzantısını, denetleyici uzantısını veya sürücü tarafından ayrılan sayfalanmamış havuzu kullanabilir.

Sürücü KeInitializeEvent'i çağırdığında, olay nesnesi için sürücünün yerleşik depolama alanına bir işaretçi geçirmesi gerekir. Buna ek olarak, çağıranın olay nesnesi için ilk durumu (sinyalli veya sinyalli değil) belirtmesi gerekir. Çağıranın, aşağıdakilerden biri olabilecek olay türünü de belirtmesi gerekir:

  • SynchronizationEvent

    Eşitleme olayı Sinyalli duruma getirildiğinde, olayın Not-Signaled olarak sıfırlanmasını bekleyen tek bir iş parçacığı çalıştırılmaya uygun hale gelir ve olayın durumu otomatik olarak Sinyalsiz duruma sıfırlanır.

    Bu tür bir olay bazen oto-temizleme olayı olarak adlandırılır, çünkü sinyalli durumu her bekleme karşılandığında otomatik olarak sıfırlanır.

  • NotificationEvent

    Bir bildirim olayı Sinyalli durumuna ayarlandığında, olayın Not-Signaled sıfırlanmasını bekleyen tüm iş parçacıkları yürütme için uygun hale gelir ve olay, Not-Signaled açıkça sıfırlanana kadar Sinyalli durumda kalır: yani, verilen Olay işaretçisiyle KeClearEvent veya KeResetEvent çağrısı yapılır.

tr-TR: Az sayıda cihaz veya ara sürücü, tek bir sürücüye tahsis edilmiş iş parçacığına sahiptir; paylaşılan bir kaynağı koruyan bir olayı bekleyerek işlemlerini eşitleyebilecek bir dizi iş parçacığına sahip olması ise daha da nadirdir.

G/Ç işleminin tamamlanmasını beklemek için olay nesnelerini kullanan sürücülerin çoğu, KeInitializeEvent çağrısı yaptıklarında giriş TürünüNotificationEvent olarak ayarlar. Bir sürücünün IoBuildSynchronousFsdRequest veya IoBuildDeviceIoControlRequest ile oluşturduğu IRP'ler için ayarlanmış bir olay nesnesi neredeyse her zaman NotificationEvent olarak başlatılır çünkü çağıran, isteğinin bir veya daha fazla alt düzey sürücü tarafından karşılandığını belirten bildirim için olayı bekler.

Sürücü kendini başlattıktan sonra, varsa sürücüye özel iş parçacığı ve diğer yordamlar olay üzerinde işlemlerini eşzamanlayabilir. Örneğin, sistem disket denetleyici sürücüsü gibi IRP'lerin kuyruğa alınmasını yöneten bir iş parçacığına sahip bir sürücü, önceki şekilde gösterildiği gibi bir olayda IRP işlemlerini senkronize edebilir.

  1. Cihazda işlenmek üzere bir IRP'yi sıralayan iş parçacığı, başlatılan olay nesnesi için sürücü tarafından sağlanan depolamaya yönelik bir işaretçiyle KeWaitForSingleObject'i çağırır.

  2. Diğer sürücü rutinleri, IRP'yi karşılamak için gerekli cihaz G/Ç işlemlerini gerçekleştirir ve bu işlemler tamamlandıktan sonra sürücünün DpcForIsr rutini, olay nesnesine yönelik bir işaretçi, iş parçacığı için sürücü tarafından belirlenen bir öncelik artırımı (Increment, önceki şekilde gösterildiği gibi) ve WAIT Boole'unu FALSE olarak ayarlayarak KeSetEvent çağırır. KeSetEvent çağrısı olay nesnesini Signaled durumuna ayarlar ve böylece bekleyen iş parçacığının durumunu hazır olarak değiştirir.

  3. Çekirdek, bir işlemci kullanılabilir olduğunda iş parçacığını yürütme için gönderir: başka bir deyişle, daha yüksek önceliğe sahip başka bir iş parçacığı şu anda hazır durumda değildir ve daha yüksek bir IRQL'de çalıştırılacak çekirdek modu yordamları yoktur.

    DpcForIsr, IRP ile IoCompleteRequest'i henüz çağırmadıysa ve cihazda işlenecek başka bir IRP'yi dequeue edebilirse iş parçacığı artık IRP'yi tamamlayabilir.

Wait parametresi TRUE olarak ayarlanmış KeSetEvent çağrısı, çağıranın KeSetEvent'ten dönüşte hemen bir KeWaitForSingleObject veya KeWaitForMultipleObjects destek yordamı çağırma amacını gösterir.

WaitparametresiniKeSetEventolarak ayarlamak için aşağıdaki yönergeleri göz önünde bulundurun:

IRQL'de < çalışan bir sayfalanabilir iş parçacığı veya disk belleğine alınabilen sürücü yordamı DISPATCH_LEVEL Hiçbir zaman Wait parametresi TRUE olarak ayarlanmış KeSetEvent'i çağırmamalıdır. Böyle bir çağrı, çağıranın KeSetEvent ve KeWaitForSingleObject veyaKeWaitForMultipleObjects çağrıları arasında sayfalandırılması durumunda önemli bir sayfa hatasına neden olur.

IRQL = DISPATCH_LEVEL'de çalışan herhangi bir standart sürücü rutini, sistemi çökertmeden herhangi bir dağıtıcı nesnesinde sıfır olmayan bir aralık bekleyemez. Ancak bu tür bir yordam, DISPATCH_LEVEL küçük veya eşit bir IRQL'de çalışırken KeSetEvent'i çağırabilir.

Standart sürücü yordamlarının çalıştırıldığı IRQL'lerin özeti için bkz. Donanım Önceliklerini Yönetme.

KeResetEvent , belirli bir Olayın önceki durumunu döndürür: KeResetEvent çağrısı gerçekleştiğinde Sinyal verildi olarak ayarlanıp ayarlanmadığı. KeClearEvent , verilen Olayın durumunu Not-Signaled olarak ayarlar.

Yukarıdaki destek yordamlarının ne zaman çağrılmaya başladığına ilişkin aşağıdaki yönergeleri göz önünde bulundurun:

Daha iyi performans için, çağıranın bundan sonra ne yapacağını belirlemek için KeResetEvent tarafından döndürülen bilgilere ihtiyacı olmadığı sürece her sürücü KeClearEvent'i çağırmalıdır.