中斷就是產生的一個電信號.好比鍵盤.當按下就會產生電信號發送給CPU
而CPU就會中止當前處理.去執行電信號.他是根據IRQL中斷級別來進行處理的.
以下圖:
函數
中斷說白了就是個電信號.打斷CPU執行的代碼. 去調用中斷處理函數.
此時CPU就處於硬件上下文.spa
由於會產生不少CPU電信號.全部硬件同是發送中斷處理級別怎麼辦.因此須要爲這些級別分一個優先級. CPU會先執行優先級高的.會把優先級低的給屏蔽掉.線程
當CPU處於中斷上下文的時候. CPU不能是阻塞的/阻塞. 沒有進程能夠調度.code
瞭解CPU的上下文.至少腦海須要有印象blog
上下文 | 說明 | |
---|---|---|
中斷上下文 | CPU代替硬件作某些事情. | |
進程上下文 | CPU代替進程作某些事情. |
中斷級別瞭解
以下圖:
進程
軟件中只會處理下面三種級別.
DISPATCH_LEVEL最高
APC_LEVEL 其次
PASSIVE_LEVEL最低內存
1.查詢MSDN.MSDN最下面有IRQL級別的說明.回調函數
3.在PASSIVE級別下.咱們可使用任何內存沒有限制.it
首先了解下以下表格.
函數 | 運行級別 | |
---|---|---|
DriverEntry | Passive級別. | |
各類派遣函數 | Passive級別 | |
完成函數 | Dispatch級別 | |
各類NDIS回調函數 | Dispatch級別 |
PASSIVE級別是可使用任何函數和內存
DISPATCH級別只能訪問能運行在DISPATCH級別內存.
非分頁內存
NONPAGEPOOL 內存是能夠在任何級別使用的.
相關申請內存函數爲:
ExAllocatePoolWithTag
PAGEDPOOL 分頁內存
只能在PASSIVE級別或者APC級別使用.
咱們能夠加入一個宏.來判斷當前的中斷級別.有沒有高於APC
產生一個斷言.若是當前級別大於APC級別就會報錯.
斷言宏的意思就是 我決定當前的事就是某事. 若是你不是我指定的.
那麼對不起.報錯.
使用PAGE_CODE這個宏便可.
其實很簡單.宏站看看一下.
#define PAGED_CODE() PAGED_ASSERT(KeGetCurrentIrql() <= APC_LEVEL); #if (NTDDI_VERSION >= NTDDI_VISTA) #define PAGED_ASSERT( exp ) NT_ASSERT( exp ) #else #define PAGED_ASSERT( exp ) ASSERT( exp ) #endif 往下跟不少..... 直到最終 #define NT_ASSERT_ACTION(_exp) \ ((!(_exp)) ? \ (__annotation(L"Debug", L"AssertFail", L#_exp), \ DbgRaiseAssertionFailure(), FALSE) : \ TRUE)
其實很簡單. 首先調用 KeGetCurrentIrql()
這個函數來判斷是否小於等於 APC級別.
而後當參數傳遞給 PAGED_ASSERT(exp)宏. 裏面就調用函數進行斷言
斷言宏只會在Debug版本中有效.讓咱們儘快發現問題. 把 PAGE_CODE 放到咱們代碼塊中便可.