64位內核開發第十講,IRQL中斷級別瞭解

中斷級別IROL瞭解

一丶IRQL

1.瞭解什麼是中斷

中斷就是產生的一個電信號.好比鍵盤.當按下就會產生電信號發送給CPU
而CPU就會中止當前處理.去執行電信號.他是根據IRQL中斷級別來進行處理的.
以下圖:
函數

中斷說白了就是個電信號.打斷CPU執行的代碼. 去調用中斷處理函數.
此時CPU就處於硬件上下文.spa

2.IROL中斷級別.

由於會產生不少CPU電信號.全部硬件同是發送中斷處理級別怎麼辦.因此須要爲這些級別分一個優先級. CPU會先執行優先級高的.會把優先級低的給屏蔽掉.線程

當CPU處於中斷上下文的時候. CPU不能是阻塞的/阻塞. 沒有進程能夠調度.code

瞭解CPU的上下文.至少腦海須要有印象blog

上下文 說明
中斷上下文 CPU代替硬件作某些事情.
進程上下文 CPU代替進程作某些事情.

中斷級別瞭解
以下圖:
進程

軟件中只會處理下面三種級別.
DISPATCH_LEVEL最高
APC_LEVEL 其次
PASSIVE_LEVEL最低內存

3.遵照IROL編程規範的方式

1.查詢MSDN.MSDN最下面有IRQL級別的說明.回調函數

  1. 運行在DISPATHCH_LEVEL級別的上下文.如何調用PASSIVE_LEVEL級別的函數.
    如咱們有一個需求.
    當鍵盤按下的時候. 鍵盤的優先級最高. 會運行在DISPATCH_LEVEL級別.可是此時
    按照咱們Ring3編程的想法.你可能會調用ZwCreateFile這個函數進行將按鍵寫入到文件中.
    可是此時咱們若是查詢MSDN以後就會發現.其實ZwCreateFile是不能運行在DISPATCH級別的. 此時解決方法 就是建立一個 工做線程. 工做線程中完成
    咱們想要操做的事情.

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 放到咱們代碼塊中便可.

相關文章
相關標籤/搜索