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.
Giriş
Bu sürücü geliştirme yönergeleri, Microsoft'taki sürücü geliştiricileri tarafından yıllar boyunca geliştirilmiştir. Zamanla, sürücülerin yanlış davranmaları sonucunda dersler öğrenildi ve bu dersler kaydedilip bu kılavuz haline geldi. Bu en iyi yöntemler, Microsoft Surface Donanım ekibi tarafından benzersiz Surface donanım deneyimlerini destekleyen cihaz sürücü kodunu geliştirmek ve korumak için kullanılır.
Tüm yönergelerde olduğu gibi, aynı şekilde geçerli olacak yasal özel durumlar ve alternatif yaklaşımlar olacaktır. Bu yönergeleri geliştirme standartlarınıza dahil etmeyi veya geliştirme ortamınıza ve benzersiz gereksinimlerinize yönelik etki alanına özgü yönergeleri başlatmak için kullanmayı göz önünde bulundurun.
Sürücü geliştiricileri tarafından yapılan yaygın hatalar
G/Ç İşleme
- Uzunluğu doğrulamadan IOCTL'lerden alınan arabelleklere erişme. Bkz. Arabelleklerin Boyutunu Denetleme Hatası.
- Kullanıcı iş parçacığı veya rastgele iş parçacığı bağlamında bloklayıcı G/Ç gerçekleştirme. Bkz. Çekirdek Dağıtıcı Nesnelerine Giriş.
- Zaman aşımı olmadan başka bir sürücüye senkron G/Ç gönderme. Bkz. G /Ç İsteklerini Zaman Uyumlu Olarak Gönderme.
- Güvenlik etkilerini anlamadan neither-io IOCTL'leri kullanma. Bkz. Ne Arabelleğe Alınan Ne de Doğrudan G/Ç Kullanma.
- WdfRequestForwardToIoQueue'un dönüş durumu kontrol edilmediğinde veya hatalar düzgün bir şekilde ele alınmadığında, sonucunda WDFREQUEST'lerin bırakılması söz konusu olur.
- WDFREQUEST'i sıranın dışında iptal edilemeyen bir durumda tutma. Bkz. G/Ç Kuyruklarını Yönetme, G/Ç İsteklerini Tamamlama ve G/Ç İsteklerini İptal Etme.
- IoQueues yerine Mark/UnmarkCancelable işlevini kullanarak iptali yönetmeye çalışıyor. Bkz. Çerçeve Kuyruk Nesneleri.
- Dosya işleme Temizleme ve Kapatma işlemleri arasındaki farkı bilmeme. Bkz. Temizleme ve Kapatma İşlemlerini İşleme hataları.
- G/Ç tamamlama ve tamamlama rutininden yeniden gönderimle muhtemel özyinelemeleri gözden kaçırma.
- WDFQUEUE'lerin güç yönetimi öznitelikleri hakkında açık değildir. Güç yönetimi seçimini net bir şekilde belgelememe. WDF sürücülerinde Hata Denetimi 0x9F: DRIVER_POWER_STATE_FAILURE'ın birincil nedeni budur. Cihaz kaldırıldığında, sistem G/Ç'yi kaldırma sürecinin farklı aşamalarında güç yönetimli kuyruktan ve güç yönetimsiz kuyruktan çıkarır. Güç yönetimine tabi olmayan kuyruklar, son IRP_MN_REMOVE_DEVICE alındığında temizlenir. Bu nedenle G/Ç'yi güçle yönetilmeyen bir kuyrukta tutuyorsanız kilitlenmeyi önlemek için G/Ç'yi EvtDeviceSelfManagedIoFlush bağlamında açıkça temizlemek iyi bir uygulamadır.
- IRP işleme kurallarına uyulmuyor. Bkz. Temizleme ve Kapatma İşlemlerini İşleme hataları.
Senkronizasyon
- Koruma gerektirmeyen kod için kilit tutma. Yalnızca az sayıda işlemin korunması gerektiğinde işlevin tamamı için kilit tutmayın.
- Kilitleri tutan sürücüleri çağırmak. Kilitlenmelerin birincil nedenleri budur.
- Mutex, semaphore ve spinlocks gibi kilit temel öğelerinin uygun sistem tarafından sağlanması yerine kilitleme düzeni oluşturmak için kilitlenmiş ilkelleri kullanma. Bkz. Mutex Nesnelerine Giriş, Semafor Nesneleri ve Döndürme Kilitlerine Giriş.
- Daha uygun olan bir tür pasif kilit yerine spinlock kullanmak. Bkz. Hızlı Mutex'ler ve Korunan Mutex'ler ve Olay Nesneleri. Kilitler üzerine daha fazla bilgi için OSR Makalesi - Eşitleme Durumu'nu inceleyin.
- Etkileri tam olarak anlamadan WDF eşitleme ve yürütme düzeyi modeline katılma. Bkz. Çerçeve Kilitlerini Kullanma. Sürücünüz, donanımla doğrudan etkileşime giren bir monolitik üst düzey sürücü değilse, özyineleme nedeniyle oluşabilecek kilitlenmeleri önlemek için WDF eşitlemesini kabul etmekten kaçının.
- KEVENT, Semaphore, ERESOURCE, UnsafeFastMutex'i, kritik bölgelere girmeden çoklu iş parçacığı bağlamında almak. Bunu yapmak DOS saldırısına yol açabilir çünkü bu kilitlerden birini tutan bir iş parçacığı askıya alınabilir. Bkz. Çekirdek Dağıtıcı Nesnelerine Giriş.
- KEVENT'i iş parçacığı yığınına ayırma ve EVENT hala kullanımdayken çağırana geri dönme. Genellikle IoBuildSyncronousFsdRequest veya IoBuildDeviceIoControlRequest ile kullanıldığında yapılır. Bu çağrıları çağıran, IRP tamamlandığında G/Ç yöneticisi olayın sinyalini verene kadar yığından geri adım atmadığından emin olmalıdır.
- Dağıtım yordamlarında süresiz olarak bekleniyor. Genel olarak, dağıtım yordamında her türlü bekleme kötü bir uygulamadır.
- Silmeden önce nesnenin geçerliliğini uygunsuz bir şekilde denetleme (blah == NULL ise). Bu genellikle yazarın nesnenin ömrünü denetleyen kodu tam olarak anlamadığı anlamına gelir.
Nesne Yönetimi
- WDF nesnelerine açıkça ebeveynlik yapılmaz. Bkz. Çerçeve Nesnelerine Giriş.
- Daha iyi yaşam süresi yönetimi sağlayan ve bellek kullanımını en iyi duruma getiren bir nesneye üst öğe eklemek yerine WDF nesnesini WDFDRIVER'a üst öğe ekleme. Örneğin, WDFREQUEST'i IOTARGET yerine WDFDEVICE'ye ebeveyn olarak ekleme. Bkz. Genel Çerçeve Nesnelerini Kullanma, Çerçeve Nesnesi Yaşam Döngüsü ve Çerçeve Nesnelerinin Özeti.
- Sürücüler arasında erişilen paylaşılan bellek kaynaklarının çöküşe karşı korunması yapılmaz. Bkz ExInitializeRundownProtection işlevi.
- Bir önceki zaten kuyrukta veya zaten çalışıyorken aynı iş öğesini yanlışlıkla kuyruğa alma. İstemci kuyruğa alınan her iş öğesinin yürütüleceğini varsayacak bir varsayımda bulunursa bu sorun olabilir. Bkz. Framework İş Öğeleri kullanma. WorkItems'i kuyruğa alma hakkında daha fazla bilgi için Sürücü Modülü Çerçevesi (DMF) projesindeki DMF_QueuedWorkitem modülüne bakın- https://github.com/Microsoft/DMF.
- Mesajı göndermeden önce zamanlayıcının işlemesi beklenen kuyruğa alma zamanlayıcısı. Bkz . Zamanlayıcıları Kullanma.
- İş öğesinde, süresiz olarak engelleyebilen veya tamamlanması uzun sürebilen bir işlem gerçekleştirme.
- İş öğelerinin kuyruğa alınmasına yol açan bir çözüm tasarlama. Kötü adam eylemi kontrol edebiliyorsa, sistemin yanıt vermemesi veya DOS saldırısına yol açabilir (örneğin, her G/Ç için yeni bir iş öğesi kuyruğa alan bir sürücüye sürekli G/Ç verilmesi). Bkz. Framework İş Öğelerini Kullanma.
- Nesneyi silmeden önce iş öğesi DPC geri çağırmalarının tamamlanmasını sağlamak için çalıştırıldığından emin olunmaması. Bkz. DPC Rutinleri Yazma Yönergeleri ve WdfDpcCancel fonksiyonu.
- Kısa süreli ve yoklama gerektirmeyen görevler için iş öğeleri yerine iş parçacıkları oluşturulması. Bkz. Sistem Çalışanı İş Parçacıkları.
- Sürücüyü silmeden veya kaldırmadan önce iş parçacıklarının tamamlanmaya çalıştığından emin olunmuyor. İş parçacığı çalıştırma eşitlemesi hakkında daha fazla bilgi için Driver Module Framework (DMF) projesindeki DMF_Thread modülüyle ilişkilendirilmiş koda bakın. https://github.com/Microsoft/DMF
- Farklı ancak birbirine bağlı cihazları yönetmek için tek bir sürücü kullanma ve bilgileri paylaşmak için genel değişkenleri kullanma.
Hafıza
- Mümkün olduğunda pasif yürütme kodunu PAGEABLE olarak işaretlememek. Sürücü kodunu disk belleğine alma, sürücünün kod ayak izinin boyutunu küçülterek sistem alanını diğer kullanımlar için boşaltabilir. Kodun IRQL >= DISPATCH_LEVEL yükselten veya yükseltilmiş IRQL'de çağrılabilir durumdayken sayfalanabilir olarak işaretlenmesine dikkat edin. Bkz. Kod ve Veriler Ne Zaman Sayfalanabilir Olmalı ve Sürücüleri Sayfalanabilir Hale Getirme ve Sayfalanabilen Kodu Algılama.
- Yığının üzerinde büyük yapıları tanımlamak yerine, yığın/havuz kullanılmalıdır. Bkz. KernelStack'i Kullanma ve System-Space Belleği Ayırma.
- WDF Nesnesi bağlamını gereksiz yere sıfırlama. Bu, belleğin otomatik olarak ne zaman sıfırlanacağı konusunda netlik eksikliği olduğunu gösterebilir.
Genel Sürücü Yönergeleri
- WDM ve WDF temel öğelerini karıştırma. WDF temel öğelerinin kullanılabileceği yerlerde WDM temel öğelerini kullanma. WDF temel öğelerini kullanmak sizi gotcha'lardan korur, hata ayıklamayı iyileştirir ve daha da önemlisi sürücünüzü kullanıcı moduna taşınabilir hale getirir.
- FDO'ları adlandırma ve gerekmediğinde sembolik bağlantılar oluşturma. Bkz. Sürücü erişim denetimini yönetme.
- Örnek sürücülerden GUID'leri ve diğer sabit değerleri kopyalayıp yapıştırma.
- Sürücü projenizde Driver Module Framework (DMF) açık kaynak kodunu kullanmayı göz önünde bulundurun. DMF, WDF sürücüsü geliştiricisi için ek işlevsellik sağlayan bir WDF uzantısıdır. Bkz . Sürücü Modülü Çerçevesi'ne giriş.
- Kayıt defterini işlemler arası bildirim mekanizması veya posta kutusu olarak kullanma. Alternatif olarak DMF projesinde mevcut DMF_NotifyUserWithEvent ve DMF_NotifyUserWithRequest modüllerine bakın - https://github.com/Microsoft/DMF.
- Kayıt defterinin tüm bölümlerinin sistemin erken önyükleme aşamasında erişim sağlanacağı varsayılır.
- Başka bir sürücünün veya hizmetin yük sırasına bağımlılık alma. Yük sırası sürücünüzün denetimi dışında değiştirilebildiği için bu, başlangıçta çalışan ancak daha sonra öngörülemeyen bir düzende başarısız olan bir sürücüye neden olabilir.
- Mevcut olan sürücü kitaplıklarını, örneğin WDF'nin Sürücünüzde PnP ve Güç Yönetimini Destekleme bölümünde açıklandığı gibi PnP için sağladıklarını veya OSR makalesinde belirtilen Sürücüden Sürücüye İletişim için Veri Yolu Arabirimlerini Kullanma bölümünde anlatıldığı üzere veri yolu arabiriminde sağlananları yeniden oluşturma.
PnP/Güç
- Pnp ile uyumlu olmayan bir şekilde başka bir sürücüyle haberleşme - Pnp cihaz değişikliği bildirimlerine kaydolmama. Bkz . Cihaz Arabirimi Değişiklik Bildirimine Kaydolma.
- PNP ve güç bağımlılıkları için veri yolu sürücüsü veya sistem tarafından sağlanan yazılım cihazı oluşturma arabirimleri yerine cihazları listelemek ve aralarında güç bağımlılıkları oluşturmak için ACPI düğümleri oluşturma. Bkz . İşlev Sürücülerinde PnP ve Güç Yönetimini Destekleme.
- Cihazı devre dışı bırakılamaz olarak işaretleme - sürücü güncelleştirmesinde yeniden başlatmayı zorlama.
- Cihazı cihaz yöneticisinde gizleme. Bkz . Cihazları Cihaz Yöneticisi'nden Gizleme.
- Sürücünün cihazın yalnızca bir tek örneği için kullanılacağına dair varsayımlar yapmak.
- Sürücünün hiçbir zaman boşaltılmayacağı varsayımlarında bulunma. Bkz. PnP Sürücüsünün Kaldırma Yordamı.
- Yanıltıcı arabirim geliş bildirimi işlenmiyor. Bu durum oluşabilir ve sürücülerin bu durumu güvenli bir şekilde işlemesi beklenir.
- DRIPS kısıtlamaları ve bunların alt öğeleri olan cihazlar için önemli olan S0 Boşta güç ilkesinin uygulanmaması. Bkz. Boşta Güç Azaltmayı Destekleyen.
- WdfDeviceStopIdle dönüş değerinin denetlenmemesi, WdfDeviceStopIdle/ResumeIdle dengesizliği ve sonunda 9F hata denetimi nedeniyle güç referansı sızıntısına neden olur.
- Kaynağı yeniden dengeleme nedeniyle PrepareHardware/ReleaseHardware'in birden çok kez çağrılabileceğini bilmemek. Bu geri çağırmalar, donanım kaynaklarını başlatmayla kısıtlanmalıdır. Bkz. EVT_WDF_DEVICE_PREPARE_HARDWARE.
- Yazılım kaynaklarını ayırma için PrepareHardware/ReleaseHardware kullanma. Cihaza statik yazılım kaynağı ayırma işlemi, donanımla etkileşime geçmek için gereken kaynakların ayrılması durumunda AddDevice veya SelfManagedIoInit içinde yapılmalıdır. Bkz. EVT_WDF_DEVICE_SELF_MANAGED_IO_INIT.
Kodlama Yönergeleri
- Güvenli dize ve tamsayı işlevleri kullanılmıyor. Bkz. Güvenli Dize İşlevlerini Kullanma ve Güvenli Tamsayı İşlevlerini Kullanma.
- Sabitleri tanımlamak için typedef kullanmamak.
- Genel değişkenleri ve statik değişkenleri kullanma. Cihaz bağlamı başına genel olarak depolamaktan kaçının. Globaller, birden çok cihaz örneği arasında bilgi paylaşımı içindir. Alternatif olarak, birden çok cihaz örneğinde bilgi paylaşmak için WDFDRIVER nesne bağlamını kullanmayı göz önünde bulundurun.
- Değişkenler için açıklayıcı adlar kullanılmıyor.
- Adlandırma değişkenlerinde tutarlı olmaması - büyük/küçük harf tutarlılığı. Mevcut kodda güncelleştirmeler yapılırken mevcut kodlama stiline uyulmuyor. Örneğin, farklı işlevlerdeki ortak yapılar için farklı değişken adları kullanma.
- Güç yönetimi, kilitler, durum yönetimi, iş öğelerinin kullanımı, DC'ler, zamanlayıcılar, genel kaynak kullanımı, kaynak ön ayırma, karmaşık ifadeler/koşullu deyimler gibi önemli tasarım seçeneklerine yorum yapılmaz.
- Çağrılan API'nin adından açıkça belli olan şeyler hakkında yorum yapma. Açıklamanızı işlev adının İngilizce diliyle eşdeğer hale getirme (WdfDeviceCreate çağrısı yaparken "Cihaz Nesnesi Oluştur" açıklamasını yazma gibi).
- Dönüş çağrısı olan makrolar oluşturmayın. Bkz. İşlevler (C++).
- Kaynak Kodu Ek Açıklamaları (SAL) yok veya tamamlanmadı. Bkz. Windows Sürücüleri için SAL 2.0 Ek Açıklamaları.
- Satır içi işlevler yerine makroları kullanma.
- C++ kullanırken constexpr yerine sabitler için makro kullanma
- Derleyicinizi C++ derleyicisi yerine C derleyicisini kullanarak derleyin, böylece güçlü tür denetimi aldığınızdan emin olun.
Hata İşleme
- Kritik sürücü hatalarını bildirmiyor ve cihazı düzgün bir şekilde işlevsel değil olarak işaretliyor.
- Anlamlı WIN32 hata durumuna çevrilen uygun NT hata durumu döndürülmedi. Bkz. NTSTATUS Değerlerini Kullanma.
- Sistem işlevlerinin döndürülen durumunu denetlemek için NTSTATUS makroları kullanılmıyor.
- Gerekli olan yerlerde durum değişkenleri veya bayraklar üzerinde doğrulama yapılmaması.
- Yarış koşullarına geçici bir çözüm bulmak için işaretçiye erişmeden önce geçerli olup olmadığını denetleyin.
- NULL işaretçilerle ASSERT uygulaması. Belleğe erişmek için NULL işaretçisi kullanmayı denerseniz Windows hata denetimi yapacaktır. Hata denetiminin parametreleri, null işaretçiyi düzeltmek için gerekli bilgileri sağlar. Zamanla, birçok gereksiz ASSERT deyimi koda eklendiğinde, bunlar bellek tüketir ve sistemi yavaşlatır.
- Nesne bağlam işaretçisini doğrulama. Sürücü çerçevesi, nesnenin her zaman bağlamla ayrılacağını garanti eder.
İzleme
- WPP özel türlerini tanımlamama ve insan tarafından okunabilir izleme iletileri almak için izleme çağrılarında kullanma. Bkz. Windows Sürücüsüne WPP Yazılım İzleme Ekleme.
- IFR izlemesi kullanılmıyor. Bkz. KMDF ve UMDF 2 Sürücülerinde Trafik İzleme Kaydedicisi (IFR) Kullanma.
- WPP izleme çağrılarında işlev isimlerini çağırma. WPP zaten işlev adlarını ve satır numaralarını izler.
- Performansı ve olayları etkileyen diğer kritik kullanıcı deneyimini ölçmek için ETW olaylarını kullanmama. Bkz. Kernel-Mode Sürücülerine Olay İzleme Ekleme.
- Olay günlüğünde kritik hataları rapor etmeyip cihazı zarif bir şekilde işlevsiz olarak işaretleme.
Doğrulama
- Geliştirme ve test sırasında hem standart hem de gelişmiş ayarlarla sürücü doğrulayıcı çalıştırılmıyor. Bkz . Sürücü Doğrulayıcı. Gelişmiş ayarlarda, düşük kaynak benzetimiyle ilgili kurallar dışında tüm kuralların etkinleştirilmesi önerilir. Sorunlarda hata ayıklamayı kolaylaştırmak için düşük kaynaklı simülasyon testlerinin izole olarak çalıştırılması tercih edilir.
- Gelişmiş doğrulayıcı ayarları etkinken sürücüde veya sürücünün parçası olduğu cihaz sınıfında DevFund testi çalıştırılmıyor. Bkz. Komut satırı aracılığıyla DevFund Testlerini çalıştırma.
- Sürücünün HVCI uyumlu olduğu doğrulanmıyor. Bkz. HVCI uyumluluk kodunu uygulama.
- Kullanıcı modu sürücülerinin geliştirilmesi ve test edilmesi sırasında WUDFhost.exe AppVerifier çalıştırılmıyor. Bkz. Uygulama Doğrulayıcı.
- WDF nesnelerinin terk edilmediğinden emin olmak için çalışma zamanında !wdfpoolusage hata ayıklayıcısı uzantısını kullanarak bellek kullanımı denetlenmiyor. Bellek, istekler ve iş öğeleri bu sorunların yaygın kurbanlarıdır.
- Nesnelerin doğru üst öğeye sahip olduğundan emin olmak için nesne ağacını incelemek için !wdfkd hata ayıklayıcısı uzantısını kullanmamak ve WDFDRIVER, WDFDEVICE, GÇ gibi ana nesnelerin özniteliklerini denetlemek.