Aracılığıyla paylaş


Güç IP'lerini geçirme

Güç geçişlerinin temiz bir şekilde yönetildiğinden emin olmak için güç IRP'leri cihaz yığını boyunca PDO'ya kadar iletilmelidir. Sürücüler, IRP cihaz yığınında aşağı doğru ilerledikçe cihaz gücünü azaltan bir IRP'yi işler. Sürücüler, IRP cihaz yığınını yedeklerken IoCompletion yordamlarında cihaz gücü uygulayan bir IRP'yi işler.

Aşağıdaki şekilde, Windows 7 ve Windows Vista'da bir cihaz yığınında güç IRP'si geçirmek için sürücülerin izlemesi gereken adımlar gösterilmektedir.

Windows Vista'da bir güç IRP'sinin devrini gösteren diyagram.

Önceki şekilde gösterildiği gibi, Windows 7 ve Windows Vista'da bir sürücü aşağıdakileri yapmalıdır:

  1. IoCompletion yordamı ayarlıysa IoCopyCurrentIrpStackLocationToNext öğesini veya IoCompletion yordamı ayarlanmadıysa IoSkipCurrentIrpStackLocation öğesini çağır.

    Bu iki yordam, sonraki alt sürücü için IRP yığını konumunu ayarlar. Geçerli yığın konumunun kopyalanması, IoCompletion yordamı çalıştırıldığında IRP yığın işaretçisinin doğru konuma ayarlanmasını sağlar.

    Kötü yazılmış bir sürücü IoSkipCurrentIrpStackLocation'ı çağırma hatası yapar ve ardından bir tamamlama yordamı ayarlarsa, bu sürücü altındaki sürücünün ayarladığı bir tamamlama yordamının üzerine yazabilir.

  2. Eksiksiz bir yordam gerekiyorsa, ioCompletion yordamını ayarlamak için IoSetCompletionRoutine'i çağırabilirsiniz.

  3. IRP'yi yığındaki bir sonraki alt sürücüye geçirmek için IoCallDriver'ı çağırın.

Aşağıdaki şekilde, Sürücülerin Windows Server 2003, Windows XP ve Windows 2000'de bir cihaz yığınında güç IRP'si geçirmek için izlemesi gereken adımlar gösterilmektedir.

bir güç IRP'sini (Windows Server 2003, Windows XP ve Windows 2000) devretme.

Önceki şekilde gösterildiği gibi, bir sürücü aşağıdakileri yapmalıdır:

  1. Sürücünün türüne bağlı olarak PoStartNextPowerIrp'i çağırabilirsiniz. Daha fazla bilgi için bkz . PoStartNextPowerIrp'i Çağırma.

  2. IoCompletion yordamı ayarlıysa IoCopyCurrentIrpStackLocationToNext öğesini veya IoCompletion yordamı ayarlanmadıysa IoSkipCurrentIrpStackLocation öğesini çağır.

    Bu iki yordam, sonraki alt sürücü için IRP yığını konumunu ayarlar. Geçerli yığın konumunun kopyalanması, IoCompletion yordamı çalıştırıldığında IRP yığın işaretçisinin doğru konuma ayarlanmasını sağlar.

  3. IoCompletion yordamını ayarlamak için IoSetCompletionRoutine çağrısında bulunur. IoCompletion yordamında çoğu sürücü, bir sonraki güç IRP'sini işlemeye hazır olduğunu belirtmek için PoStartNextPowerIrp'i çağırır.

  4. IRP'yi yığındaki bir sonraki alt sürücüye geçirmek için PoCallDriver'ı çağırın.

    Sürücülerin, sistemin güç IP'lerini düzgün eşitlediğinden emin olmak için IoCallDriver (diğer IRP'ler için olduğu gibi) yerine PoCallDriver kullanması gerekir. Daha fazla bilgi için bkz . IoCallDriver'ı çağırma ve PoCallDriver'ı çağırma.

IoCompletion yordamlarının IRQL = DISPATCH_LEVEL'de çağrılabileceğini unutmayın. Bu nedenle, bir sürücü IRQL = PASSIVE_LEVEL seviyesinde ek işleme ihtiyaç duyuyorsa ve alt düzey sürücüler IRP ile işlerini tamamladıktan sonra, sürücünün tamamlama rutini bir iş öğesini kuyruğa almalı ve ardından STATUS_MORE_PROCESSING_REQUIRED durumunu döndürmelidir. Çalışan iş parçacığı IRP'yi tamamlamak zorundadır.

Windows 98/Me'de sürücülerin IRQL = PASSIVE_LEVEL'de güç IRP'lerini tamamlaması gerekir.

Power IRP'de İşlev Kodlarını Değiştirmeyin

IRP'lerin işlenmesini yöneten her zamanki kurallara ek olarak , IRP_MJ_POWER IRP'ler aşağıdaki özel gereksinime sahiptir: Güç IRP'si alan bir sürücü, IRP'deki güç yöneticisi tarafından veya üst düzey sürücüler tarafından ayarlanan G/Ç yığını konumlarındaki ana ve ikincil işlev kodlarını değiştirmemelidir. Power Manager, IRP tamamlanana kadar bu işlev kodlarının değişmeden kalmasına dayanır. Bu kuralın ihlalleri, hata ayıklaması zor sorunlara neden olabilir. Örneğin, işletim sistemi yanıt vermeyi durdurabilir veya "kilitlenebilir".

Güç IRP'lerini İşleme sırasında Engellemeyin

Sürücüler, güç IRP'lerini işlerken uzun gecikmelere neden olmamalıdır.

Güç IRP'sini devrederken, bir sürücü IoCallDriver (Windows 7 ve Windows Vista'da) veya PoCallDriver'ı (Windows Server 2003, Windows XP ve Windows 2000'de) çağırdıktan sonra DispatchPower yordamından en kısa sürede geri dönmelidir. Bir sürücü, bir çekirdek olayını beklememeli veya geri dönmeden önce başka bir gecikmeye neden olmamalıdır. Bir sürücü kısa süre içinde güç IRP'sini işleyemiyorsa, STATUS_PENDING döndürmeli ve güç IRP tamamlanana kadar tüm gelen IRP'leri kuyruğa almalıdır. (Bu davranışın, engellemesine izin verilen PnP IRP'lerinden ve DispatchPnP yordamlarından farklı olduğunu unutmayın.)

Sürücü, cihaz yığınının daha aşağısına doğru başka bir sürücünün güç eylemini beklemesi gerekiyorsa DispatchPower yordamından STATUS_PENDING döndürmeli ve güç IRP için bir IoCompletion yordamı ayarlamalıdır. Sürücü IoCompletion yordamında gereken görevleri gerçekleştirebilir ve ardından PoStartNextPowerIrp (yalnızca Windows Server 2003, Windows XP ve Windows 2000) ve IoCompleteRequest'i çağırabilir.

Örneğin, bir cihazın güç politikası sahibi, bir sistem güç IRP'si tutarken genellikle istenen sistem güç durumuna uygun cihaz güç durumunu ayarlamak için bir cihaz güç IRP'si gönderir.

Bu durumda, güç yönetimi ilkesi sahibi sistem gücü IRP'sinde bir IoCompletion yordamı ayarlamalı, sistem gücü IRP'sini bir alt sürücüye geçirmeli ve DispatchPower yordamından STATUS_PENDING döndürmelidir.

IoCompletion yordamında, cihaz gücü IRP'sini göndermek için PoRequestPowerIrp'i çağırır ve istekteki bir geri çağırma yordamına bir işaretçi geçirir. IoCompletion yordamı STATUS_MORE_PROCESSING_REQUIRED döndürmelidir.

Son olarak, sürücü sistem IRP'sini geri çağırma yordamından geçirir. Sürücü, şu anda işlemekte olduğu IRP için DispatchPower yordamında çekirdek olayını beklememeli ve IoCompletion yordamı ile sinyal vermemelidir; aksi takdirde sistem kilitlenmesi meydana gelebilir. Daha fazla bilgi için bkz . Cihaz Güç İlkesi Sahibinde Sistem Set-Power IRP İşleme.

Benzer bir durumda, sistem uyku moduna geçtiğinde, güç ilkesi sahibinin cihazı kapatmak için cihaz IRP'sini göndermeden önce bekleyen bazı G/Ç'leri tamamlaması gerekebilir. G/Ç tamamlandığında ve DispatchPower yordamında beklediğinde bir olaya sinyal göndermek yerine, sürücü bir iş öğesini kuyruğa almalı ve DispatchPower yordamından STATUS_PENDING döndürmelidir. Çalışan iş parçacığında G/Ç'nin tamamlanmasını bekler ve ardından cihaz güç IRP'sini gönderir. Daha fazla bilgi için bkz. IoAllocateWorkItem.