windows驅動開發中,感受不少小問題都會致使一些比較麻煩的錯誤,不少不良習慣均可能會致使系統崩潰。緣由是對內核原理的理解太欠缺了,由於驅動運行在RING0優先級,開發的時候必須至關注意細節,否則調試的時候會很麻煩(有些時候Dump文件分析出來是錯誤的)。原來我一直奇怪寫驅動程序問什麼要把有些例程放到非分頁內存中,今天算是豁然開朗。只怪原來看內核原理的時候沒太仔細。具體緣由是這樣的:由於windows的缺頁中斷處理程序是運行在DISPATCH_LEVEL的級別的。而個人驅動某些例程通常是等於DISPATCH_LEVEL這個中斷級別。也就是說。。若是我把個人代碼放到分頁內存中。。那操做系統極可能在某個時候就把它從物理內存換出到磁盤頁面交換文件中了。。而後EIP指針若是訪問到的下一個內存頁在換頁文件中。。那操做系統將產生缺頁中斷。。而後這缺頁中斷的級別與個人代碼例程是一個級別的。。因此不能被打斷。。EIP就會訪問的一個錯誤的內存地址(極可能讀/寫到了其餘進程,也多是系統中重要的數據)上,,用戶層的程序內存訪問違例的異常操做系統能捕捉到。反饋給用戶。。。而在驅動內核層內存訪問錯誤。。這是一個很嚴重的問題。。操做系統發現當即就以藍屏的方式處理了。。嚴重的還致使系統崩潰。就悲劇了。。。另外還有一點就是OS的線程調度程序也運行在這個級別。。這也應該有意識。。否則引發線程切換致使藍屏也時常發生。。。。。。。。
TIPS:
DISPATCH > APC > PASSIVE
IRQL是Interrupt ReQuest Level,中斷請求級別。一個由windows虛擬出來的概念,劃分在windows下中斷的優先級,這裏中斷包括了硬中斷和軟中斷,硬中斷是由硬件產生,而軟中斷則是徹底虛擬出來的。
處理器在一個IRQL上執行線程代碼。IRQL是幫助決定線程如何被中斷的。在同一處理器上,線程只能被更高級別IRQL的線程能中斷。每一個處理器都有本身的中斷IRQL。
咱們在調用NDIS API時,在DDK幫助文檔中都有該API函數的所在級別。
PASSIVE_LEVEL
IRQL最低級別,沒有被屏蔽的中斷,在這個級別上,線程執行用戶模式,能夠訪問分頁內存。
APC_LEVEL
在這個級別上,只有APC級別的中斷被屏蔽,能夠訪問分頁內存。當有APC發生時,處理器提高到APC級別,這樣,就屏蔽掉其它APC,爲了和APC執行一些同步,驅動程序能夠手動提高到這個級別。好比,若是提高到這個級別,APC就不能調用。在這個級別,APC被禁止了,致使禁止一些I/O完成APC,因此有一些API不能調用。
DISPATCH_LEVEL
這個級別,DPC 和更低的中斷被屏蔽,不能訪問分頁內存,全部的被訪問的內存不能分頁。由於只能處理非分頁內存,因此在這個級別,可以訪問的Api大大減小。windows