funcții de management coadă joasă - studopediya

Pentru coadă prin utilizarea funcțiilor de nivel scăzut, folosind structura LIST_ENTRY standardul.

typedef struct _LIST_ENTRY

struct _LIST_ENTRY * volatil Flink; // pointer la următorul element din listă

struct _LIST_ENTRY * Blink volatil; // pointer la elementul lista precedentă

Se pare așa cum se vede din definiția structurii, bi-direcțională.

Structura este creată în mod tipic DeviceExtension LIST_ENTRY structura instanță care reprezintă capul de coadă, care este apoi inițializat folosind funcția InitializeListHead (). După aceea puteți adăuga sau șterge intrări în coada de așteptare. Pentru această funcție scop InsertHeadList (), InsertTailList (), RemoveHeadList (), RemoveTailList (), RemoveEntryList ().

IRP se adaugă la coadă în funcția de cameră de control, cel mai probabil, care rulează la IRQL = PASSIVE_LEVEL. În acest caz, să fie eliminate din coadă, ele pot funcționa, exerciții fizice la orice nivel ICCV, iar funcțiile, alegând IRP din coadă, se poate deplasa funcția IRP este plasată într-o coadă. Există o problemă de sincronizare. În cazul în care nu este rezolvată, neterminat operațiune spațiu IRP în coada de așteptare pot fi anulate operație de prelevare de probe IRP din coadă, care va avea ca rezultat un ecran albastru.

Sincronizarea de acces la resursa partajată este realizată prin spin-blocare (mecanisme de sincronizare vor fi discutate în capitolul următor). Având în vedere că exploatarea de adăugare și de ștergere a înregistrărilor în nivelurile coadă ICCV PASSIVE_LEVEL și DISPATCH_LEVEL foarte frecvente, pentru comportamentul lor în condiții de siguranță prevăzute pentru funcții speciale: ExInterlocked ... Lista (). Pentru a utiliza aceste funcții trebuie să fie create și inițializate de blocare de spin. Acesta este creat de obicei în același loc și rotiți capul (de obicei, DeviceExtension) și inițializat după capete de inițializare rândul său. De exemplu:

typedef struct _DEVICE_EXTENSION

// În funcție de DriverEntry

// atunci puteți adăuga și șterge înregistrări

PLIST_ENTRY pOldHead = ExInterlockedInsertHeadList (

După cum se poate observa din structura definiției LIST_ENTRY, conține câmpuri pentru stocarea datelor reale (de exemplu, un pointer la IRP de pachete). Prin urmare, comun mod de a utiliza structura LIST_ENTRY - includerea sa în instanță a unei structuri mai generale.

Pentru organizarea cozii de pachete IRP, fiecare în domeniul IRP Tail.Overlay.ListEntry conține LIST_ENTRY instanță a structurii. Acest lucru ridică întrebarea cum, știind că indicatorul LIST_ENTRY la o structură pentru a obține un pointer la structura IRP, care include LIST_ENTRY. Pentru acest DDK oferă o CONTAINING_RECORD macro specială

#define CONTAINING_RECORD (adresa. tip. câmp) \

((Tip *) ((PCHAR) (adresa) - (ULONG_PTR) (((tip *) 0) -> câmp)))

În ceea ce privește IRP, va trebui să scrie ceva de genul

pIrp = CONTAINING_RECORD (pListEntry, IRP, Tail.Overlay.ListEntry);

// continuare - prelucrare IRP

Organizarea IRP coadă de pachete este prezentată în figura următoare.

[10.2.2.2.2] funcții de management coadă la nivel înalt - "Queue Devices" (dispozitiv Queue)

Coadă driver creează dispozitive suplimentare prin alocarea de memorie din memoria nepaginată sub coadă suplimentare obiecte dispozitive KDEVICE_QUEUE și inițializează aceste obiecte prin KeInitializeDeviceQueue) funcția (. Adăugarea de pachete IRP în cozile de așteptare, se realizează printr-o funcție KeInsertDeviceQueue () sau KeInsertByKeyDeviceQueue () și probă pachetele din coada - KeRemoveDeviceQueue (), KeRemoveByKeyDeviceQueue () sau KeRemoveEntryDeviceQueue ().

Pentru organizarea IRP coadă de pachete de structura de tip KDEVICE_QUEUE_ENTRY utilizat, un pointer la care conținute în IRP în câmpul Tail.Overlay.DeviceQueueEntry.