windows - Tråd-lokal opbevaring i kernel-tilstand?

Indlæg af Hanne Mølgaard Plasc

Problem



Er der en Thread-Local Storage (TLS) ækvivalent for kernel-mode drivere i Windows (Win32 for at være præcis)?


Hvad jeg forsøger at opnå:


Til sidst fra min chaufførs afsendelsesrutine kan det kalde mange andre funktioner (der kan være en dyb callstack). Jeg vil gerne give nogle kontekstoplysninger, der er specifikke for den anmodning, der behandles. Det vil sige, jeg har en struktur, en peger, som skal være synlig i alle de kaldte funktioner uden eksplicit at sende det som en parameter til hver funktion.


Brug af statisk/global er ikke en perfekt mulighed (multithreading, sync objekter og etc.).


Hvis det var en bruger-modus kode - ville man naturligvis bruge TLS i en sådan situation. Men AFAIK er der ingen kernel-mode funktioner som TlsGetValue/TlsSetValue. Og det giver mening - for at funktionen skal fungere, må man først tildele et proces-bredt TLS-indeks. OTOH-driverkode kan påberåbes på vilkårlig tråd, ikke begrænset til en bestemt proces.


Men jeg har faktisk ikke brug for en vedvarende trådspecifik opbevaring. Jeg har bare brug for en trådspecifik opbevaring til min topniveaufunktion påkaldelse.


Jeg tror, ​​jeg ved, hvordan man kan 'implementere' TLS, men på en hackish måde. I stedet for at tildele TLS-indekset bruger jeg altid et foruddefineret indeks (sige indeks=0). På øverste niveau funktion gemmer jeg den gemte TLS-værdi og overskriver den med den ønskede værdi. Efter færdiggørelse bliver den gemte værdi genoprettet.


Heldigvis ved jeg, hvordan TLS implementeres i Win32. Der er en TIB struktur (trådinformationsblok) for hver tråd. I hver tråd kan den fås ved hjælp af FS:[18h] vælger. TIB indeholder (blandt andet) en matrix, der anvendes af TLS . Resten er ret ligetil.


Men jeg foretrækker at bruge en officiel API til at opnå noget lignende.



  • Er der en officiel kernel-tilstand API for at opnå det, jeg har brug for?

  • Er der grunde til at undgå, hvad jeg planlægger at gøre? Jeg ved, at der muligvis kan være et problem med genindtræden (dvs. en kode påberåber mig, overskriver jeg TLS-værdien og kalder så til sidst oprindelseskoden, som kan stole på TLS). Men det er ikke muligt i mit specifikke tilfælde?

  • Er der mindre beskidte måder at løse dette på?



Tak på forhånd.


P. S. Man kan teoretisk bruge SEH (som også har lagret per-tråd information). Det vil sige at pakke topniveaukoden med \_\_try/\_\_except, så hvor kontekstinformationen er nødvendig - hæv kontinuable undtagelsen med en parameter, i \_\_except -blokken udfyld parameteren med kontekstoplysningerne, og genoptag eksekveringen. Og dette er et 100\% gyldigt programflow uden brug af de ukendte funktioner. Men det ser ikke desto mindre ud som et grimt hack for mig, for ikke at nævne præstationskomplikationerne.

Bedste reference


I stedet for at bruge FS: [[18h]] skal du nok bruge PsGetCurrentThreadTeb. Selv da tror jeg, at du vil være afhængig af detaljer, der kan ændre sig i fremtidige OS udgivelser (muligvis inklusive service packs).


I stedet kunne du ikke bruge KeGetCurrentProcessorNumber som et indeks i et array, hvor du kan gemme en peger til din kontekstinformation? (Hvis du kører på DISPATCH\_LEVEL eller højere selvfølgelig, så du ikke kan skiftes til en anden processor uventet.)


Hvis du ikke er garanteret at køre på DISPATCH\_LEVEL, kan du bruge en tabel eller en tilknyttet liste med hver post (som repræsenterer en tråd, der kører din kode), mærket med værdien af ​​PsGetCurrentThread.

Andre referencer 1


Du kan oprette en struktur, der besidder den indgående anmodning, og du videresender denne rundt i stedet for den faktiske anmodning, så sætter du bare i de felter, du har brug for. Selvfølgelig fjerner dette ikke helt behovet for at videregive et objekt rundt, men normalt overgår du normalt forespørgslen.


Fra de fleste af de føreren ting jeg har set (hvilket ganske vist ikke er en enorm mængde), var alt altid anmodet centreret. Så de bundet altid ting til anmodningen i stedet for at forsøge at holde det på en anden placering.

Andre referencer 2


Det gør du ikke med TEB! TIB og TEB er brugerdefinerede strukturer. En brugertilstandsapplikation kan modificere disse ting efter ønske fra en anden tråd/processor, mens din chauffør kører. Dette ville være et privilegium for eskalering af privilegier i din driver.


Jeg vil anbefale at aflevere en kontekststruktur for ephemeral kontekst relateret til din anmodning. Hvis du har brug for noget mere permanent, kan du bruge et AVL-bord eller et Hash-bord, som du rydder op, når tråde udløber.