我正在爲Windows 7 32位編寫設備驅動程序。我正在使用WDK版本7600.16385.1。到目前爲止,事情進展順利,但prefast總是告訴我,我搞亂了IRQL級別。特別是當我嘗試鎖定/解鎖共享緩衝區時。Prefast註釋修復IRQL級別警告
我有一個代表,像這樣的緩衝結構:
typedef struct _PORT_BUFFER {
WDFMEMORY mMemory;
PUCHAR pucBuff;
ULONG ulSizeMax;
ULONG ulSizeCurr;
ULONG ulAdd;
ULONG ulRemove;
ULONG ulLost;
WDFREQUEST rPending;
BOOLEAN bDMAing;
WDFSPINLOCK slLock;
} PORT_BUFFER, *PPORT_BUFFER;
我有兩個功能,可以鎖定和解鎖說緩衝區:
VOID PLxBufferLock(PPORT_BUFFER ppbBuff){
WdfSpinLockAcquire(ppbBuff->slLock);
}
VOID PLxBufferUnlock(PPORT_BUFFER ppbBuff){
WdfSpinLockRelease(ppbBuff->slLock);
}
當我編譯我的司機,PREfast的告訴我:
warning 28167 : The function 'PLxBufferLock' changes the IRQL and does not restore the IRQL before it exits. It should be annotated to reflect the change or the IRQL should be restored. IRQL was last set to 2 at line 57.
warning 28167 : The function 'PLxBufferUnlock' changes the IRQL and does not restore the IRQL before it exits. It should be annotated to reflect the change or the IRQL should be restored. IRQL was last set at line 63.
所以,我看着WdfSpinLockAcquire和WdfSpinLockRelease如何AR e定義:
__drv_raisesIRQL(DISPATCH_LEVEL)
__drv_maxIRQL(DISPATCH_LEVEL)
VOID
FORCEINLINE
WdfSpinLockAcquire(
__in
__drv_savesIRQL
__drv_neverHold(SpinLockObj)
__drv_acquiresResource(SpinLockObj)
WDFSPINLOCK SpinLock
)
{
((PFN_WDFSPINLOCKACQUIRE) WdfFunctions[WdfSpinLockAcquireTableIndex])(WdfDriverGlobals, SpinLock);
}
__drv_maxIRQL(DISPATCH_LEVEL)
__drv_minIRQL(DISPATCH_LEVEL)
VOID
FORCEINLINE
WdfSpinLockRelease(
__in
__drv_restoresIRQL
__drv_mustHold(SpinLockObj)
__drv_releasesResource(SpinLockObj)
WDFSPINLOCK SpinLock
)
{
((PFN_WDFSPINLOCKRELEASE) WdfFunctions[WdfSpinLockReleaseTableIndex])(WdfDriverGlobals, SpinLock);
}
看起來很直截了當。所以我改變了我的功能看起來是一樣的:
__drv_raisesIRQL(DISPATCH_LEVEL)
__drv_maxIRQL(DISPATCH_LEVEL)
VOID PLxBufferLock(
__in
__drv_savesIRQL
__drv_neverHold(ppbBuff)
__drv_acquiresResource(ppbBuff)
PPORT_BUFFER ppbBuff);
__drv_maxIRQL(DISPATCH_LEVEL)
__drv_minIRQL(DISPATCH_LEVEL)
VOID PLxBufferUnlock(
__in
__drv_restoresIRQL
__drv_mustHold(ppbBuff)
__drv_releasesResource(ppbBuff)
PPORT_BUFFER ppbBuff);
然後,我從兩個警告,很多很多的警告去泄漏ppbBuff,但仍不能正確還原IRQL級別:
warning 28103 : Leaking the ppbBuff stored in 'ppbBuff'.
warning 28104 : The ppbBuff that should have been acquired before function exit was not acquired.
warning 28107 : The ppbBuff '&pdepPort->pbRead' must be held when calling 'PLxBufferUnlock'.
warning 28107 : The ppbBuff '&pdepPort->pbWrite' must be held when calling 'PLxBufferUnlock'.
warning 28107 : The ppbBuff '&pdepExtPort->pbRead' must be held when calling 'PLxBufferUnlock'.
warning 28107 : The ppbBuff '&pdepExtPort->pbRead' must be held when calling 'PLxBufferUnlock'.
warning 28107 : The ppbBuff '&pdepExtPort->pbWrite' must be held when calling 'PLxBufferUnlock'.
warning 28157 : The IRQL in 'ppbBuff' was never restored.
warning 28158 : No IRQL was saved into 'ppbBuff'.
warning 28166 : The function 'PLxInitEvtPortCleanup' does not restore the IRQL to the value that was current at function entry and is required to do so. IRQL was last set at line 320.
warning 28166 : The function 'PLxReadEvt' does not restore the IRQL to the value that was current at function entry and is required to do so. IRQL was last set at line 51.
warning 28166 : The function 'PLxReadEvtTimer' does not restore the IRQL to the value that was current at function entry and is required to do so. IRQL was last set at line 104.
warning 28166 : The function 'PLxWriteEvt' does not restore the IRQL to the value that was current at function entry and is required to do so. IRQL was last set at line 60.
我用的緩衝區而且我沒有在任何地方檢查錯誤,所以我認爲我正確鎖定了。在這種情況下,任何人都知道如何安撫prefast?謝謝!
編輯:
在此處,我使用了鎖定功能的示例:
VOID PLxInitEvtPortCleanup(WDFFILEOBJECT foFileObject){
PDEVICE_EXTENSION_PORT pdepPort = NULL;
PDEVICE_EXTENSION_CARD pdecCard = NULL;
GSCSIO4BXSYNC_PORT_CONFIGURATION pcPortConfig = { 0 };
WDFREQUEST rRequest = NULL;
pdepPort = PLxGetDeviceContextPort(WdfFileObjectGetDevice(foFileObject));
pdecCard = PLxGetDeviceContextCard(pdepPort->dDeviceCard);
pcPortConfig.bEnable = FALSE;
pcPortConfig.bRxEnable = FALSE;
pcPortConfig.bTxEnable = FALSE;
pcPortConfig.ulClockFrequency = 0;
pcPortConfig.eptcdTxClockDirection = GSCSIO4BXSYNC_ESTCD_INPUT;
PLxSioConfigPortSet(pdecCard,pdepPort->ulPortNumber,&pcPortConfig);
PLxBufferLock(&pdepPort->pbRead);
rRequest = PLxBufferClearPendingRequest(&pdepPort->pbRead);
PLxBufferUnlock(&pdepPort->pbRead);
if (rRequest) WdfRequestComplete(rRequest,STATUS_CANCELLED);
PLxBufferLock(&pdepPort->pbWrite);
rRequest = PLxBufferClearPendingRequest(&pdepPort->pbWrite);
PLxBufferUnlock(&pdepPort->pbWrite);
if (rRequest) WdfRequestComplete(rRequest,STATUS_CANCELLED);
}
我鎖定緩衝液,除去任何掛起的請求,解鎖緩衝器和完成該請求。 Prefast告訴我,我沒有正確恢復IRQL級別。當我註釋掉鎖定/清除/解鎖/完整代碼時,prefast很快樂。
編輯:
我升級到VS2015和WDK10 + SDK10。我已經添加了由M'hand BOUGHIAS建議註釋:
_Acquires_lock_(ppbBuff->slLock)
_Requires_lock_not_held_(ppbBuff->slLock)
_IRQL_saves_
VOID PLxBufferLock(PPORT_BUFFER ppbBuff){
WdfSpinLockAcquire(ppbBuff->slLock);
}
_Releases_lock_(ppbBuff->slLock)
_Requires_lock_held_(ppbBuff->slLock)
_IRQL_restores_
VOID PLxBufferUnlock(PPORT_BUFFER ppbBuff){
WdfSpinLockRelease(ppbBuff->slLock);
}
現在我得到以下幾點:
warning C28158: No IRQL was saved into 'return'.
warning C28167: The function 'PLxBufferLock' changes the IRQL and does not restore the IRQL before it exits. It should be annotated to reflect the change or the IRQL should be restored.
warning C28157: The IRQL in 'return' was never restored.
我注意到,其中定義爲任何的_Acquires_lock_和_Requires_lock_not_held_所以我看着他們並注意到他們需要_PREFAST_被定義爲工作。所以我將_PREFAST_添加到我的預處理器定義中。現在我得到了一堆鏈接錯誤,但沒有更多的prefast錯誤!
error LNK2005: __Lock_kind_mutex_ already defined in Buffer.obj
error LNK2005: __Lock_kind_event_ already defined in Buffer.obj
error LNK2005: __Lock_kind_semaphore_ already defined in Buffer.obj
error LNK2005: __Lock_kind_spin_lock_ already defined in Buffer.obj
error LNK2005: __Lock_kind_critical_section_ already defined in Buffer.obj
error LNK2001: unresolved external symbol __Prefast_unreferenced_parameter_impl_
我想我在把我的項目轉換到VS2015時搞砸了一些東西。所以我創建了標準的KMDF驅動程序項目,爲您提供了一個很好的框架。我在新項目中打開了靜態分析並像以前一樣定義了_PREFAST_,它也給我提供了相同的鏈接錯誤。
這可能是因爲您正在獲取鎖而不在該函數中釋放它。你是否嘗試過在同一個函數中獲取和釋放,看看它是否能解決問題? – Serdalis
@Serdalis如果我在同一個函數中獲取/釋放Wdf函數的鎖定,我相信prefast就可以。在助手功能中獲取鎖正在導致問題。但我想抽象出緩衝區的鎖定概念。我希望緩衝區的用戶能夠鎖定緩衝區,檢查其大小,添加一些數據,然後解鎖緩衝區。我不希望緩衝區的用戶知道鎖的工作方式。 –
您的註釋適用於ppbBuf。你應該將它們應用於鎖定的元素。 –