前言 :
在核心模式下, 有一系列的同步物件與使用者模式下的同步物件相對應. 在使用者模式下, 各個函式都是以控制碼操作同步物件的. 而在使用者模式下, 程式設計師無法獲得真實同步物件的指標, 而用一個控制碼代表這個物件. 在核心模式下, 程式設計師可以獲得真實同步物件的指標.
每種同步物件在內核中都會對應一種資料結構. 因為在核心模式下, 程式設計師可以很自由地操作這些物件, 因此很可能因為不小心造成系統的鎖死.
核心模式下的等待 :
在核心模式下, 同樣也有兩個函式負責等待內核同步物件, 分別是 KeWaitForSingleObject 和 KeWaitForMultipleObjects 函式. 其實使用者模式下的 WaitForSingleObject 和 WaitForMultipleObjects 函式都是依靠核心模式下的這兩支函式實現的. KeWaitForSingleObject 函式負責等待單個同步物件, 其宣告如下 :
核心模式下的 KeWaitForSingleObject 函式比使用者模式下的 WaitForSingleObject 函式多了一些參數, 說明如下 :
如果等待的同步物件變為激發狀態, 這個函式會退出睡眠狀態, 並返回 STATUS_SUCCESS. 如果這個函式是因為超時而退出, 則會返回 STATUS_TIMEOUT.
KeWaitForMultipleObjects 負責在核心模式下等待多個同步物件, 其宣告如下 :
第一個參數 Count 為等待同步物件的個數, 第二個參數 Object 是同步物件的陣列, 第三個參數 WaitType 指示是等待任意一個同步物件還是等待所有的同步物件. 剩下的參數 WaitType, WaitReason, WaitMode 等作用同 KeWaitForSingleObject 參數說明.
如果這個函式是因為超時而退出, 則返回 STATUS_TIMEOUT. 如果是因為陣列中其中一個同步物件變為激發狀態, 這個函式返回的狀態碼減去 STATUS_WAIT_0, 就是激發的同步物件在陣列中的索引號. 下面範例代碼說明如何使用 KeWaitForMultipleObjects 函式 :
核心模式下開啟多執行緒 :
一般在多執行緒中才需要同步處理機制, 這裡介紹一下如何在核心模式下新建執行緒. 內核函式 PsCreateSystemThread 負責新建執行緒. 該函式可以新建兩種執行緒. 一種是使用者執行緒, 一種是系統執行緒. 使用者執行緒是屬於當前處理程序中的執行緒. 當前處理程序指的是當前 I/O 操作的發起者. 如果在 IRP_MJ_READ 的派遣函式中呼叫 PsCreateSystemThread 函式新建使用者執行緒, 新執行緒就屬於呼叫 ReadFile 的處理程序.
系統執行緒不屬於當前使用者處理程序, 而屬於系統處理程序. 系統處理程序是作業系統中一個特殊的處理程序. 這個處理程序的 PID 一般為 4, 讀者可以用工作管理員查看該處理程序, 如下圖所示 :
驅動程式中的 DriverEntry 和 AddDevice 等函式都是被某個系統執行緒呼叫的. PsCreateSystemThread 函式宣告如下 :
參數說明 :
在核心模式下, 新建的執行緒必須用函式 PsTerminateSystemThread 強制結束執行緒. 否則該執行緒是無法自動退出的. 這裡介紹一種方法可以方便的讓執行緒知道自己屬於哪個處理程序. 首先使用 IoGetCurrentProcess 函式得到當前執行緒. IoGetCurrentProcess 含是會得到一個 PEPROCESS 資料結構. 該資料結構記錄處理程序的資訊, 其中包括處理程序名. 遺憾的是微軟並沒有在 DDK 中定義 PEPROCESS 結構, 但可以利用微軟的符號表分析這個資料結構. 一般使用 WinDbg 查看這個資料結構. 在 Windows XP 中, PEPROCESS 結構的 0x174 偏移位置記錄著處理程序名. 因此可以用下面方法查看當前處理程序名稱.
下面的程序碼展示如何在驅動程式中新建執行緒. 在例子中分別新建使用者執行緒和系統執行緒. 執行緒還顯示出各自所屬的處理程序名, 代碼如下 :
第二個執行緒是使用者執行緒, 它是在 IRP_MJ_CONTROL 的派遣函式中新建的. 因此這個執行緒屬於 DeviceIOControl 所在的處理程序, 也就是 DDPWraper.exe 處理程序. 第一個新建的執行緒是系統執行緒, 驅動程式輸出 log 資訊如下圖 :
在核心模式下, 有一系列的同步物件與使用者模式下的同步物件相對應. 在使用者模式下, 各個函式都是以控制碼操作同步物件的. 而在使用者模式下, 程式設計師無法獲得真實同步物件的指標, 而用一個控制碼代表這個物件. 在核心模式下, 程式設計師可以獲得真實同步物件的指標.
每種同步物件在內核中都會對應一種資料結構. 因為在核心模式下, 程式設計師可以很自由地操作這些物件, 因此很可能因為不小心造成系統的鎖死.
核心模式下的等待 :
在核心模式下, 同樣也有兩個函式負責等待內核同步物件, 分別是 KeWaitForSingleObject 和 KeWaitForMultipleObjects 函式. 其實使用者模式下的 WaitForSingleObject 和 WaitForMultipleObjects 函式都是依靠核心模式下的這兩支函式實現的. KeWaitForSingleObject 函式負責等待單個同步物件, 其宣告如下 :
核心模式下的 KeWaitForSingleObject 函式比使用者模式下的 WaitForSingleObject 函式多了一些參數, 說明如下 :
如果等待的同步物件變為激發狀態, 這個函式會退出睡眠狀態, 並返回 STATUS_SUCCESS. 如果這個函式是因為超時而退出, 則會返回 STATUS_TIMEOUT.
KeWaitForMultipleObjects 負責在核心模式下等待多個同步物件, 其宣告如下 :
第一個參數 Count 為等待同步物件的個數, 第二個參數 Object 是同步物件的陣列, 第三個參數 WaitType 指示是等待任意一個同步物件還是等待所有的同步物件. 剩下的參數 WaitType, WaitReason, WaitMode 等作用同 KeWaitForSingleObject 參數說明.
如果這個函式是因為超時而退出, 則返回 STATUS_TIMEOUT. 如果是因為陣列中其中一個同步物件變為激發狀態, 這個函式返回的狀態碼減去 STATUS_WAIT_0, 就是激發的同步物件在陣列中的索引號. 下面範例代碼說明如何使用 KeWaitForMultipleObjects 函式 :
核心模式下開啟多執行緒 :
一般在多執行緒中才需要同步處理機制, 這裡介紹一下如何在核心模式下新建執行緒. 內核函式 PsCreateSystemThread 負責新建執行緒. 該函式可以新建兩種執行緒. 一種是使用者執行緒, 一種是系統執行緒. 使用者執行緒是屬於當前處理程序中的執行緒. 當前處理程序指的是當前 I/O 操作的發起者. 如果在 IRP_MJ_READ 的派遣函式中呼叫 PsCreateSystemThread 函式新建使用者執行緒, 新執行緒就屬於呼叫 ReadFile 的處理程序.
系統執行緒不屬於當前使用者處理程序, 而屬於系統處理程序. 系統處理程序是作業系統中一個特殊的處理程序. 這個處理程序的 PID 一般為 4, 讀者可以用工作管理員查看該處理程序, 如下圖所示 :
驅動程式中的 DriverEntry 和 AddDevice 等函式都是被某個系統執行緒呼叫的. PsCreateSystemThread 函式宣告如下 :
參數說明 :
在核心模式下, 新建的執行緒必須用函式 PsTerminateSystemThread 強制結束執行緒. 否則該執行緒是無法自動退出的. 這裡介紹一種方法可以方便的讓執行緒知道自己屬於哪個處理程序. 首先使用 IoGetCurrentProcess 函式得到當前執行緒. IoGetCurrentProcess 含是會得到一個 PEPROCESS 資料結構. 該資料結構記錄處理程序的資訊, 其中包括處理程序名. 遺憾的是微軟並沒有在 DDK 中定義 PEPROCESS 結構, 但可以利用微軟的符號表分析這個資料結構. 一般使用 WinDbg 查看這個資料結構. 在 Windows XP 中, PEPROCESS 結構的 0x174 偏移位置記錄著處理程序名. 因此可以用下面方法查看當前處理程序名稱.
- PEPROCESS pEProcess = IoGetCurrentProcess();
- PTSTR ProcessName = (PTSTR)((ULONG)pEProcess + 0x174);
- KdPrint(("This thread run in %s process!\n", ProcessName));
第二個執行緒是使用者執行緒, 它是在 IRP_MJ_CONTROL 的派遣函式中新建的. 因此這個執行緒屬於 DeviceIOControl 所在的處理程序, 也就是 DDPWraper.exe 處理程序. 第一個新建的執行緒是系統執行緒, 驅動程式輸出 log 資訊如下圖 :
This message was edited 10 times. Last update was at 07/01/2011 15:46:12
沒有留言:
張貼留言