在驅動程式中建立執行緒的方法是呼叫 pscreatesystemthread 核心函式,此函式即可以建立系統執行緒,也可以建立使用者執行緒。此函式的原型如下:
ntstatus pscreatesystemthread(
_out_ phandle threadhandle,
_in_ ulong desiredaccess,
_in_opt_ pobject_attributes objectattributes,
_in_opt_ handle processhandle,
_out_opt_ pclient_id clientid,
_in_ pkstart_routine startroutine,
_in_opt_ pvoid startcontext
);
引數1:乙個 handle 型別的指標,用於輸出建立的執行緒控制代碼。此控制代碼必須在不需要使用時通過 zwclose 釋放。
引數2:建立執行緒的許可權,一般設定為0。
引數3:指向指定物件的屬性的結構,一般設定為 null 。
引數4:如果為 null ,則執行緒屬於系統。如果指定乙個程序控制代碼,則執行緒屬於該程序,通過 ntcurrentprocess 巨集可以得到當前程序控制代碼。
引數5:用於接收客戶端id,一般為 null 。
引數6:執行緒的啟動函式指標。
引數7:傳遞給啟動函式的資料。
執行緒啟動函式原型:
kstart_routine threadstart;
void threadstart(
_in_ pvoid startcontext
)
需要注意,和使用者模式執行緒不同,執行緒必須呼叫 psterminatesystemthread (或系統關機)才會退出,而不是函式返回即退出。
驅動程式進行等待可以通過 kewaitforsingleobject 和 kewaitformultipleobjects 進行等待,其實使用者模式下的 waitforsingleobject 和 waitformultipleobjects 就是呼叫了這兩個函式,先來看看函式原型:
ntstatus kewaitforsingleobject(
_in_ pvoid object,
_in_ kwait_reason waitreason,
_in_ kprocessor_mode waitmode,
_in_ boolean alertable,
_in_opt_ plarge_integer timeout
);ntstatus kewaitformultipleobjects(
_in_ ulong count,
_in_ pvoid object,
_in_ wait_type waittype,
_in_ kwait_reason waitreason,
_in_ kprocessor_mode waitmode,
_in_ boolean alertable,
_in_opt_ plarge_integer timeout,
_out_opt_ pkwait_block waitblockarray
);
解釋一下 kewaitforsingleobject :
引數1:同步物件的指標。(不是控制代碼)
引數2:指定等待的原因。驅動程式應將該值設定為 executive ,除非是做代表使用者的工作,並在使用者執行緒的上下文中,在這種情況下,應該將該值設定為執行 userrequest 。
引數3:說明是在核心模式等待還是在使用者模式等待(kernelmode or usermode)一般設定為 kernelmode 。
引數4:設定等待是否「警惕」,一般為 false 。
和使用者模式下的同步物件大致一樣,因為使用者模式同步物件就是通過呼叫核心同步物件函式建立的。
在應用程式中我們只能得到同步物件的指標,而在驅動程式中我們可以直接使用事件物件的指標!
對於各函式我想我不必乙個個解釋了,msdn說的很清楚了,這裡只起乙個引導和區分作用。
1。事件
建立事件:keinitializeevent
建立命名事件:iocreatenotificationevent 和 iocreatesynchronizationevent
命名的事件物件的好處是,可以方便在不同驅動中找到事件物件的指標。
notificationevent(通知事件)和 synchronizationevent(同步事件)的區別:前者由未激發變為激發時,需要手動變成未激發,而後者激發後呼叫 kewaitfor… 函式就會自動變為未激發。
2。自旋鎖
獲取自旋鎖:keacquirespinlock
釋放自旋鎖:kereleasespinlock
自旋鎖有「鎖住」和「解鎖」狀態,當執行緒獲取自旋鎖時,如果處於解鎖狀態就可以被獲取,獲取會自動鎖住自旋鎖,必須釋放後才能解鎖;如果獲取時處於鎖住狀態,那麼執行緒就會不停地「自旋」,即執行緒不停地常數獲取自旋鎖,直到獲取到為止。自旋鎖不能工作在 irql dispatch_level 中斷請求級。
特別需要注意:執行緒如果等待乙個「事件」物件,那麼執行緒就會休眠,作業系統會去排程其他執行緒,而獲取自旋鎖不同,執行緒會一直「自旋」,會浪費寶貴的 cpu 時間,因此獲取自旋鎖後到釋放之前的時間不要過長。
3。互斥體/快速互斥體
建立互斥體:keinitializemutex
釋放互斥體:kereleasemutex
建立快速互斥體:exinitializefastmutex
釋放快速互斥體:exreleasefastmutex
快速互斥體不能被執行緒遞迴獲取。
只有乙個執行緒可以占用互斥體,獲取互斥體的執行緒如果不釋放互斥體,其他執行緒就不能得到互斥體,執行緒獲取到乙個互斥體時,互斥體變為激發,釋放乙個互斥體時,互斥體變為未激發。互斥體未激發時,等待互斥體就可以獲取他,激發時則會使執行緒休眠,直到指定互斥體被釋放後,才會有且僅有乙個等待該互斥體的執行緒獲取該互斥體。
4。訊號量
建立訊號量:keinitializesemaphore
釋放訊號量: kereleasesemaphore
訊號量同樣有激發和未激發兩種狀態,他的特殊之處是內部維護乙個計數器,只要計數器不小於1就是激發狀態,否則是未激發狀態。
核心執行緒之間的同步,R3執行緒和核心執行緒的同步
當執行緒1需要等待執行緒2處理一些事情的時候就用到這種執行緒同步機制 1 事件,訊號燈,互斥體都是執行緒之間通訊的方式,事件的通訊能滿足大部分需求。2 休眠函式 large integer sleeptime 定義乙個休眠的時間 sleeptime.quadpart 100 10 100 3 這裡是...
後端開發核心技術 第9章多執行緒 多執行緒的建立與結束
include int pthread create pthread t restrict tidp,const pthread attr t restrict attr,void start rtn void void restrict arg 返回值若成功則返回0,否則返回出錯編號 引數 第乙個...
執行緒實現的兩種方式 使用者空間和核心中
特點 整個執行緒包放入使用者空間中,核心對執行緒包一無所知。從核心角度考慮,就是按正常的方式管理,即單執行緒程序 優點 1 使用者級執行緒包可以在不支援執行緒的作業系統上實現 2 執行緒切換比核心快更多 3 允許每個程序有自己定製的排程演算法 缺點 執行緒發生i o或頁面故障引起的阻塞時,如果呼叫阻...