![WDM驅(qū)動程序設(shè)計_第1頁](http://file3.renrendoc.com/fileroot_temp3/2022-1/9/1b7dc067-739c-4472-98e2-fe87f1523dae/1b7dc067-739c-4472-98e2-fe87f1523dae1.gif)
![WDM驅(qū)動程序設(shè)計_第2頁](http://file3.renrendoc.com/fileroot_temp3/2022-1/9/1b7dc067-739c-4472-98e2-fe87f1523dae/1b7dc067-739c-4472-98e2-fe87f1523dae2.gif)
![WDM驅(qū)動程序設(shè)計_第3頁](http://file3.renrendoc.com/fileroot_temp3/2022-1/9/1b7dc067-739c-4472-98e2-fe87f1523dae/1b7dc067-739c-4472-98e2-fe87f1523dae3.gif)
![WDM驅(qū)動程序設(shè)計_第4頁](http://file3.renrendoc.com/fileroot_temp3/2022-1/9/1b7dc067-739c-4472-98e2-fe87f1523dae/1b7dc067-739c-4472-98e2-fe87f1523dae4.gif)
![WDM驅(qū)動程序設(shè)計_第5頁](http://file3.renrendoc.com/fileroot_temp3/2022-1/9/1b7dc067-739c-4472-98e2-fe87f1523dae/1b7dc067-739c-4472-98e2-fe87f1523dae5.gif)
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、WDM驅(qū)動程序設(shè)計同步技術(shù)第 5 講主要內(nèi)容 一個同步問題的例子 中斷請求級 自旋鎖 內(nèi)核同步對象 其它內(nèi)核同步原語一個同步問題的例子下面利用靜態(tài)變量lActiveRequests記錄當前未完成的I/O請求數(shù): static LONG lActiveRequests;NTSTATUS DispatchPnp(PDEVICE_OBJECT fdo, PIRP Irp) +lActiveRequests; . / process PNP request -lActiveRequests;有什么問題?關(guān)于語句“+lActiveRequests”在X86處理器上匯編程序生成如下代碼: / +lActi
2、veRequests; mov eax, lActiveRequests add eax, 1 mov lActiveRequests, eax 上述代碼的第三條指令被執(zhí)行之前如果被同一CPU上的其它執(zhí)行線程打斷,或者在不同CPU上有完全相同的代碼在同時運行都會引起+lActiveRequests的計數(shù)錯誤。解決的辦法把load/add/store和load/subtract/store指令序列替換為原子指令: / +lActiveRequests; inc lActiveRequests / -lActiveRequests; dec lActiveRequests INC和DEC指令不能被
3、中斷,但是多處理器環(huán)境中仍然是不安全的,因為這兩個指令都是由幾條微代碼實現(xiàn)的。最終解決辦法 / +lActiveRequests; lock inc lActiveRequests / -lActiveRequests; lock dec lActiveRequests LOCK指令前綴可以使當前執(zhí)行多微碼指令的CPU鎖定總線,從而保證數(shù)據(jù)訪問的完整性。兩個最差的假定驅(qū)動程序開發(fā)者必須做如下兩個最差的假定:操作系統(tǒng)可以在任何時間搶先任何例程并停留任何長的時間,所以我們不能保證自己的任務(wù)不被干擾或延遲。即使我們能防止被搶先,但其它CPU上執(zhí)行的代碼也會干擾我們代碼的執(zhí)行,甚至一個程序的代碼可以在
4、兩個不同線程的上下文中并發(fā)執(zhí)行。 同步請求級一個確定的CPU上的活動僅能被擁有更高IRQL的活動搶先。IRQL與線程優(yōu)先級線程優(yōu)先級是與IRQL非常不同的概念。線程優(yōu)先級控制著OS線程調(diào)度器的調(diào)度動作,決定何時搶先運行線程以及下一次運行什么線程。當IRQL級高于或等于DISPATCH_LEVEL級時線程切換停止,無論當前活動的是什么線程都將保持活動狀態(tài)直到IRQL降到DISPATCH_LEVEL級之下。在進行線程調(diào)度時會切換線程上下文;按照IRQL進行活動搶先時不會切換線程上下文。利用IRQL進行同步方法:將所有對共享數(shù)據(jù)的訪問都應(yīng)該在同一(提升的,高于PASSIVE_LEVEL級的) IRQ
5、L上進行。上述方法只適用于單CPU??衫肒eRaiseIrql和KeLowerIrql函數(shù)改變當前IRQL。 KIRQL oldirql;ASSERT(KeGetCurrentIrql() QLock); .如何使用自旋鎖當代碼運行在低于或等于DISPATCH_LEVEL級時獲取這個鎖,并執(zhí)行需要保護的代碼,最后釋放自旋鎖。NTSTATUS DispatchSomething(.) KIRQL oldirql; PDEVICE_EXTENSION pdx = .; KeAcquireSpinLock(&pdx-QLock, &oldirql); . KeReleaseSpin
6、Lock(&pdx-QLock, oldirql);如何使用自旋鎖如果知道代碼已經(jīng)處在DISPATCH_LEVEL級上 ,如DPC、StartIo,和其它執(zhí)行在DISPATCH_LEVEL級上的驅(qū)動程序例程,可以調(diào)用兩個專用函數(shù)來操作自旋鎖 :KeAcquireSpinLockAtDpcLevel(&pdx-QLock);.KeReleaseSpinLockFromDpcLevel(&pdx-QLock);內(nèi)核同步對象利用內(nèi)核同步對象可以暫時阻塞一個線程的執(zhí)行,同步不同線程的執(zhí)行動作。內(nèi)核同步對象僅影響OS線程調(diào)度器的調(diào)度動作,因此一般只在低于DISPATCH_LEVE
7、L級的代碼中用于阻塞線程。在驅(qū)動程序中,只能在“非任意線程上下文非任意線程上下文”條件下利用內(nèi)核同步對象阻塞調(diào)用者的線程或產(chǎn)生該請求的線程。在“任意線程上下文任意線程上下文”調(diào)用等待原語等待原語只會阻塞一個“無辜”的線程。非任意線程上下文如果驅(qū)動程序的回調(diào)例程能確切知道處于哪個線程上下文中,則稱處于“非任意線程上下文”;大部分時間里,驅(qū)動程序無法知道這個事實,即處于“任意線程上下文”中。非任意線程上下文的例子: 設(shè)備的最高級驅(qū)動程序的IRP處理函數(shù)可以確切地知道它執(zhí)行在發(fā)出該I/O請求的應(yīng)用程序線程的上下文中。PNP類IRP的處理函數(shù)可以確切地知道它執(zhí)行在一個系統(tǒng)線程(System Threa
8、d)中。在你自己創(chuàng)建的內(nèi)核模式系統(tǒng)線程中。(PsCreateSystemThread)DriverEntry、AddDevice、DriverUnload等函數(shù)執(zhí)行在一個系統(tǒng)線程(System Thread)中。常用的內(nèi)核同步對象對象對象數(shù)據(jù)類型數(shù)據(jù)類型描述描述Event(事件) KEVENT阻塞一個線程直到檢測到某事件發(fā)生 Semaphore(信號燈)KSEMAPHORE 控制多個線程對共享資源的訪問Mutex(互斥)KMUTEX 執(zhí)行到關(guān)鍵代碼段時,禁止其它線程執(zhí)行該代碼段 Timer(定時器)KTIMER推遲線程執(zhí)行一段時期Thread(線程) KTHREAD阻塞一個線程直到另一個線程結(jié)
9、束在單同步對象上等待在任何時刻,任何對象都處于兩種狀態(tài)中的一種:信號態(tài)信號態(tài)(signaled)或非信號態(tài)非信號態(tài)(not signaled) 。調(diào)用KeWaitForSingleObject或KeWaitForMultipleObjects函數(shù)可以使代碼(以及背景線程)在一個或多個同步對象上等待,等待它們進入信號態(tài)。ASSERT(KeGetCurrentIrql() = DISPATCH_LEVEL);LARGE_INTEGER timeout;NTSTATUS status = KeWaitForSingleObject(object, WaitReason, WaitMode, Aler
10、table, &timeout);KeWaitForSingleObject參數(shù)含義object 指向要等待的對象,它應(yīng)該指向一個上面表中列出的同步對象。該對象必須在非分頁內(nèi)存中。WaitReason 是一個純粹建議性的值,KWAIT_REASON枚舉型,一般取值為Executive。WaitMode 是MODE枚舉類型,該枚舉類型僅有兩個值:KernelMode和UserMode。一般取值為KernelMode 。Alertable 參數(shù)一般指定為FALSE。timeout 是一個64位超時值的地址,單位為100納秒。正數(shù)的超時表示一個從1601年年1月月1日日起的絕對時間。負數(shù)代表
11、相對于當前時間的時間間隔。 指定為0將使等待函數(shù)立即返回。指定為NULL代表無限期等待。KeWaitForSingleObject(object, WaitReason, WaitMode, Alertable, &timeout);KeWaitForSingleObject返回值含義STATUS_SUCCESS,表示等待被滿足。即你調(diào)用KeWaitForSingleObject時,對象或者已經(jīng)進入信號態(tài),或者在等待中進入信號態(tài)使等待返回。STATUS_TIMEOUT指出在指定的超時期限內(nèi)對象未進入信號態(tài) 。如果指定0超時,則函數(shù)將立即返回。返回代碼為STATUS_TIMEOUT,代表
12、對象處于非信號態(tài),返回代碼為STATUS_ SUCCESS,代表對象處于信號態(tài)。其它兩個返回值STATUS_ALERTED和STATUS_USER_APC表示等待提前終止,對象未進入信號態(tài) 。在多個同步對象上等待objects指向一個指針數(shù)組,每個數(shù)組元素指向一個同步對象,count表示數(shù)組中指針的個數(shù) 。WaitType是枚舉類型,其值可以為WaitAll或WaitAny,它指出你是等到所有對象都進入信號態(tài),還是只要有一個對象進入信號態(tài)就可以。waitblocks參數(shù)指向一個KWAIT_BLOCK結(jié)構(gòu)數(shù)組,內(nèi)核用它來記錄每個對象在等待中的狀態(tài)。 不需要你對其進行初始化。ASSERT(KeGe
13、tCurrentIrql() = DISPATCH_LEVEL);LARGE_INTEGER timeout;NTSTATUS status = KeWaitForMultipleObjects(count, objects, WaitType, WaitReason, WaitMode, Alertable, &timeout, waitblocks);KeWaitForMultipleObjects的返回值如果指定了WaitAll,則返回STATUS_SUCCESS表示等待的所有對象都進入了信號態(tài)。如果指定了WaitAny,則返回值在數(shù)值上等于進入信號態(tài)的對象在objects數(shù)組中
14、的索引。如果碰巧有多個對象進入了信號態(tài),則返回值僅代表其中的一個,可能是第一個也可能是其它??梢哉J為返回值等于STATUS_WAIT_0加上數(shù)組索引。NTSTATUS status = KeWaitForMultipleObjects(.);if (NT_SUCCESS(status) iSignalled = status - STATUS_WAIT_0; .內(nèi)核事件(Event)對象用途:把一個特定的事件通知給一個等待中的線程。與該對象相關(guān)的內(nèi)核服務(wù)函數(shù)如下:服務(wù)函數(shù)服務(wù)函數(shù)功能功能KeInitializeEvent初始化事件對象KeSetEvent把事件設(shè)置為信號態(tài),返回前一個狀態(tài)KeR
15、esetEvent把事件設(shè)置為非信號態(tài),返回前一個狀態(tài)KeClearEvent把事件設(shè)置為非信號態(tài),不報告以前的狀態(tài)。KeReadStateEvent取事件的當前狀態(tài)。通知事件與同步事件通知事件通知事件(notification event)有這樣的特性,當它進入信號態(tài)后,它將一直處于信號態(tài)直到明確地把它重置為非信號態(tài)。因此,當通知事件進入信號態(tài)后,所有在該事件上等待的線程都被釋放。同步事件同步事件(synchronization event):只要有一個線程被釋放,該事件就被自動重置為非信號態(tài)。 ASSERT(KeGetCurrentIrql() = DISPATCH_LEVEL);KEVE
16、NT event;KeInitializeEvent(event, EventType, initialstate);EventType是一個枚舉值,可以為NotificationEvent或SynchronizationEvent。initialstate是布爾量,為TRUE表示事件的初始狀態(tài)為信號態(tài),為FALSE表示事件的初始狀態(tài)為非信號態(tài)。KeSetEvent函數(shù)調(diào)用KeSetEvent函數(shù)可以把事件置為信號態(tài):ASSERT(KeGetCurrentIrql() lock, SynchronizationEvent, TRUE);void thread () KeWaitForSingl
17、eObject(&pdx-lock, Executive, KernelMode, FALSE, NULL); / do something KeSetEvent(&pdx-lock, EVENT_INCREMENT, FALSE);在應(yīng)用層異步訪問設(shè)備/ CreateFile的一個參數(shù)可以規(guī)定同步方式還是異步方式訪問該設(shè)備的一個參數(shù)可以規(guī)定同步方式還是異步方式訪問該設(shè)備hDevice = CreateFile(“.wdm1Device”, .);HANDLE waitEvent = CreateEvent(.);OVERLAPPED ol;ol.hEvent = waitEv
18、ent;ReadFile( hDevice, buffer, NumberOfBytesToRead, &ol);while(WaitForSingleObject(waitEvent, 100)=WAIT_TIMEOUT) if(!KeepRunning) CancelIo(hDevice); goto EXIT; / 從從buffer中訪問數(shù)據(jù)中訪問數(shù)據(jù)內(nèi)核信號燈內(nèi)核信號燈是一個有同步語義的整數(shù)計數(shù)器。信號燈計數(shù)器為正值時代表信號態(tài),為0時代表非信號態(tài)。計數(shù)器不能為負值。釋放信號燈將使信號燈計數(shù)器增1,在一個信號燈上等待將使該信號燈計數(shù)器減1。如果計數(shù)器值被減為0,則信號燈進入非信
19、號態(tài),之后其它調(diào)用KeWaitXxx函數(shù)的線程將被阻塞。注意如果等待線程的個數(shù)超過了計數(shù)器的值,那么并不是所有等待的線程都可以恢復(fù)運行。服務(wù)函數(shù)與使用方法KeInitializeSemaphore:初始化信號燈對象KeReadStateSemaphore:取信號燈當前狀態(tài)KeReleaseSemaphore:釋放信號燈對象KSEMAPHORE semaphore;ASSERT(KeGetCurrentIrql() = PASSIVE_LEVEL);KeInitializeSemaphore(&semaphore, count, limit);.KeWaitForSingleObject
20、(&semaphore, .);.ASSERT(KeGetCurrentIrql() = DISPATCH_LEVEL);KeReleaseSemaphore(semaphore, boost, delta, wait);互斥對象Mutex 互斥(mutex)就是mutual exclusion的簡寫。內(nèi)核互斥對象為多個競爭線程串行化訪問共享資源提供了一種方法。雖然用其它方法也能實現(xiàn)此功能,但互斥對象加入了一些措施能防止死鎖死鎖。如果互斥對象不被某線程所擁有,則它是信號態(tài),反之則是非信號態(tài)。如果需要長時間串行化訪問一個對象,應(yīng)該首先考慮使用互斥(而不是依賴提升的IRQL和自旋鎖)。利用
21、互斥對象控制資源的訪問,可以使其它線程分布到多處理器平臺上的其它CPU中運行,還允許導致頁故障的代碼仍能鎖定資源而不被其它線程訪問。 互斥對象的服務(wù)函數(shù)KeInitializeMutex 初始化互斥對象KeReadStateMutex 取互斥對象的當前狀態(tài)KeReleaseMutex 設(shè)置互斥對象為信號態(tài)KMUTEX mutex;ASSERT(KeGetCurrentIrql() = PASSIVE_LEVEL);KeInitializeMutex(&mutex, level);.KeWaitForSingleObject(&mutex, .);.ASSERT(KeGetCur
22、rentIrql() = PASSIVE_LEVEL);KeReleaseMutex(&mutex, wait);內(nèi)核定時器 (Timer) Timer對象可以在指定的絕對時間或間隔時間后自動從非信號態(tài)變?yōu)樾盘枒B(tài)。它還可以周期性的進入信號態(tài)。可以利用KeWaitXxxx函數(shù)等待一個Timer對象在某個時間間隔后進入信號態(tài),也可以利用Timer對象安排一個在某個時間間隔后或定期執(zhí)行的DPC回調(diào)函數(shù)。定時器也分為通知型通知型和同步型同步型兩種。通知型定時器及時結(jié)束后一直處于信號態(tài),除非手動改變。因此,所有等待它的線程都被釋放。同步定時器正相反,它只允許有一個等待線程。一旦有線程在這種定時器
23、上等待,并且開始執(zhí)行,定時器就自動進入非信號態(tài)。內(nèi)核定時器的服務(wù)函數(shù)服務(wù)函數(shù)服務(wù)函數(shù)功能功能KeInitializeTimer初始化一次性的通知型定時器KeInitializeTimerEx 初始化一次性的或周期性的通知型的或同步型定時器 KeSetTimer為通知型定時器設(shè)定時間或DPC對象KeSetTimerEx為定時器設(shè)定時間、周期和其它屬性KeCancelTimer取消一個定時器KeReadStateTimer 獲取定時器的當前狀態(tài)。一次性定時器的用法KTIMER timer; / someone gives you thisASSERT(KeGetCurrentIrql() = DI
24、SPATCH_LEVEL);KeInitializeTimerEx(&timer, NotificationTimer);/ KeInitializeTimer(timer);LARGE_INTEGER duetime;KeSetTimer(&timer, duetime, NULL);KeWaitForSingleObject(&timer, .);.周期性定時器的用法KTIMER timer; / someone gives you thisASSERT(KeGetCurrentIrql() = DISPATCH_LEVEL);KeInitializeTimerEx
25、(&timer, SynchronizationTimer);LARGE_INTEGER duetime;long period;KeSetTimerEx(&timer, duetime, period, NULL);while(True) KeWaitForSingleObject(&timer, .);.KeCancelTimer(&timer);定時器與DPCPKDPC dpc; / points to KDPC youve allocatedASSERT(KeGetCurrentIrql() = PASSIVE_LEVEL);KeInitializeTimer(timer);KeInitializeDpc(dpc, DpcRoutine, context);ASSERT(KeGetCurrentIrql() = DISPATCH_LEVEL);LARGE_INTEGER duetime;KeSetTimer(timer, duetime, dpc);. . . .VOID DpcRoutine(PKDPC dpc, PVOID context, .) .定時函數(shù) KeDelayExecutionThread :可以在PA
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責。
- 6. 下載文件中如有侵權(quán)或不適當內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 山西工商學院《學前教育學(媒)》2023-2024學年第二學期期末試卷
- 海南軟件職業(yè)技術(shù)學院《科技論文寫作》2023-2024學年第二學期期末試卷
- 南京林業(yè)大學《面向?qū)ο蟪绦蛟O(shè)計及C++》2023-2024學年第二學期期末試卷
- 江西冶金職業(yè)技術(shù)學院《國際市場營銷B(雙語)》2023-2024學年第二學期期末試卷
- 通化師范學院《機械工程檢測技術(shù)》2023-2024學年第二學期期末試卷
- 親子主題餐廳裝修合同
- 二零二五年度蘇州工業(yè)園區(qū)勞動合同管理與薪酬福利設(shè)計
- 2025年度互聯(lián)網(wǎng)企業(yè)員工勞動集體合同(創(chuàng)新發(fā)展)
- 《核裂變與核聚變》課件
- 《句式變換好》課件
- 四川省自貢市2024-2025學年上學期八年級英語期末試題(含答案無聽力音頻及原文)
- 2025-2030年中國汽車防滑鏈行業(yè)競爭格局展望及投資策略分析報告新版
- 2025年上海用人單位勞動合同(4篇)
- 二年級上冊口算題3000道-打印版讓孩子口算無憂
- 高中英語北師大版必修第一冊全冊單詞表(按單元編排)
- 新教科版科學小學四年級下冊全冊教案
- 2024中考語文試卷及答案長沙
- 2024年高考生物總復(fù)習高中生物必修一全冊重點知識梳理筆記(全冊完整版)
- 2025年生物安全年度工作計劃
- 人教版數(shù)學六年級下冊全冊核心素養(yǎng)目標教學設(shè)計
- 通用電子嘉賓禮薄
評論
0/150
提交評論