Αυτό το άρθρο περιγράφει τον τρόπο χρήσης μια απλής περιόδου
λειτουργίας εντοπισμού σφαλμάτων, για τον προσδιορισμό του συγκεκριμένου
προγράμματος οδήγησης που εμφανίζει το ακόλουθο μήνυμα λάθους:
Σφάλμα διακοπής IRQL_NOT_LESS_OR_EQUAL
(0xA)
(Stop Error IRQL_NOT_LESS_OR_EQUAL
(0xA))
Αφού εγκαταστήσετε ένα πρόγραμμα οδήγησης, το σύστημα
σταματά να ανταποκρίνεται και εμφανίζεται το ακόλουθο μήνυμα λάθους στο
nt!KiActivateWaiterQueue+0x27:
Σφάλμα διακοπής IRQL_NOT_LESS_OR_EQUAL
(0xA)
(Stop Error IRQL_NOT_LESS_OR_EQUAL (0xA))
Το αρχικό
ίχνος στοιβάδας υποδηλώνει ότι το θέμα βρίσκεται στο πρόγραμμα οδήγησης Fast
Fat.
Αυτό το θέμα παρουσιάζεται, επειδή τα προγράμματα οδήγησης
καλούν δύο φορές τη συνάρτηση
IoQueueWorkItem ή τη συνάρτηση
ExQueueWorkItem στο ίδιο στοιχείο εργασίας, πριν να εκτελεστεί το στοιχείο
εργασίας.
Τα προγράμματα οδήγησης συσκευής που κατανέμουν στατικά τη
δομή
IO_WORKITEM ή τη δομή
WORK_QUEUE_ITEM επηρεάζονται ιδιαίτερα από αυτό το θέμα. Τα προγράμματα οδήγησης
συσκευής που διεξάγουν μια τέτοια στατική κατανομή, θα πρέπει να εγγυώνται ότι
δεν πρόκειται να χρησιμοποιήσουν το στατικά κατανεμημένο στοιχείο, ενώ αυτό
βρίσκεται ήδη σε ουρά.
Για να εντοπίσετε το σφάλμα ενός συστήματος που σταμάτησε να
ανταποκρίνεται, εμφανίζονται το σφάλμα που αναφέρεται στην ενότητα
"Συμπτώματα", ακολουθήστε τα εξής βήματα:
- Ας θεωρήσουμε ότι εγκαταστήσατε ένα πρόγραμμα οδήγησης που
ονομάζεται, για παράδειγμα, Xyz.sys, το σύστημα σταματά να ανταποκρίνεται και
εμφανίζεται το σφάλμα διακοπής stop error 0xA που αναφέρεται
παραπάνω.
- Ξεκινήστε το πρόγραμμα εντοπισμού σφαλμάτων με τα σωστά
σύμβολα, και ακολουθήστε το παράδειγμα εντοπισμού σφάλματος που περιγράφεται
αργότερα σε αυτό το άρθρο.
Σε αυτό το παράδειγμα χρησιμοποιείται
πρόγραμμα εντοπισμού σφαλμάτων πυρήνα. Μπορείτε να χρησιμοποιήσετε είτε το
εργαλείο KD είτε το WinDbg. Μπορείτε επίσης να χρησιμοποιήσετε αυτήν τη μέθοδο,
ενεργοποιώντας το πρόγραμμα επαλήθευσης του προγράμματος οδήγησης. - Η εντολή kv του προγράμματος εντοπισμού σφαλμάτων δείχνει τη στοίβα (stack).
Το ακόλουθο ίχνος στοίβας υποδηλώνει ότι έχει καταστραφεί το WORKER_QUEUE.
Stack Trace:
f8979768 804f076c fc502008 ff651fb8 e16de008 nt!KiActivateWaiterQueue+0x27
f8979790 f8462061 00000000 00000000 00000000 nt!KeWaitForSingleObject+0x198
f89797ac f8462289 ff651fb8 00000600 ff651fb8 Fastfat!FatWaitSync+0x18
f897989c f8461e62 ff651fb8 fc502008 e16de008 Fastfat!FatNonCachedIo+0x36b
f8979a2c f845b6b0 ff651fb8 fc502008 fc502008 Fastfat!FatCommonWrite+0xf29
f8979a70 804eca36 82378020 fc502008 823d1698 Fastfat!FatFsdWrite+0xaa
f8979a80 f847f3b8 804f46ad f377404c f8979ab8 nt!IopfCallDriver+0x31
f8979a90 804eca36 82379a08 e27dac88 f8979aec sr!SrWrite+0xa8
f8979ad8 804f46ad f376a0a6 823cafb8 82035ca8 nt!IopfCallDriver+0x31
f8979adc f376a0a6 823cafb8 82035ca8 80570400 nt!IoSetThreadHardErrorMode
- Αν δείτε τη στοίβα στο βήμα 3, ίσως να πιστέψετε ότι το
ελαττωματικό πρόγραμμα οδήγησης είναι το Fast Fat. Ωστόσο, η δομή KQUEUE δείχνει μια καταστραμμένη καταχώρηση LIST_ENTRY:
kd> dv
Queue = ffffffff8054eddc
kd> dt -r1 _KQUEUE 8054eddc
+0x000 Header :
+0x000 Type : 0x4 ''
+0x001 Absolute : 0 ''
+0x002 Size : 0xa ''
+0x003 Inserted : 0 ''
+0x004 SignalState : 1
+0x008 WaitListHead : _LIST_ENTRY [ 0x823cb438 - 0x823ca6b0 ]
+0x010 EntryListHead : [ 0x0 - 0x820ae3c8 ]
+0x000 Flink : (null)
+0x004 Blink : 0x820ae3c8 [ 0x0 - 0x8054edec ]
- Καταργώντας την αναφορά της δομής BLINK, οδηγεί σε ένα στοιχείο WORK_QUEUE_ITEM (εδώ, είναι στην πραγματικότητα η πρώτη παράμετρος σε ένα
στοιχείο IO_WORKITEM).
Σημείωση Ο ορισμός της δομής για το στοιχείο IO_WORKITEM γίνεται διαθέσιμος χρησιμοποιώντας το διακομιστή συμβόλων για τα
Windows XP και νεότερες εκδόσεις. Η δομή είναι ίδια στις παλιότερες εκδόσεις
των Windows, αν και τα σύμβολα δεν είναι διαθέσιμα.
kd> dt -r1 _IO_WORKITEM 820ae3c8
+0x000 WorkItem :
+0x000 List : _LIST_ENTRY [ 0x0 - 0x8054edec ]
+0x008 WorkerRoutine : 0x8057fb78 nt!IopProcessWorkItem+0
+0x00c Parameter : 0x820ae3c8
+0x010 Routine : 0xf289dff0
+0 +0x014 DeviceObject : 0xfe01b110
+0x000 Type : 0 +0x002 Size : 0
+0x004 ReferenceCount : 0
+0x008 DriverObject : (null)
+0x00c NextDevice : (null)
+0x010 AttachedDevice : 0x1fde0970
+0x014 CurrentIrp : (null)
+0x018 Timer : (null)
+0x01c Flags : 0
+0x020 Characteristics : 0x490049
+0x024 Vpb : 0x000c0105
+0x028 DeviceExtension : 0x0001ffff
+0x02c DeviceType : 0x86a24
+0x030 StackSize : 8 ''
+0x034 Queue : __unnamed
+0x05c AlignmentRequirement : 0x7fffffff
+0x060 DeviceQueue : _KDEVICE_QUEUE
+0x074 Dpc : _KDPC
+0x094 ActiveThreadCount : 0
+0x098 SecurityDescriptor : (null)
+0x09c DeviceLock : _KEVENT
+0x0ac SectorSize : 0
+0x0ae Spare1 : 0
+0x0b0 DeviceObjectExtension : (null)
+0x0b4 Reserved : (null)
+0x018 Context : 0x81f4a14c
Σημείωση Τα περιεχόμενα του αντικειμένου συσκευής δεν δείχνουν ότι
πρόκειται για έγκυρο αντικείμενο συσκευής. Ωστόσο, το πεδίο Context είναι έγκυρο, και η εντολή !pool δείχνει pooltag με Culprit Pool Tag. - Για να προσδιορίσετε αν είναι έγκυρη η διεύθυνση ρουτίνας
(Routine), χρησιμοποιήστε την εντολή ln στη διεύθυνση του χώρου συγκέντρωσης (pool). Αν έχετε σύμβολα, το
αποτέλεσμα της χρήσης της εντολής ln στη διεύθυνση του χώρου συγκέντρωσης, θα πρέπει να αντιστοιχεί σε
μια διεύθυνση στο πιθανώς ελαττωματικό πρόγραμμα οδήγησης. Επομένως, μια σωστή
εικασία είναι ότι το IO_WORKITEM αντιστοιχεί σε κάποια συσκευή που δημιουργείται από το πρόγραμμα
οδήγησης της ετικέτας του χώρου συγκέντρωσης.
- Στον κώδικα που ακολουθεί, η ουρά εργασίας περιέχει μόνο
ένα στοιχείο. Επομένως, η κατάργηση της αναφοράς της δομής BLINK ήταν ένας εύκολος τρόπος για να το βρούμε. Επειδή η ουρά εργασίας
μπορεί να περιέχει πολλά στοιχεία, θα πρέπει να καταργήσετε την αναφορά της
δομής BLINK για κάθε στοιχείο εργασίας, μέχρι να βρείτε το στοιχείο εργασίας
του οποίου η δομή BLINK οδηγεί πίσω στο KQUEUE.
kd> !pool 81f4a14c
Pool page 81f4a14c region is Nonpaged pool
*81f4a140 size: 2b8 previous size: 8 (Allocated) *Culprit Pool Tag
Για να αποτρέψετε τη διακοπή του συστήματος με την εμφάνιση
αυτού του σφάλματος διακοπής (Stop error), απενεργοποιήστε και στη συνέχεια
αντικαταστήστε το ελαττωματικό πρόγραμμα οδήγησης που βρήκατε μέσω της περιόδου
λειτουργίας εντοπισμού σφαλμάτων.
Για
περισσότερες πληροφορίες, κάντε κλικ στον αριθμό του άρθρου παρακάτω, για να
προβάλετε το άρθρο της Γνωσιακής Βάσης της Microsoft (Knowledge Base):
314063
(http://support.microsoft.com/kb/314063/EL/
)
Αντιμετώπιση σφάλματος διακοπής Stop 0xA στα Windows XP
Για περισσότερες πληροφορίες και τεκμηρίωση από το
Windows DDK, επισκεφθείτε τις ακόλουθες τοποθεσίες του MSDN στο Web (στα
αγγλικά):