2016-05-17 9 views
5

मैं विंडोज 7 32 बिट के लिए डिवाइस ड्राइवर लिख रहा हूं। मैं डब्लूडीके संस्करण 7600.16385.1 का उपयोग कर रहा हूं। अब तक चीजें अच्छी तरह से चल रही हैं, लेकिन प्रीफास्ट मुझे बताता रहता है कि मैं आईआरक्यूएल स्तर को गड़बड़ कर रहा हूं। विशेष रूप से जब मैं साझा बफर को लॉक/अनलॉक करने का प्रयास करता हूं।आईआरक्यूएल स्तर चेतावनियों को ठीक करने के लिए प्रीफास्ट एनोटेशन

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 को देखा ई परिभाषित:

__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); 

} 

मैं बफर ताला, कोई भी लंबित अनुरोध निकल बफर अनलॉक और अनुरोध को पूरा:

एक उदाहरण है जहाँ मैं ताला कार्यों का उपयोग है। प्रीफास्ट मुझे बताता है कि मैं सही ढंग से आईआरक्यूएल स्तर को बहाल नहीं कर रहा हूं। जब मैं लॉक/साफ़/अनलॉक/पूर्ण कोड पर टिप्पणी करता हूं, तो प्रीफ़ास्ट फिर से खुश होता है।

संपादित करें:

मैं 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_ जोड़ा। अब मुझे त्रुटियों को जोड़ने का एक गुच्छा मिलता है लेकिन कोई और प्रीफास्ट त्रुटियां नहीं!

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 करने के लिए अपने प्रोजेक्ट को परिवर्तित करते हुए। इसलिए मैंने मानक केएमडीएफ ड्राइवर प्रोजेक्ट बनाया है जिसके साथ आपको निर्माण करने के लिए एक अच्छा ढांचा मिल गया है। मैंने नई परियोजना में स्थैतिक विश्लेषण चालू कर दिया और पहले से ही _PREFAST_ परिभाषित किया और यह मुझे वही लिंकिंग त्रुटियां भी देता है।

+0

ऐसा इसलिए हो सकता है क्योंकि आप उस फ़ंक्शन में इसे जारी किए बिना लॉक प्राप्त कर रहे हैं। क्या आपने यह देखने के लिए एक ही फ़ंक्शन में अधिग्रहण और रिलीज़ करने का प्रयास किया है कि क्या इससे समस्या से छुटकारा पड़े? – Serdalis

+0

@ सेरडलिस यदि मैं वही फ़ंक्शन के भीतर WDF फ़ंक्शंस के साथ लॉक प्राप्त/रिलीज़ करना चाहता हूं, तो मुझे यकीन है कि प्रीफ़ास्ट ठीक होगा। एक सहायक समारोह में ताला प्राप्त करना समस्या पैदा कर रहा है। लेकिन मैं बफर की लॉकिंग धारणा को अमूर्त करना चाहता हूं। मैं बफर के उपयोगकर्ता को बफर को लॉक करने, इसके आकार की जांच करने, कुछ डेटा जोड़ने और फिर बफर को अनलॉक करने में सक्षम होना चाहता हूं। मैं नहीं चाहता कि बफर के उपयोगकर्ता को पता चले कि लॉक कैसे काम करता है। –

+0

आपकी टिप्पणियां ppbBuf पर लागू होती हैं। आपको उन्हें लॉक किए गए मेम्ब्रे पर लागू करना चाहिए। –

उत्तर

4

आप अच्छे रास्ते पर हैं। दरअसल, आप PREfast है कि अपने कार्यों ताला बता सकते हैं या साल एनोटेशन वस्तुओं धन्यवाद अनलॉक कर सकते हैं: Annotating Locking Behavior

तुम भी IRQL परिवर्तन के बारे में PREfast बताने की आवश्यकता: IRQL annotations for drivers

यहाँ का उपयोग करता है एक नमूना कोड है

_IRQL_raises_(DISPATCH_LEVEL) 
_Acquires_lock_(ppbBuff->slLock) 
_Requires_lock_not_held_(ppbBuff->slLock) 
VOID PLxBufferLock(_In_ _IRQL_saves_ PPORT_BUFFER ppbBuff){ 
     WdfSpinLockAcquire(ppbBuff->slLock);  
} 

_Releases_lock_(ppbBuff->slLock) 
_Requires_lock_held_(ppbBuff->slLock) 
VOID PLxBufferUnlock(_In_ _IRQL_restores_ PPORT_BUFFER ppbBuff){ 
    WdfSpinLockRelease(ppbBuff->slLock); 
} 

टिप्पणी: आपपर एनोटेशन का उपयोग करना चाहिए साल अपने कोड के आधार पर एनोटेशन, वे पुराने WDK7 से अलग हो सकतापरिवर्तनीय, अपने मालिक पर नहीं।

अद्यतन: ऊपर प्रलेखन मैं एनोटेशन के उपयोग को अद्यतन है पढ़ने के बाद, _IRQL_saves_/_IRQL_restores_ समारोह पर नहीं एक समारोह पैरामीटर पर इस्तेमाल किया जाना चाहिए। आपको _IRQL_raises_ का उपयोग करने की आवश्यकता हो सकती है। मैंने उपरोक्त कोड नमूना संपादित किया है। लिंक समस्या से बचने के लिए आप अपनी _PREFAST_ परिभाषा को भी हटा सकते हैं। _PREFAST_ संकलक द्वारा परिभाषित किया जाता है जब यह विश्लेषण शुरू करता है।

अद्यतन 2: इसके बजाय _In_ पैरामीटर पर _IRQL_saves_/_IRQL_restores एनोटेशन का उपयोग कर के आप भी समारोह पर _IRQL_saves_global_(kind, param)/_IRQL_restores_global_(kind, param) एनोटेशन का उपयोग कर सकते हैं। यहां एक अद्यतन कोड नमूना है:

_IRQL_raises_(DISPATCH_LEVEL) 
_Acquires_lock_(ppbBuff->slLock) 
_Requires_lock_not_held_(ppbBuff->slLock) 
_IRQL_saves_global_(SpinLock, ppbBuff) 
VOID PLxBufferLock(_In_ PPORT_BUFFER ppbBuff){ 
     WdfSpinLockAcquire(ppbBuff->slLock);  
} 

_Releases_lock_(ppbBuff->slLock) 
_Requires_lock_held_(ppbBuff->slLock) 
_IRQL_restores_global_(SpinLock, ppbBuff) 
VOID PLxBufferUnlock(_In_ PPORT_BUFFER ppbBuff){ 
    WdfSpinLockRelease(ppbBuff->slLock); 
} 
+0

जानकारी के लिए धन्यवाद, मैंने कोशिश की है और ऐसा लगता है लेकिन यह मुझे एक अलग समस्या का कारण बनता है। मैंने अधिक जानकारी के साथ प्रश्न संपादित किया है। –

संबंधित मुद्दे