Utsatte prosedyreanrop og avbruddshåndteringsrutiner. Systemavbrudd laster prosessoren. Alt skjedde på en eller annen måte plutselig, etter en omstart

Er prosessoren din overbelastet? Systemavbrudd har skylden.

Årsaken til at prosessoren er overbelastet nesten hele økten kan være såkalte systemavbrudd, og dette betyr igjen at problemet ligger i maskinvaren installert på datamaskinen eller driverne for disse enhetene. Men jeg advarer deg med en gang: selv volumet av hele denne artikkelen er ikke nok til å identifisere alle årsakene (og spesielt alternativene for deres løsninger) hvorfor systemavbrudd bare dreper Windows. Fordi tilnærmingen til å finne problemer er komplisert ved bruk av et mye mer komplekst verktøy enn det som er beskrevet her.

Hva er systemavbrudd og hvordan kan du prøve å takle prosessoroverbelastning?

Systemavbrudd vises i Task Manager som en systemprosess, men de er faktisk ikke slike. Denne " " er bare representativ, og gjenspeiler prosessorbelastningen når du arbeider med avbrudd på et lavt nivå. Det er en integrert del av Windows; du kan ikke drepe prosessen. Til tross for det illevarslende navnet, er systemavbrudd en obligatorisk og normal del av samspillet mellom CPU og annet utstyr.

Årsaken til avbrudd (mer presist, for treg drift fra tid til annen) kan være enheter inne i datamaskinen, installerte programmer og noen ganger selve prosessoren. Systemavbrudd er tross alt en viss form for interaksjon mellom programmet/maskinvaren og selve prosessoren. Hver gang en ny prosess må vises på systemet, dropper prosessoren alt og utfører oppgaven. Det spiller ingen rolle om brukeren klikket med musen eller om prosessen ble startet i henhold til tidsplanen, oppgaven legges umiddelbart til køen for utførelse. Etter fullføring går prosessoren tilbake til forrige tilstand.

Som du forstår, kan systemavbrudd godt signalisere til systemet og brukeren at for øyeblikket fortsetter noen beregninger med en feil, noe som gjenspeiles i det alvorlige forbruket av prosessorressurser ved denne "prosessen". I et sunt system "forbruker" systemavbrudd IKKE MER enn 2% av det totale prosessorarbeidet. Selv om jeg også har kommet over prosessorer med en avbruddsrate fra 3 til 10 %% - kommer alt an på konfigurasjonen. Men hvis du legger merke til at prosessoren bruker minst 5 - 10 % av prosessorkraften på avbrudd fra økt til økt, er dette et signal om at datamaskinen har problemer.

Systemet avbryter. Hvordan håndtere høye målinger?

Hvert av de følgende trinnene krever en omstart av systemet. Ikke fordi det er vanlig, men fordi problemer med avbrudd ofte løses ved å starte Windows på nytt.

  • SJÅFØRER OG FLERE SJÅFØRER

Det aller første verktøyet som vil hjelpe å avgjøre om ødelagte drivere er skyld i systemavbrudd som laster prosessoren, er et tysk verktøy DPC Latency Checker. Last den ned fra denne linken:

Ingen installasjon nødvendig. Essensen av verktøyet er enkelt. Vi starter og begynner å jobbe i Windows til systemavbrudd begynner å forstyrre oss. Her er vinduet til en normalt fungerende sammenstilling:

Men her begynner de å vise seg:

Verktøyet i kommentarfeltet på engelsk råder deg til å gå til Enhetsbehandling og begynne å gradvis deaktivere nettverksenheter, lydkort, USB-kontrollere, enheter blåtann. Jeg råder deg til å lytte. Etter hver nedleggelse, se nærmere på Task Manager og verktøyvinduet, se hvordan systemet reagerer på en midlertidig nedleggelse av utstyr. Fortsett ved å koble fra alle eksterne enheter: modemer, eksterne stasjoner, flash-stasjoner. Og hvis det på et tidspunkt er endringer til det bedre, bestem deg for å oppdatere driveren for enheten. Men for å unngå problemer med å starte Windows, er det bedre å ikke deaktivere disse enhetene (disse driverne er viktige, men de er også drivere, og det er ganske mulig at du må installere driverne på hovedkortet som en hel pakke, bare som når du installerer Windows fullstendig):

Programmet fungerer på samme måte LatencyMon

http://www.resplendence.com/downloads

Det krever installasjon, men er også gratis. Dens oppgave er å søke etter driverfiler med en høy frekvens av beregninger brukt på et utsatt prosedyrekall (en prosess som kalles opp av avbruddstjenesterutinen som svar på selve avbruddet, men som ikke nødvendigvis utføres umiddelbart). Dette vanskelige navnet skjuler prosessen med å søke etter drivere, hvis filer inneholder informasjon om at driveren krever for mye av prosessoren for å betjene enheten som er spesifikt tildelt den. Her er utgiversiden:

http://www.resplendence.com/latencymon

som jeg imidlertid med mine blinde øyne ikke fant en nedlastingslenke på, og derfor vil jeg gi deg muligheten til å laste ned programmet fra nettstedet mitt

LAST NED PROGRAMMET GRATIS

Etter å ha startet, informerte den meg umiddelbart om mulige problemer med DVD-stasjonen - driveren atapi.sys er spesifikt ansvarlig for det (og forresten, stasjonen har ikke fungert på nesten 3 måneder...). Advarer om at du kanskje må flashe BIOS:

Gå til fanen Drivere og sorter dem etter de mest sårbare indikasjonene ved å klikke på kolonnen DPC-antall:

Ta en nærmere titt på de første i rekken: de og kan væreårsaken til problemene dine.

  • ALT SKJEDE NOE Plutselig, ETTER OMSTARTEN

Det var et øyeblikk da aldri Det var ikke mulig å isolere årsaken til bremsene. En sak hjalp: brukeren "grep" et virus som fullstendig ødela DirectX, og handlet ekstremt selektivt, drepte Windows-systemfilene og etterlot DirectX-spillfiler. Jeg måtte reparere systemet med en oppdatering, og lo og se! – sammen med søppelet forsvant også systemavbrudd. Jeg brukte litt tid, men resultatet var uventet. De skyldige viste seg ikke å være virus eller drivere, men oppdateringspakker. Her er navnene deres:

  • KB3199986
  • KB4013418
  • KB3211320

Jeg insisterer på at det var ETTER INSTALLERING AV NØYAKTIG DISSE OPPDATERINGENE at en bestemt bruker begynte å lide av overbelastning med systemavbrudd. Noe sånt som dette... til ettertanke for deg.

  • VI EKLUDERER DEFEKT UTSTYR

Dette kan også være grunnen til at systemavbrudd overbelaster prosessoren. Begynn å sjekke om det forrige søket etter ødelagte drivere ikke ga suksess. Windows selv og dets innebygde selvdiagnoseverktøy vil hjelpe deg med å finne problemer med maskinvare. Jeg har allerede skrevet om dem i artikkelen. Skum øynene dine, informasjonen vil være nyttig, ikke tvil. Vær oppmerksom på at kabler som har løsnet fra kontakten også kan være årsaken til uhell. Jeg personlig møtte problemer med både prosessoroveroppheting og "glemsomhet" for å oppgradere BIOS for den splitter nye Windows 10 (mer om det nedenfor) - alt dette resulterte i merkbare systemavbrudd.

MERK. Hvis systemavbrudd plager den bærbare datamaskinen din, må du sørge for at du ikke har et døende batteriproblem. Les artikkelen på egenhånd.

  • SJEKK DITT WINDOWS-LYDSKEMA

Egentlig snakker vi om å tilbakestille lydeffektene i Windows til standard. Høyreklikk på lydikonet og klikk på Avspillingsenheter:

I Avspilling-fanen dobbeltklikker du på standardenhetselementet (for meg Høyttalere), gå til fanen Tilleggsfunksjoner og merk av i boksen ved siden av Deaktiver alle effekter. Søk - OK. Start på nytt og sjekk:

  • ER BIOSEN SKYLD?

Det er mulig. BIOS er det første programmet som starter etter at du har trykket på datamaskinens strømknapp. Så det er på tide å se etter oppdateringer til BIOS. Og for at søket etter den riktige versjonen ikke skal fortsette, sjekk versjonen av BIOS-en din akkurat nå. I kommandokonsollen cmd skriv inn to kommandoer i rekkefølge:

Systeminfo | findstr /I /c:bios wmic bios få produsent, smbiosbiosversion

Jeg i førstelaget - dette er en stor latin Jeg.

Er det harddisken?

“Ganske og til og med veldig bra.” Den enkleste måten er å sjekke disken for feil ved å bruke innebygde verktøy som chkdsk. Hvis systemavbruddene etter "kjøringen" har avtatt, har årsaken blitt oppdaget. Men i tilfelle når problemet dukker opp igjen og igjen, til tross for alt dette chkdsk oppdager alltid feil, du har problemer (med harddisken, strømforsyningen eller hovedkortet) - forbered deg på det verste.

P.S. Vel, etter vurderingene å dømme, er folk plaget av problemet. Jeg lover å utvikle emnet i fremtidige artikler.

Jeg ønsker deg suksess.

Lest: 1.238

Selv om de fleste avbrudd genereres i maskinvare, genererer Windows-kjernen programvareavbrudd for å utføre en rekke oppgaver, inkludert følgende:

  • start trådutsendelse;
  • behandle ikke-tidskritiske avbrudd;
  • håndtering av utløp av timer;
  • asynkron utførelse av en prosedyre i sammenheng med en spesifikk tråd;
  • støtte for asynkrone I/O-operasjoner.

Disse oppgavene diskuteres i de følgende avsnittene.

Sendbare avbrudd eller DPC-avbrudd (Deferred Procedure Call). Når en tråd ikke lenger kan fortsette å kjøre, kanskje fordi den har avsluttet eller fordi den frivillig har gått inn i en ventetilstand, kaller kjernen direkte koordinatoren for å utføre en umiddelbar kontekstbytte.

Men noen ganger oppdager kjernen at omplanlegging må skje når koden som kjøres er dypt nestet. I denne situasjonen ber kjernen om sending, men utsetter sending til den fullfører sitt nåværende arbeid. Å bruke et programvare-DPC-avbrudd er en praktisk måte å implementere denne forsinkelsen.

Kjernen hever alltid prosessorens IRQL til DPC/dispatch-nivå eller høyere når den trenger å synkronisere tilgang til delte kjernestrukturer. Dette blokkerer ytterligere programvareavbrudd og trådutsendelse. Når kjernen oppdager behovet for utsendelse, ber den om et DPC/utsendelsesnivåavbrudd, men prosessoren forsinker avbruddet fordi IRQL er på det nivået eller et høyere nivå.

Når kjernen fullfører sitt nåværende arbeid, ser prosessoren at den er i ferd med å sette IRQL under DPC/dispatch-nivået og sjekker for eventuelle ventende utsendelsesavbrudd. Hvis slike avbrudd er tilstede, senkes IRQL til DPC/utsendelsesnivået og utsendelsesavbrudd behandles. Å aktivere trådformidleren ved hjelp av et programvareavbrudd er en måte å utsette utsendelsen på til de rette omstendighetene oppstår for den. Men Windows bruker programvareavbrudd for å utsette andre typer behandling også.

I tillegg til trådutsendelse, behandler kjernen IRQL og deferred procedure calls (DPC) på dette nivået. DPC er en funksjon som utfører en systemoppgave som er mindre tidskritisk enn den gjeldende oppgaven.

Funksjoner kalles utsatt fordi de ikke krever umiddelbar utførelse.

Utsatte prosedyrekall gir operativsystemet muligheten til å generere et avbrudd og utføre en systemfunksjon i kjernemodus.

Kjernen bruker DPC-kall til å håndtere tidtakerutløp (og ledige tråder som venter på at tidtakere skal utløpe) og for å omplanlegge CPU-tid etter at en tråds tildelte tid (trådkvante) har utløpt. Enhetsdrivere bruker DPC-anrop for å håndtere avbrudd. For å sikre rettidig service av programvareavbrudd, jobber Windows med enhetsdrivere for å holde IRQL-er under enhets IRQL-nivåer. En måte å oppnå dette målet på er at enhetsdriver-ISRer utfører det minste nødvendige arbeidet for å varsle enhetene sine, opprettholde en midlertidig avbruddstilstand og forsinke dataoverføring, eller håndtere andre mindre tidskritiske avbrudd for kjøring i DPC-anrop på DPC IRQL-nivået . utsendelse.

Et DPC-kall er representert av et DPC-objekt, som er et kjernekontrollobjekt som er usynlig for brukermodusprogrammer, men synlig for enhetsdrivere og annen systemkode. Den viktigste informasjonen i et DPC-objekt er adressen til systemfunksjonen som kjernen vil kalle når et DPC-avbrudd behandles. DPC-prosedyrer som venter på å bli utført, lagres i kjernestyrte køer, én kø per prosessor.

De kalles DPC-køer. For en DPC-forespørsel kaller systemkoden kjernen for å initialisere et DPC-objekt og plasserer deretter objektet i DPC-køen.

Som standard plasserer kjernen DPC-objekter på slutten av DPC-køen til prosessoren som kjørte DPC-prosedyren (vanligvis prosessoren som ISR-prosedyren kjører på). Men enhetsdriveren kan overstyre denne oppførselen ved å spesifisere DPC-prioriteten (lav, middels, over middels eller høy, der standarden er middels prioritet) og målrette DPC-en mot en spesifikk prosessor. Et DPC-kall som retter seg mot en spesifikk CPU er kjent som en mål-DPC. Hvis DPC har høy prioritet, setter kjernen DPC-objektet øverst i køen, ellers for alle andre prioriteter plasserer den objektet på slutten av køen.

Kjernen behandler DPC-anrop når prosessorens IRQL-nivå er klart til å falle fra DPC/sendings-IRQL-nivået eller høyere til et lavere IRQL-nivå (APC eller passiv). Windows sørger for at IRQL forblir på DPC/dispatch-nivå og fjerner DPC-objekter fra den gjeldende prosessorens kø til den er oppbrukt (det vil si at kjernen "bruker opp" køen), og kaller hver DPC-funksjon etter tur. Kjernen vil tillate at IRQL-nivået faller under DPC/utsendelsesnivået og lar tråden fortsette normal kjøring bare når køen er oppbrukt. DPC-behandling er avbildet i figur DPC-prioriteringer kan påvirke systematferd på andre måter.

Vanligvis starter kjernen forbruket av DPC-køen ved å avbryte DPC/ekspedisjonsnivået. Kjernen genererer et slikt avbrudd bare når DPC-anropet er rettet til den gjeldende prosessoren (den som ISR-prosedyren kjører på) og DPC-en har en prioritet høyere enn lav. Hvis DPC har lav prioritet, ber kjernen om et avbrudd bare når antallet utestående DPC-forespørsler på prosessoren overskrider en terskel eller når antallet DPC-anrop som blir bedt om å bli utført på prosessoren i et gitt tidsvindu er lite.

DPC-anropslevering

Hvis et DPC-anrop retter seg mot en annen CPU enn den ISR-en kjører på, og DPC-prioriteten er høy eller middels høy, signaliserer kjernen umiddelbart mål-CPU (ved å sende den en utsendelses-IPI) til forbruk av DPC-køen. , men bare hvis målprosessoren er i hvilemodus. Hvis prioriteten er middels eller lav, må antallet DPC-anrop som står i kø på målprosessoren overskride en viss terskel for at kjernen skal utstede et DPC/utsendelsesavbrudd. En inaktiv systemtråd tapper også DPC-køen til prosessoren den kjører på. Til tross for fleksibiliteten som DPC-anropsmål og prioritetsnivåer gir systemet, trenger enhetsdrivere sjelden å endre standardoppførselen til DPC-objektene sine. Situasjoner som utløser tømming av DPC-køen er oppsummert i tabellen. Hvis du ser på generasjonsreglene, så viser det seg faktisk at prioriteringene over middels og høye er lik hverandre. Forskjellen er tydelig når de settes inn i listen, med avbrudd på høyt nivå foran og øvre middels avbrudd bak.

Siden brukermodustråder kjører med lav IRQL, er sjansen stor for at et DPC-anrop vil avbryte kjøringen av en vanlig brukertråd. DPC-prosedyrer utføres uavhengig av hvilken tråd som kjører, så når en DPC-prosedyre kjører, kan den ikke gjette på hvem sitt adresseområde, hvilken prosess som vises for øyeblikket. DPC-rutiner kan kalle opp kjernefunksjoner, men de kan ikke kalle systemtjenester, generere feil på siden eller opprette eller vente på utsendelsesobjekter. Imidlertid kan de få tilgang til ikke-søkte adresser i systemminnet fordi systemets adresserom alltid er kartlagt, uavhengig av hva den gjeldende prosessen er.

Regler for å generere et DPC-avbrudd.

DPC-prioritetEt DPC-anrop retter seg mot prosessoren som utfører
ISR-prosedyre
DPC-anropsmål
til en annen prosessor
LavDPC-kølengden overskrider maksimal DPC-kølengde eller nivået på DPC-forespørsler er under minimum
DPC-forespørselsnivå
Gjennomsnitt
(Medium)
AlltidDPC-kølengden overskrider den maksimale DPC-kølengden eller systemet er inaktivt
Over gjennomsnittet
(Medium høy)
Alltid
HøyAlltidMålprosessoren er inaktiv

DPC-anrop leveres primært til enhetsdrivere, men brukes også av kjernen. Vanligvis bruker kjernen DPC for å håndtere utløp av tidsstykke. Ved hvert klokkemerke oppstår et avbrudd på IRQL-nivået for klokken. Klokkeavbruddsbehandleren (kjører på klokke-IRQL-nivå) oppdaterer systemtiden og reduserer deretter telleren som sporer hvor lenge den gjeldende tråden har kjørt.

Når telleren når null, utløper trådens tidsstykke, og kjernen må kanskje omplanlegge CPU-tid, dvs. utføre en oppgave med lavere prioritet som skal utføres på DPC/dispatch IRQL-nivå.

Klokkeavbruddsbehandleren setter et DPC-anrop i kø for å starte trådutsendelse og avslutter og senker prosessorens IRQL-nivå. Fordi DPC-avbruddet har lavere prioritet enn enhetsavbrudd, behandles eventuelle ventende enhetsavbrudd som oppstår før klokkeavbruddet fullføres før DPC-avbruddet utstedes.

Siden DPC-anrop utføres uavhengig av hvilken tråd som kjører på systemet for øyeblikket (omtrent som avbrudd), er de hovedårsaken til at systemet de utføres på ikke reagerer på arbeidsbelastningen til klientsystemer eller arbeidsstasjon fordi selv de høyest prioriterte trådene vil bli avbrutt av et ventende DPC-anrop.

Noen DPC-anrop tar så lang tid at brukere kan legge merke til video- eller lydforsinkelse eller til og med oppleve unormalt treg mus- eller tastaturrespons, så for drivere med lange DPC-anrop støtter Windows streaming av DPC-anrop.

Trådede DPC-anrop, som navnet antyder, er designet for å utføre en DPC-prosedyre på passivt nivå på en tråd med sanntidsprioritet (prioritet 31). Dette lar DPC-kallet ha forrang over de fleste brukermodustråder (siden de fleste applikasjonstråder ikke kjører i sanntidsprioritetsområder). Men dette lar andre avbrudd, ikke-trådede DPC-anrop, APC-anrop og høyere prioriterte tråder utøve sin prioritet over denne prosedyren.

Et viktig trekk ved rutiner som utføres på avbruddsforespørsler er at de utfører arbeid som oftest ikke har noe med den pågående prosessen å gjøre.

For eksempel kan en diskdriver motta kontroll etter at diskkontrolleren har skrevet informasjon mottatt fra prosess A til de passende sektorene, men dette tidspunktet faller ikke sammen med perioden for neste iterasjon av prosess A eller dens tråd.

I det mest typiske tilfellet vil prosess A vente på at I/O-operasjonen skal fullføres (hvis operasjonen kjører synkront), og diskdriveren vil avbryte en annen prosess.

I noen tilfeller er det generelt vanskelig å entydig bestemme hvilken prosess en bestemt OS-programvaremodul, for eksempel en trådplanlegger, utfører arbeid. Derfor innføres begrensninger for denne typen prosedyrer - de har ikke rett til å bruke ressurser (minne, åpne filer osv.) som den nåværende prosessen fungerer med.

Avbruddsrutiner fungerer med ressursene som ble tildelt dem da den tilsvarende driveren ble initialisert eller selve operativsystemet ble initialisert. Disse ressursene tilhører operativsystemet, ikke til en bestemt prosess. Dette er hvordan minne allokeres til drivere fra systemområdet. Derfor er det vanlig å si at avbruddsrutiner opererer utenfor konteksten av en prosess.

Avbruddssending er en viktig OS-funksjon, og denne funksjonen er implementert i nesten alle multiprogrammerings-OSer. Som regel implementerer operativsystemet en arbeidsplanleggingsmekanisme på to nivåer. Det øverste planleggingsnivået utføres av avbruddsbehandleren, som fordeler prosessortid mellom en strøm av innkommende forespørsler om avbrudd av ulike typer - eksternt, internt og programvare. Den gjenværende prosessortiden tildeles av en annen avsender - trådavsenderen, basert på kvantiseringsdisiplinene og andre som vi har vurdert.

Systemanrop

Et systemanrop lar en applikasjon kontakte operativsystemet med en forespørsel om å utføre en bestemt handling, formatert som en prosedyre (eller et sett med prosedyrer) for OS-kodesegmentet.

For en applikasjonsprogrammerer ser operativsystemet ut som et bibliotek som implementerer nyttige funksjoner som gjør det enklere å administrere en applikasjonsoppgave eller utføre handlinger som er forbudt i brukermodus, for eksempel utveksling av data med en I/O-enhet.

Implementeringen av systemanrop må tilfredsstille følgende krav:

· gi bytte til privilegert modus;

· ha høy hastighet for å ringe OS-prosedyrer;

· gi enhetlig tilgang til systemanrop for alle maskinvareplattformer som operativsystemet kjører på;

· tillate enkel utvidelse av settet med systemanrop;

· gi OS-kontroll over riktig bruk av systemanrop

I de fleste operativsystemer håndteres systemanrop på en sentralisert måte basert på eksistensen av en systemanropsbehandler.

For ethvert systemanrop, utfører applikasjonen et programvareavbrudd med et spesifikt og unikt vektornummer.

Før et programvareavbrudd utføres, sender applikasjonen systemets anropsnummer til operativsystemet. Overføringsmetoden er implementeringsavhengig. For eksempel kan nummeret plasseres i et spesifikt prosessorregister eller føres gjennom stabelen. Systemanropsargumenter sendes også på en eller annen måte; de ​​kan overføres enten til generelle registre eller sendes gjennom en stabel eller en rekke RAM.

Prosedyre adresse 21h
Prosedyre adresse 22h
Prosedyre adresse 23h
Systemanropsadministratoradresse
System Call Manager
Prosedyre for håndtering av systemanrop 21t
Prosedyre for behandling Systemanrop 22t
Prosedyre for håndtering av Systemanrop 23t

Etter at systemanropet er fullført, returneres kontrollen til ekspeditøren, og han mottar også fullføringskoden for denne samtalen. Avsenderen gjenoppretter prosessorens registre, plasserer en returkode i et spesifikt register og utfører en returinstruksjon fra et avbrudd, som gjenoppretter prosessorens uprivilegerte modus.

Den beskrevne tabellmetoden for å organisere systemanrop er akseptert i nesten alle operativsystemer. Den lar deg enkelt endre sammensetningen av systemanrop ved ganske enkelt å legge til en ny adresse i tabellen og utvide utvalget av gyldige anropsnumre.

OS kan utføre systemanrop inn synkron eller asynkron moduser.

Synkron systemanrop betyr at prosessen som foretok et slikt anrop, stanses inntil systemanropet har fullført alt nødvendig arbeid . Etter dette setter planleggeren prosessen i klar tilstand.

Asynkron systemanrop fører ikke til at prosessen settes i hvilemodus, etter å ha utført noen innledende systemhandlinger, for eksempel å starte en I/O-operasjon, går kontrollen tilbake til applikasjonsprosessen.

De fleste systemanrop i operativsystemet er synkrone.

Send ditt gode arbeid i kunnskapsbasen er enkelt. Bruk skjemaet nedenfor

Studenter, hovedfagsstudenter, unge forskere som bruker kunnskapsbasen i studiene og arbeidet vil være deg veldig takknemlig.

BEREGNING OG FORKLARENDE MERKNAD

for et kursprosjekt om emnet:

Applikasjonsprofiler

1. Introduksjon

2. Analytisk del

2.1. Teknisk oppgave

2.2. Windows NT 5.x arkitekturoversikt

2.3. Sjåførklassifisering

2.4. Generell struktur for Legacy-driveren

2.4.1. Driverinntastingsprosedyre

2.4.2. DriverUtlastingsprosedyre

2.4.3. Arbeidsflyter for behandling av IRP-pakker

2.4.3.1. IRP-pakkehode

2.4.3.2. IRP-stabel

2.4.3.3. Pakkebehandlingsfunksjon IRP_MJ_CREATE

2.4.3.4. Pakkebehandlingsfunksjon IRP_MJ_CLOSE

2.4.3.5. Pakkebehandlingsfunksjon IRP_MJ_DEVICE_CONTROL

2.4.4. ISR - Rutine for avbruddstjeneste

2.4.5. DPC - utsatt anropsprosedyre

3. Designdel

3.1. Eldre driver

3.1.1. Driverinntastingsprosedyre

3.1.2. Last ned driver

3.1.3. DispatchCreate og DispatchClose

3.1.4. DispatchDeviceControl

3.2. Tilpasset applikasjon

4. Teknisk seksjon

4.1. Velge et operativsystem og programmeringsmiljø.

4.2. Grensesnitt

4.3. Systemkrav

5. Konklusjon.

6. Liste over brukt litteratur.

1. Introduksjon

Svært ofte, når du utvikler programvare, er det behov for å overvåke driften: hvor lenge trådene kjører i kjernemodus, hvor lenge i brukermodus, hvor mye tid de bruker på å vente, samt antall kontekstbytter fra én modus til en annen. Alt dette er viktig, siden hver modus har sine egne egenskaper. I kjernemodus kjører koden raskere, men det er et potensial for korrupsjon av data/systemkode. I motsetning til kjernemodus er brukermodus begrenset i tjenestene den kan tilby, slik at koden ikke kan krasje systemet. For samme formål utføres ytterligere kontroller i brukermodus for å forhindre utførelse av ondsinnede instruksjoner. Derfor er utførelseshastigheten til brukermoduskoden betydelig lavere. Antall kontekstbrytere påvirker også hastigheten på kodeutførelsen, siden denne operasjonen er ganske dyr (ca. 2000 klokkesykluser). Dette var tydelig merkbart under utviklingen av laboratoriearbeid og et kursprosjekt om datagrafikk: når du tegnet et bilde piksel for piksel ved hjelp av SetPixel-funksjonen, var tegnehastigheten uforholdsmessig lavere enn ved bruk av en brukermodusbuffer, hvor informasjon om fargen av pikslene som tilsvarer bufferelementene ble gradvis lagt inn. Dette var på grunn av det faktum at ved bruk av SetPixel-funksjonen, skjedde det to kontekstsvitsjer (fra brukermodus til kjernemodus og tilbake) per piksel, og ved bruk av en buffer som lagrer en kontekstuavhengig representasjon av farge, skjedde de samme to svitsjene, men en gang for å tegne hele rammen.

Dermed vil muligheten til å finne ut den ovennevnte statistiske informasjonen om målprogramvaren tillate deg å umiddelbart legge merke til de såkalte "flaskehalsene" i programmet som forstyrrer å forbedre ytelsen til applikasjonen som helhet.

2. Analytisk seksjon

2.1 Teknisk oppgave

Målet med det presenterte kursprosjektet er å utvikle en enkel applikasjonsprofiler, som inkluderer:

Eldre driver, som bør:

Periodisk oppdatere informasjon om prosesser og deres flyter;

Gi grunnleggende informasjon om prosesser og deres tråder;

Oppgi maskinvarekontekst for den valgte tråden;

Sørg for sikker tilgang til denne informasjonen fra flere brukerklientapplikasjoner.

En tilpasset applikasjon som lar deg:

Installer og fjern driveren på riktig måte uten å måtte starte systemet på nytt;

Kontakt sjåføren med forespørsler for å få diverse opplysninger.

2.2 Arkitektur oversiktWindows NT 5.x

På Windows er applikasjoner atskilt fra selve operativsystemet. Kjernekoden kjører i privilegert prosessormodus ( kjernemodus), som gir tilgang til systemdata og maskinvare. Applikasjonskoden kjører i uprivilegert prosessormodus ( tilpasset modus) med et ufullstendig sett med grensesnitt, begrenset tilgang til systemdata og ingen direkte tilgang til utstyr. Når et brukermodusprogram kaller en systemtjeneste, avskjærer prosessoren samtalen og bytter anropstråden til kjernemodus. Når systemtjenesten avsluttes, bytter operativsystemet trådens kontekst tilbake til brukermodus og fortsetter å kjøre den.

Det følgende viser skjematisk den delen av Windows-arkitekturen som påvirkes av dette kursprosjektet. Komponenter som systemstøtteprosesser, tjenesteprosesser, miljøundersystemer, maskinvareabstraksjonsnivå og støtte for vinduer og grafikk er ikke spesifisert her.

Brukerapplikasjoner er en type brukerprosess som kjører i brukermodus, der de er begrenset til å bruke uprivilegerte instruksjoner.

Delsystem-DLL-er -- I Windows kan ikke brukerapplikasjoner kalle operativsystemtjenester direkte; i stedet jobber de med en eller flere undersystem-DLL-er hvis formål er å oversette dokumenterte funksjoner til tilsvarende interne (og vanligvis udokumenterte) kall til systemtjenester.

Det utøvende systemet inneholder kjerneoperativsystemtjenestene som gir minne, prosess- og trådadministrasjon, sikkerhet, I/O og kommunikasjon mellom prosesser.

Kjernen inneholder operativsystemfunksjoner på lavt nivå som støtter for eksempel trådplanlegging, avbrudd og unntakssending. Det gir også et sett med prosedyrer og grunnleggende objekter som det utøvende systemet bruker for å implementere strukturer på høyere nivå.

Drivere brukes til å utvide funksjonaliteten til kjernen.

2.3 Sjåførklassifisering

I motsetning til en brukerapplikasjon er en driver ikke en prosess og har ingen utførelsestråd. I stedet overføres kontrollen til sjåføren som et resultat av en I/O-forespørsel fra en brukerapplikasjon eller driver, eller som et resultat av et avbrudd. I det første tilfellet er driverutførelseskonteksten nøyaktig kjent - det er et applikasjonsprogram. I det andre tilfellet kan utførelseskonteksten enten være kjent eller tilfeldig - det avhenger av utførelseskonteksten til den kallende driverfunksjonen. I det tredje tilfellet er kjøringskonteksten tilfeldig, siden et avbrudd (og følgelig kjøringen av driverkode) kan oppstå under kjøringen av et hvilket som helst applikasjonsprogram.

Etter plassering i driverstabelen:

Drivere på høyere nivå -- motta forespørsler fra brukerapplikasjonen og samhandle med drivere på lavere nivå;

Mellomliggende drivere -- motta forespørsler fra oppstrømsdrivere og samhandle med nedstrømsdrivere;

Sjåfører på lavt nivå mottar forespørsler fra sjåfører på høyere nivå og utfører sluttbehandling av forespørselspakker.

Fremhev også konseptet monolittisk driver- en sjåfør på toppnivå som ikke samhandler med andre sjåfører.

I forbindelse med forbedringen av Windows-drivermodellen (WDM - Windows Driver Model), der Plug and Play-støtte og energisparende teknologier ble lagt til, begynte driverne å bli delt inn i:

Eldre drivere (Legacy drivere, NT-stil drivere) - drivere skrevet i gammel stil, uten støtte for innovasjoner;

WDM-drivere - drivere som tilfredsstiller alle kravene til den utvidede WDM-modellen.

2.4 Generell struktur for Legacy-driveren

Den eldre driveren har følgende hovedinngangspunkter:

DriverEntry - prosedyre for sjåførinnlasting;

DriverUnload - prosedyre for sjåføravlasting;

Driftsprosedyrer for behandling av IRP-pakker;

ISR-prosedyre (Interrupt Service Routine) - prosedyre for avbruddsbehandling;

DPC-prosedyre (Deferred Procedure Call) - en utsatt anropsprosedyre.

2.4.1 Driverinntastingsprosedyre

Denne prosedyren finnes i alle drivere og kalles opp av I/O-manageren når driveren er lastet inn.

Eldre drivere utfører betydelig mer arbeid i den enn WDM-drivere, siden de er tvunget til å utføre arbeidet med AddDevice-prosedyren, som er obligatorisk for WDM-drivere. I tillegg til å løse initialiseringsoppgaver og registrere inngangspunkter for arbeidsprosedyrer for behandling av støttede IRP-pakker og prosedyrer for utlasting av drivere, her:

Maskinvaren som driveren vil kontrollere bestemmes;

Enhetsobjekter opprettes (IoCreateDevice-funksjon) for hver fysisk eller logisk enhet som kontrolleres av denne driveren;

For enheter som skal være synlige for brukerapplikasjoner, opprettes symbolske lenker (IoCreateSymbolicLink-funksjon);

Om nødvendig kobles enheten til avbruddsobjektet. Hvis ISR-prosedyren krever bruk av en DPC-prosedyre, blir det tilsvarende objektet opprettet og initialisert på dette stadiet;

Tildeling av minne som kreves for driverdrift.

2.4.2 DriverUtlastingsprosedyre

I/O-manageren kaller denne prosedyren ved dynamisk utlasting av en driver. Denne prosedyren gjør det motsatte av det som gjøres i DriverEntry-prosedyren.

Følgende trinn er typiske for eldre drivere:

For noen typer maskinvare er det nødvendig å lagre tilstanden i systemregisteret, fordi når du laster driveren senere, kan disse dataene brukes;

Hvis avbrudd er aktivert for enheten som betjenes, må avlastingsprosedyren deaktivere dem og koble fra avbruddsobjektet. En situasjon der en enhet genererer avbrudd for et ikke-eksisterende avbruddsobjekt vil uunngåelig føre til et systemkrasj;

Slett et enhetsobjekt (IoDeleteDevice);

Frigjør minne som er tildelt sjåføren under drift.

2.4.3 Arbeidsflyter for behandling av IRP-pakker

Alle funksjoner som er registrert i DriverEntry-prosedyren ved å fylle ut MajorFunction-matrisen kalles opp av I/O Manager for å håndtere passende forespørsler fra driverens klienter. Disse forespørslene er alltid formatert i form av spesielle datastrukturer - IRP-pakker, hvor minne tildeles av I/O Manager i den ikke-sidede systempoolen. Strukturen til en IRP-pakke er slik at den består av en header med fast størrelse og en IRP-stabel, hvis størrelse avhenger av antall enhetsobjekter i stabelen.

2.4.3.1 IRP-pakkeoverskrift. IRP-pakkehodestrukturen har følgende felt:

IoStatus-feltet av typen IO_STATUS_BLOCK inneholder to underfelt:

Status inneholder verdien som driveren angir etter å ha behandlet pakken;

Informasjon inneholder oftest antall byte som sendes eller mottas.

AssociatedIrp.SystemBuffer-feltet av typen PVOID inneholder en peker til systembufferen i tilfelle enheten støtter bufret I/O;

MdlAddress-feltet av PMDL-typen inneholder en peker til MDL-listen hvis enheten støtter direkte input/output;

UserBuffer-feltet av typen PVOID inneholder adressen til brukerbufferen for I/O;

Avbryt BOOLEAN-feltet er en indikator på at IRP bør kanselleres.

2.4.3.2 IRP-pakkestabel. Det primære formålet med IRP-stabelceller er å lagre funksjonskode og I/O-forespørselsparametere. For en forespørsel som er adressert til driveren på laveste nivå, har den tilsvarende IRP-pakken bare én stabelplassering. For en forespørsel som sendes til en driver på øverste nivå, oppretter I/O Manager en IRP med flere stabelceller, en for hvert enhetsobjekt.

Hver IRP-stabelcelle inneholder:

MajorFunction av typen UCHAR er kode som beskriver formålet med operasjonen;

MinorFunction av typen UCHAR er en kode som beskriver en underkode til operasjonen;

DeviceObject av typen PDEVICE_OBJECT er en peker til enhetsobjektet som denne IRP-forespørselen ble adressert til;

FileObject av typen PFILE_OBJECT - filobjekt for denne forespørselen;

Parametre for unionstype - bruk avhenger av MajorFunction-verdien.

I/O-manageren bruker MajorFunction-feltet til å hente frem prosedyren som trengs for å behandle forespørselen fra MajorFunction-arrayen.

Hver prosedyre for å behandle IRP-pakker må ta som parametere:

Peker til enhetsobjektet som IRP-forespørselen er ment for;

En peker til en IRP som beskriver denne forespørselen;

2.4.3.3 Pakkebehandlingsfunksjon IRP_MJ_CREATE. Denne funksjonen er utformet for å håndtere forespørsler om en driverbeskrivelse fra brukerapplikasjoner eller oppstrømsdrivere. Vanligvis merker denne funksjonen ganske enkelt IRP-pakken som fullført.

2.4.3.4 Pakkebehandlingsfunksjon IRP_MJ_CLOSE. Denne funksjonen er utviklet for å håndtere forespørsler om å lukke et driverhåndtak fra brukerapplikasjoner eller oppstrømsdrivere. Vanligvis merker denne funksjonen ganske enkelt IRP-pakken som fullført.

2.4.3.5 Pakkebehandlingsfunksjon IRP_MJ_DEVICE_CONTROL. Denne funksjonen lar deg behandle avanserte forespørsler fra brukermodusklienter, som oftest brukes til å utveksle data mellom applikasjonen og driveren. En slik forespørsel kan genereres ved å kalle opp DeviceIoControl-funksjonen fra brukermodus.

IOCTL-koder (I/O-kontrollkoder) brukes her, noen av dem er forhåndsdefinert av operativsystemet, og noen kan opprettes av driverutvikleren. Denne koden spesifiseres i forespørselen av I/O Manager når IRP-pakken genereres.

Driveroperasjoner som opererer på IOCTL-forespørsler krever ofte at et bufferområde spesifiseres for å imøtekomme inn- eller utdata. En situasjon er mulig når begge buffere brukes i en forespørsel.

Datatilgangsmetoden gitt av I/O Manager er definert i IOCTL-koden. Slike metoder kan være:

METHOD_BUFFERED: Inngangsbrukerbufferen kopieres til systembufferen, og når behandlingen er fullført, kopieres systembufferen til utgangsbrukerbufferen.

METHOD_IN_DIRECT: De nødvendige brukerbuffersidene lastes fra disken til RAM og låses. Deretter, ved hjelp av DMA, overføres data mellom enheten og brukeren.

METHOD_OUT_DIRECT: De nødvendige brukerbuffersidene lastes fra disken til RAM og låses. Deretter, ved hjelp av DMA, overføres data mellom enheten og brukeren.

METHOD_NEITHER: Denne overføringsmetoden sjekker ikke for minnetilgjengelighet, tildeler mellombuffere eller oppretter MDL-er. IRP-pakken bærer de virtuelle adressene til bufferne i adresserommet til initiatoren av I/O-forespørselen.

I dette tilfellet har flaggene som bestemmer typen bufring i enhetsobjektet ingen betydning når du arbeider med IOCTL-forespørsler. Den bufrede utvekslingsmekanismen er definert når IOCTL-verdien er spesifisert i en dedikert del av denne datastrukturen. Denne tilnærmingen gir maksimal fleksibilitet når du arbeider med brukermoduskallet DeviceIoControl.

Fra førerens synspunkt får man tilgang til bufferområder som inneholder eller er beregnet på data ved å bruke følgende strukturfelt:

METHOD_IN_DIRECT eller METHOD_OUT_DIRECT

Buffer med data

Bufferadressen i systemadresserommet er spesifisert i pIrp->AssociatedIrp.SystemBuffer

Virtuell klientadresse i Parameters. DeviceIoControl. Type3InputBuffer

Lengden er spesifisert i Parameters.DeviceIoControl.InputBufferLength

Buffer for data

Bruker buffering (systembuffer)

Adressen til bufferen i systemadresserommet er spesifisert i pIrp->AssociatedIrp. Systembuffer

Bruker direkte tilgang, klientbufferen konverteres til en MDL-liste, hvor pekeren er plassert i pIrp->MdlAddress

Virtuell klientadresse i pIrp->UserBuffer

Lengden er spesifisert i Parameters.DeviceIoControl.OutputBufferLength

2.4.4 ISR - Rutine for avbruddstjeneste

Sjåføren registrerer denne funksjonen slik at den får kontroll i det øyeblikket maskinvaren som betjenes av sjåføren sender et avbruddssignal. Hensikten med denne funksjonen er å gjøre minimalt med arbeid og registrere en utsatt anropsprosedyre (DPC) for å betjene avbruddet. Et kjerneavbruddsbehandlerkall kan forekomme i alle sammenhenger: både kjernen og brukerprosessen.

2.4.5 DPC - utsatt anropsprosedyre

Slike rutiner kjører på et lavere avbruddsforespørselsnivå (IRQL) enn ISR, så de blokkerer ikke andre avbrudd. De kan utføre alt eller fullstendig avbruddsservicearbeid som er startet i ISR.

3. Designseksjon

Slik ser interaksjonen mellom en brukerapplikasjon og driveren gjennom systemkomponenter ut:

3.1 arv-sjåfør

Den eldre driveren for dette kursprosjektet implementerer følgende prosedyrer:

DispatchCreate (behandler IRP_MJ_CREATE-pakke);

DispatchClose (behandler IRP_MJ_CLOSE-pakke);

DispatchDeviceControl (behandler IRP_MJ_DEVICE_CONTROL-pakke).

3.1.1 Driverinntastingsprosedyre

Her utføres typiske handlinger for initialisering av en driverdriver.

Førerinngangspunkter er registrert:

pDriverObject->DriverUnload = SpectatorDriverUnload;

PDRIVER_DISPATCH * majorFunction = pDriverObject->MajorFunction;

majorFunction[ IRP_MJ_CREATE ] = SpectatorDispatchCreate;

majorFunction[ IRP_MJ_CLOSE ] = TilskuerDispatchClose;

majorFunction[ IRP_MJ_DEVICE_CONTROL ] = SpectatorDispatchDeviceControl;

Et enhetsobjekt kalt DEVICE_NAME er opprettet:

#define DEVICE_NAME L"\\Device\\Spectator"

RtlInitUnicodeString(&enhetsnavn, DEVICE_NAME);

status = IoCreateDevice

sizeof(DEVICE_EXTENSION),

FILE_DEVICE_SPECTATOR,

FILE_DEVICE_SECURE_OPEN,

&pDeviceObject);

En symbolsk kobling SYMBOLIC_LINK er registrert for det opprettede enhetsobjektet:

#define SYMBOLIC_LINK L"\\DosDevices\\Spectator"

RtlInitUnicodeString(&symbolicLink, SYMBOLIC_LINK);

status = IoCreateSymbolicLink(&symbolicLink, &deviceName);

Et mutex-kjerneobjekt opprettes:

NTSTATUS CreateMutex()

(BEGIN_FUNC(CreateMutex);

NTSTATUS status = STATUS_SUCCESS;

status = _ExAllocatePool(g_pMutex, NonPagedPool, sizeof(KMUTEX));

if (NT_SUCCESS(status))

(KeInitializeMutex(g_pMutex, 0);

status = STATUS_SUCCESS;)

END_FUNC(CreateMutex);

returnere (status);)

For første gang lastes informasjon om prosesser og deres tråder:

if (LockInfo() == STATUS_SUCCESS)

LockInfo()- og UnlockInfo()-funksjonene er ganske enkelt wrapper-funksjoner for henholdsvis LockMutex()- og UnlockMutex()-funksjonene. Den første av de to siste funksjonene venter på et mutex-kjerneobjekt.

Kjerneobjekter kalt mutexes garanterer at tråder har gjensidig eksklusiv tilgang til en enkelt ressurs. Det er her navnet på disse objektene kommer fra (gjensidig ekskludering, mutex). De inneholder en brukerteller, en rekursjonsteller og en variabel som lagrer tråd-IDen. Mutexes oppfører seg nøyaktig det samme som kritiske seksjoner. Men mens sistnevnte er brukermodusobjekter, er mutexes kjerneobjekter. I tillegg lar et enkelt MewTex-objekt flere tråder fra forskjellige prosesser synkronisere tilgang til en ressurs; I dette tilfellet kan du angi maksimal ventetid for tilgang til ressursen.

Det er takket være denne mutexen at sikkerhetskravet er sikret ved tilgang til lagret informasjon.

Timeroperasjonen initialiseres:

En timer er nødvendig for å oppdatere den lagrede informasjonen med et visst intervall.

For å gjøre dette opprettes et kjerneobjekt "timer":

status = _ExAllocatePool(g_pTimer, NonPagedPool, sizeof(KTIMER));

KeInitializeTimerEx(g_pTimer, SynchronizationTimer);

Kommentar: minne for kjerneobjekter må tildeles eksklusivt i det ikke-sidede utvalget (NonPagedPool nøkkelord).

Tidtakere kan være av to typer:

SynchronizationTimer -- etter at et spesifisert tidsintervall eller periode har gått, settes den i en signaltilstand til en av trådene som venter på den, vekkes. Deretter slås timeren til en ikke-signaltilstand.

NotificationTimer -- etter at det angitte tidsintervallet eller perioden er utløpt, settes den i en signaltilstand, og alle tråder som venter på den vekkes. En slik tidtaker forblir i signalisert tilstand inntil den eksplisitt settes til ikke-signalert.

For å gjøre noe nyttig arbeid med tidtakeren, må du registrere OnTimer() DPC-prosedyren. For det må du lage ditt eget DPC-objekt, som med jevne mellomrom vil bli plassert i den systemomfattende køen:

status = _ExAllocatePool(g_pTimerDpc, NonPagedPool, sizeof(KDPC));

KeInitializeDpc(g_pTimerDpc, OnTime, NULL);

Videre, på grunn av det faktum at i denne timerdriverhandlinger som krever en brukerkontekst må utføres, må de tas ut av OnTimer()-funksjonen, som er en DPC-prosedyre, og derfor er bare systemkonteksten tilgjengelig under dens henrettelse. Du må imidlertid sørge for at det nødvendige arbeidet gjøres i rimelig synkronisering med tiden DPC-funksjonsobjektet fjernes fra køen for behandling. For å gjøre dette vil vi opprette en tråd som vil være dedikert til å vente på en hendelse:

OBJECT_ATTRIBUTES objectAttributes;

InitializeObjectAttributes(&objectAttributes, NULL, OBJ_KERNEL_HANDLE,

status = PsCreateSystemThread(&hThread, THREAD_ALL_ACCESS, &objectAttributes,

NULL, NULL, UpdateThreadFunc, NULL);

KeInitializeEvent(g_pUpdateEvent, SynchronizationEvent, FALSE);

Kommentar: Hendelseskjerneobjekter er identiske i type med tidtakerkjerneobjekter.

Når denne hendelsen mottas, vil tråden oppdatere systeminformasjon om prosessene og deres tråder. Vi vil overføre objektet for denne hendelsen til signaltilstanden i OnTimer()-funksjonen. Denne synkroniseringsmetoden gjorde det mulig å sikre at de nødvendige handlingene utføres med et spesifisert intervall med en nøyaktighet på opptil et millisekund, som følger av meldingene nedenfor, fanget opp av DebugView-programmet fra debug-versjonen av driveren:

0,00075233 ^^^^^^^^ OnTime ^^^^^^^^

0,00116579 ======== LockInfo ========

0,00118814 ======== ReloadInfo ========

0,99727142 ^^^^^^^^ OnTime ^^^^^^^^

1,00966775 ======== LockInfo ========

1,00968981 ======== ReloadInfo ========

1,99729049 ^^^^^^^^ OnTime ^^^^^^^^

2.05610037 ======== LockInfo ========

2.05632067 ======== ReloadInfo ========

2,99727035 ^^^^^^^^ OnTime ^^^^^^^^

2.99741030 ======== LockInfo ========

2.99743295 ======== ReloadInfo ========

3,99727631 ^^^^^^^^ OnTime ^^^^^^^^

3,99739385 ======== LockInfo ========

3.99741673 ======== ReloadInfo ========

4,99728107 ^^^^^^^^ OnTime ^^^^^^^^

4.99742365 ======== LockInfo ========

4,99744749 ======== ReloadInfo ========

5,99728870 ^^^^^^^^ OnTime ^^^^^^^^

5.99742651 ======== LockInfo ========

5.99744844 ======== ReloadInfo ========

Her er OnTime øyeblikket da OnTimer-timerprosedyren ble lagt inn, LockInfo er øyeblikket da tråden som er ansvarlig for å oppdatere informasjonen våknet, ReloadInfo er øyeblikket da informasjonen faktisk ble oppdatert.

Som det fremgår av avlyttingen er ikke periodisiteten i de to første sekundene på et høyt nivå, men så stabiliserer situasjonen seg og nøyaktigheten forbedres som sagt til ett millisekund.

Etter alle disse handlingene starter endelig timeren:

LARGE_INTEGER dueTime = RtlConvertLongToLargeInteger(0);

BOOLEAN eksisterte = KeSetTimerEx(g_pTimer, dueTime, g_timerPeriod, g_pTimerDpc);

Her er dueTime tiden før det første kallet til OnTime()-prosedyren, og g_timerPeriod er perioden for ytterligere samtaler.

Til slutt, i DriverEntry-prosedyren, vil telleren for brukerklientapplikasjoner som mottok beskrivelsen av denne driveren tilbakestilles: pDeviceExtension->clientCount = 0;

Takket være denne ene variabelen blir det mulig å få tilgang til driveren til flere brukerapplikasjoner samtidig. Den eneste begrensningen for dem er eksklusivitet for tilgang til informasjon om prosesser og deres tråder.

3.1.2 Last ned driver

I denne prosedyren, hvis antallet driverklienter er null, slettes alle objekter som er opprettet for å organisere driften av timeren, mitexen, enhetsobjektet og dets symbolske kobling slettes. Hvis antallet klienter er forskjellig fra null, blir ikke driveren lastet ut, siden det ellers vil forstyrre den normale driften av andre brukerklientapplikasjoner.

3.1.3 DispatchCreate og DispatchClose

Disse funksjonene tar hensyn til antall åpne deskriptorer for en gitt driver mottatt ved hjelp av CreateFile() API-kallet. Siden mange håndtak har blitt åpnet, må det samme nummeret lukkes med CloseHandle() API-kallet. Ellers vil driveren forbli i operativsystemet etter at brukerapplikasjonen er ferdig å kjøre, noe som selvfølgelig er svært uønsket.

3.1.4 DispatchDeviceControl

Denne prosedyren tjener IOCTL-forespørsler fra brukerapplikasjoner sendt av DeviceIoControl() API-kallet. I dette kursprosjektet er samhandling med sjåføren for det meste basert på bruken av dem, hovedfunksjonaliteten til sjåføren er implementert her: hva den var ment for. Derfor er denne prosedyren den mest omfangsrike.

Først, avhengig av den spesifikke IOCTL-forespørselen, oppnås en peker til IRP-stabelcellen til IRP-pakken beregnet på driverenhetsobjektet:

PIO_STACK_LOCATION pIrpStack = IoGetCurrentIrpStackLocation(pIrp);

I driveren som vurderes bruker alle IOCTL-forespørsler en bufret dataoverføringsmetode, siden volumet i alle forespørsler er veldig lite. Denne dataoverføringstilnærmingen tildeler nok minne i systemets ikke-sidebase til å romme den største av inngangs- og utgangsbufferne. Før forespørselen begynner å behandle, kopieres innholdet i inngangsbrukerbufferen til systembufferen, og ved fullføring fra systembufferen - til utgangsbrukerbufferen. Siden det kun brukes én systembuffer for begge brukerbufferne, må du være forsiktig når du behandler data, siden det er en mulighet for at når du skriver, vil det skade uleste inndata og deretter gå tapt for alltid.

Lengdene (i byte) til brukerbufferne, input og output, hentes fra Parameters-feltet i IRP-stabelcellen: henholdsvis Parameters.DeviceIoControl.InputBufferLength og Parameters.DeviceIoControl.OutputBufferLength. Og systembufferadressen trekkes ut fra IRP-pakkehodet: AssociatedIrp.SystemBuffer.

Helgedata: [Nei]

Denne IOCTL-forespørselen brukes til å kontakte sjåføren slik at den svarer på spørsmålet om forespørselsinitiatoren er den eneste klienten som jobber med sjåføren for øyeblikket. Denne forespørselen sendes til sjåføren av hver brukerapplikasjon når den er i ferd med å avslutte. Hvis svaret er ja, forsøker applikasjonen å avslutte driveren, ellers avsluttes den ganske enkelt, i tillit til at det er andre klienter som kjører på driveren og at applikasjonen som avsluttes sist vil ta seg av å losse driveren.

Helgsedata: [Nei]

Den første IOCTL-forespørselen fra denne brukes til brukerapplikasjonen for å beslaglegge systeminformasjon for eksklusiv bruk. Den andre er derfor å frigjøre denne ressursen. De kaller ganske enkelt funksjonene LockInfo() og UnlockInfo() med samme navn, som ble beskrevet tidligere når de snakket om DriverEntry-prosedyren i denne delen.

Helgsedata: struktur med grunnleggende informasjon om prosessen.

Dette paret med IOCTL-forespørsler lar initiativtakeren deres sekvensielt se strukturer som beskriver kjørende prosesser i systemet. Hver av dem kaller henholdsvis ProcessFirst()- og ProcessNext()-funksjonene med samme navn. Den første funksjonen setter pekeren til den første posten, og den andre flytter pekeren til den neste, hvis det er en. Resultatet av å utføre hver av disse funksjonene er en fullført struktur med informasjon om prosessen, hvis slutten av listen ikke nås. I tilfelle slutten av listen likevel nås, blir IRP-pakken likevel merket som vellykket behandlet, men verdien av antall byte som overføres settes til null, noe som lar brukerapplikasjonen gjenkjenne denne situasjonen korrekt og stoppe umiddelbart sender ytterligere IOCTL_PROCESS_NEXT til driveren -requests.

Helgsedata: en struktur med grunnleggende informasjon om tråden.

Som i forrige avsnitt, lar dette paret med IOCTL-forespørsler initiatoren deres sekvensielt se strukturene som beskriver trådene til den valgte prosessen. Logikken for å behandle disse forespørslene ligner på innhenting av informasjon om prosesser.

3.1.4.6 IOCTL_OPEN_THREAD. Inndatadata: tilgangsrettigheter, unik identifikator for måltråden.

Helgsedata: Et håndtak til målstrømmen.

Når denne IOCTL-forespørselen behandles, forsøkes det å åpne et håndtak til en tråd som har den spesifiserte identifikatoren med rettighetene som ble forespurt av brukerklientapplikasjonen.

Helgsedata: [Nei].

Under behandlingen av denne IOCTL-forespørselen blir det gjort et forsøk på å lukke et trådhåndtak som tidligere ble åpnet med en IOCTL_OPEN_THREAD-forespørsel.

3.1.4.7 IOCTL_GET_THREAD_CONTEXT. Inndatadata: maskinvarekontekststruktur, måltrådsbeskrivelse.

Helgsedata: maskinvarekontekststruktur.

Denne IOCTL-forespørselen drar full nytte av DeviceIoControl API-kallet, siden både inngangs- og utgangsbuffere er involvert her. Inndataene er en struktur for maskinvarekonteksten med et initialisert CONTEXT::ContextFlags-felt som indikerer hvilke grupper av maskinvarekontekstregistre som skal returneres i denne strukturen ved vellykket fullføring av forespørselen. Dette prosjektet spør etter hele maskinvarekonteksten.

3.2 Tilpasset applikasjon

Brukerapplikasjonen inkluderer to klasser: CDialog og CDriver. Som navnene antyder, er disse klassene henholdsvis ansvarlige for interaksjon med brukeren gjennom applikasjonsdialogboksen og interaksjon med sjåføren, primært gjennom IOCTL-forespørsler.

Når en brukerapplikasjonsforekomst starter, er det første den gjør å prøve å installere driveren, hvis dette ikke har blitt gjort tidligere av en annen forekomst. Hvis installasjonen forårsaket en feil, får brukeren en tilsvarende melding som angir i tekstform årsaken til at den oppsto, hvis den ble gitt, ellers er koden ganske enkelt angitt. Brukeren kan be om driverinstallasjonen på nytt ved å gi et positivt svar på det tilsvarende programtilbudet. Denne prosedyren vil bli gjentatt til driverinstallasjonen er vellykket eller brukeren nekter å prøve igjen.

Etter dette lastes en rullegardinliste over kjørende prosesser, sortert alfabetisk etter navn, den første prosessen fra listen velges, og trådene vises i den andre rullegardinlisten. Disse listene oppdateres hver gang brukeren ønsker å velge en annen prosess eller tråd fordi de trenger den nyeste informasjonen for å gjøre det.

Denne informasjonen innhentes gjennom driverne, som allerede nevnt, ved å bruke DeviceIoControl API-kallet:

BOOL DeviceIoControl

(HÅNDTER hDevice,

DWORD dwIoControlCode,

LPVOID lpInBuffer, DWORD nInBufferSize,

LPVOID lpOutBuffer, DWORD nOutBufferSize,

LPDWORD lpBytesReturned,

LPOVERLAPPED lpOverlappet);

HANDLE hDevice - en beskrivelse av enheten som forespørselen sendes til;

DWORD dwIoControlCode - IOCTL-forespørselskode;

LPVOID lpInBuffer - inngangsbufferadresse;

DWORD nInBufferSize - inndatabufferlengde;

LPVOID lpOutBuffer - utgangsbufferadresse;

DWORD nOutBufferSize - utgangsbufferlengde;

LPDWORD lpBytesReturned - antall byte overført;

LPOVERLAPPED lpOverlapped er en struktur som kreves ved bruk av asynkron kjøring av spørringer, som ikke finnes i denne applikasjonen.

Bruken av dette API-kallet er fullstendig innkapslet i CDriver-klassen, som implementerer en egen metode for hver forespørsel med et navn som ligner på navnet på IOCTL-forespørselen, som gir en intuitiv forståelse av grensesnittet til denne klassen.

Denne klassen innkapsler også bruken av Service Control Manager (SCM), som brukes til å dynamisk installere, starte, stoppe og fjerne driveren.

4. Teknisk seksjon

4.1 Velge et operativsystem og programmeringsmiljø

Windows ble valgt som operativsystem. Dette skyldes det faktum at DOS-operativsystemet allerede er utdatert av mange grunner (vi har allerede gått bort fra single-tasking operativsystemer), og det er ingen andre operativsystemer for personlige maskiner med et godt grensesnitt som virkelig er bruker- vennlig. Windows er fortsatt det vanligste operativsystemet for PC-er. I tillegg er ulike programvareutviklingsmiljøer designet spesielt for Windows:

Visual C++, Visual Basic, Borland C++ Builder, Delphi og andre.

C++ ble valgt som språk for å skrive brukerprogrammet. C++-språket gir svært rike muligheter for programmerere og er kanskje det mest utbredte i deres miljø. Det er et veldig kraftig operatørspråk. I tillegg gir det tilstrekkelig frihet til å skrive programmer, mens Pascal setter veldig snevre grenser, spesielt i beskrivelsen av variabler og ikke tillater konstruksjon av komplekse operatoruttrykk. C ble valgt som språk for å skrive driveren. Bruken av dette språket sikrer portabilitet mellom systemene: det maksimale som må gjøres er å bygge om driveren. Microsoft Visual Studio .Net ble valgt som utviklingsmiljø, siden det gir kraftige og praktiske verktøy ikke bare for visuell utvikling av programvareproduktgrensesnittet, men også for å sette opp prosjekter, som lar deg organisere arbeidsplassen din effektivt.

4.2 Grensesnitt

Slik ser vinduet til en tilpasset Profiler-applikasjonsforekomst ut:

Øverst i dialogen er det to rullegardinlister, den øverste viser en liste over kjørende prosesser i systemet, og den nederste - en liste over tråder i denne prosessen. Disse kontrollene kan brukes til å fortelle en applikasjon hvilken prosess og hvilken tråd i den prosessen som skal overvåkes.

Det er tre grupper i dialogen:

Gruppe "Prosessinformasjon":

ProcessID - prosessidentifikator;

ParentID - identifikator for den overordnede prosessen;

BasePriority - standard grunnprioritet for prosesstråder;

ThreadCount - antall prosesstråder;

KernelTime - total tid brukt i kjernemodus av prosesstråder, 1 enhet tilsvarer 100 ns;

UserTime - den totale tiden brukt i brukermodus av prosesstråder, 1 enhet er lik 100 ns.

"Strøminformasjon"-gruppe:

ThreadID - trådidentifikator;

BasePriority - basisprioritet for tråden;

Prioritet - trådprioritet;

ContextSwitches - antall kontekstbytter utført av tråden;

KernelTime - tid brukt i kjernemodus (1 enhet tilsvarer 100 ns);

UserTime - tid brukt i brukermodus (1 enhet tilsvarer 100 ns).

WaitTime - tidspunktet da tråden gikk inn i ventetilstand (teller fra det øyeblikket systemet starter).

Trådkontekstgruppe:

Dette representerer trådens maskinvarekontekst. De fleste applikasjoner forventer input fra brukeren. Når du overvåker trådene i en slik prosess, kan det hende du ikke ser noen endringer i det hele tatt. Derfor, for en mer visuell oversikt, er det verdt å kjøre oppgaver som krever store beregningskostnader. For eksempel WinAmp, som du kan spille musikk med - tråden som er ansvarlig for dette er umiddelbart synlig ved å endre generelle registre. Men de hyppigste endringene i registre for ulike formål skjer i virkelig "tunge" oppgaver, for eksempel kan du ta et kursprosjekt om datagrafikk.

4.3 Systemkrav

Driveren er skrevet for Windows NT versjon 5.x.

Behandling av forespørsler fra flere brukerklientapplikasjoner er kun testet på Windows XP Service Pack 2.

Konklusjon

Som et resultat av arbeidet med prosjektet ble det implementert en tilpasset applikasjon som samhandler med Legacy-driveren. Med sin hjelp får den grunnleggende informasjon om den valgte prosessen, den grunnleggende informasjonen og maskinvarekonteksten til den valgte tråden til den spesifiserte prosessen. Denne applikasjonen er grunnlaget for å implementere fullverdige applikasjonsprofiler for å spore målapplikasjoner og oppdage flaskehalser i dem, noe som kan øke effektiviteten til programmereren og programvaren han utvikler betydelig.

Liste over brukt litteratur

1. V.P. Soldatov "Windows-driverprogrammering." Ed. 3., revidert og tillegg - M.: Binom-Press LLC, 2006 - 576 s.: ill.

2. M. Russinovich, D. Solomon "Microsoft Windows Internals: Windows Server 2003, Windows XP and Windows 2000", 4. utgave.

3. J. Richter "Windows for profesjonelle: lage effektive Win32-applikasjoner som tar hensyn til spesifikasjonene til 64-biters versjonen av Windows" / Oversatt, engelsk - 4. utgave. - St. Petersburg; Peter; M.: Forlags- og handelshuset "Russian Edition", 2001.

4. Schreiber, Sven B., 1958-Udokumenterte Windows 2000-hemmeligheter: en programmerers kokebok.

5. Garry Nebbett, Windows NT/2000 Native API.

Lignende dokumenter

    De viktigste fordelene med modulær programmering. Valg av prosedyre: legge inn en matrise fra konsollen, vise matrisen, informasjon om forfatteren og tilstanden til det løste problemet før behandling og etter behandling. Hierarki av prosedyrer, kjennetegn ved hensikten med moduler.

    abstrakt, lagt til 29.01.2016

    Studie av konseptet, vektorer og mekanismer for avbruddshåndtering; deres klassifisering avhengig av opprinnelseskilden. Funksjoner av responsen til maskinvare- og programvaredelene av operativsystemet på signaler om forekomsten av en hendelse på datamaskinen.

    sammendrag, lagt til 22.06.2011

    Analyse av eksisterende teknologier for å lage webapplikasjoner. Utvikling av nettverksteknologi for publisering og behandling av informasjon om barn i barnehage nr. 176 "Belochka" ved bruk av JSP-sider og servlets ved hjelp av en JDBC-driver for å få tilgang til databasen.

    kursarbeid, lagt til 18.12.2011

    Utvikling av et datalagrings- og prosesseringssystem, grensesnitt. Bruk av Xamarin.Forms-teknologi for å organisere utfylling av fraktsedler. Velge et operativsystem, språk og programmeringsmiljø. Maskinvareintegrasjon av informasjonssystemet.

    avhandling, lagt til 07.09.2017

    Prinsipper og algoritmer for avbruddsbehandling. Et sett med handlinger for å implementere prosesseringstrinn for avbrudd i mikroprosessoren. Utvikling av strukturen og algoritmen til beboerprogrammet. Implementering av et program i Assembly-språk, metoder for feilsøking og testing.

    kursarbeid, lagt til 22.12.2014

    Et eksempel på å bygge et program ved hjelp av aritmetiske operatorer. Grunnleggende verktøy for å lage en kalkulator. Fremgangsmåte for å legge inn tall. Endret prosedyre for behandling ved å trykke på "+"-knappen. Prosedyren for å åpne hjelpeskjemaet, det endelige resultatet.

    presentasjon, lagt til 03.02.2012

    Utforming av en avbruddshåndteringsmekanisme. Intel 82C59A avbruddskontroller. Avbryt I/O. Intel 82C55A programmerbar grensesnittkontroller. Prosessorens rolle i håndtering av I/O-avbrudd. Oversikt over avbruddshåndteringsalgoritmen.

    test, lagt til 19.05.2010

    Sammenligning av resultatene av simuleringsmodellering og analytisk beregning av egenskaper. Studie av datapakkesvitsjingsnoden, pakkebehandling i prosessoren, buffering og overføring langs utgangslinjen. Bestemmelse av prosessorbelastningsfaktor.

    kursarbeid, lagt til 29.06.2011

    Krav og struktur for økonomiske informasjonsbehandlingssystemer. Informasjonsbehandlingsteknologi og systemvedlikehold, informasjonsbeskyttelse. Prosessen med å lage spørringer, skjemaer, rapporter, makroer og moduler. Verktøy for å organisere databaser og arbeide med dem.

    kursarbeid, lagt til 25.04.2012

    Grunnleggende teknikker for å jobbe i programmeringsmiljøet Delphi. Funksjoner av teknologien for å lage enkle applikasjoner. Arbeide med applikasjonsutviklingsmiljøkomponenter. Inntasting, redigering, valg og utdata av informasjon. Aspekter ved bruk av forgreningsstruktur.

Mens kjernemoduskoden som har høyest prioritet kjører, kan ingen annen kode kjøres på den prosessoren. Selvfølgelig, hvis for mye kode kjøres med for høye IRQL-verdier, vil dette uunngåelig føre til generell systemforringelse.

For å løse denne typen problemer, må kode som skal kjøres i kjernemodus være utformet for å unngå å kjøre på forhøyede IRQL-nivåer i lengre perioder. En av de viktigste komponentene i denne strategien er Deferred Procedure Calls (DPC) – utsatte prosedyreanrop.

Funksjon av DPC

Ordningen for bruk av utsatte prosedyreanrop lar deg bygge utførelsesprosessen på en slik måte at oppgaven kan planlagt kode som kjører på et høyt IRQL-nivå, men det har den ikke ennå utført . Denne utsettelsen av utførelse er nyttig når et avbrudd betjenes i driveren og det ikke er noen grunn til å blokkere utførelse av annen kode på et lavere IRQL-nivå. Med andre ord når behandlingen av en gitt situasjon smertefritt kan utsettes til et senere tidspunkt.

For å registrere forespørsler om å kalle DPC-prosedyrer, opprettholder operativsystemet en kø med DPC-objekter.

Til å begynne med vil vi begrense oss til å vurdere et enklere tilfelle av arbeid med DPC-prosedyrer beregnet for bruk i forbindelse med avbruddshåndteringsprosedyrer. Denne typen DPC-prosedyrer fikk det spesielle navnet DpcForIsr i litteraturen.

Et DPC-objekt for bruk i avbruddsrutiner opprettes ved å ringe IoInitializeDpcRequest, vanligvis utført i oppstartsprosedyrene for driveren. Denne samtalen registrerer prosedyren som tilbys av DpcForIsr-driveren og assosierer den med objektet som opprettes - en ganske vanlig teknikk i Windows. Det bør spesielt bemerkes at DPC-objektet opprettet av denne samtalen vil forbli i dypet av operativsystemet, utilgjengelig for driverutvikleren. (Forskjellen mellom DpcForIsr og andre DPC-prosedyrer er bare at sistnevnte arbeides med ved bruk av anrop Ke...Dpc, og DPC-objektene som er opprettet for dem, er tilgjengelige for driverutvikleren.)

Hvis sjåføren har registrert sin DpcForIsr-prosedyre, mens ISR-avbruddet behandles av prosedyren, kan det tilsvarende DPC-objektet plasseres i systemets DPC-kø (faktisk en forespørsel om å kalle denne DpcForIsr-prosedyren senere) - ved å bruke kallet IoRequestDpc. DpcForIsr-prosedyren vil senere fullføre behandlingen av den mottatte ISR ved forespørselsprosedyren, som vil bli utført under mindre kritiske forhold og på et lavt IRQL-nivå.

Generelt sett består funksjonen til DPC-prosedyrer (i dette tilfellet DpcForIsr) av følgende operasjoner:

  • Når et stykke kode som kjører på en høy (maskinvare) IRQL ønsker å planlegge at deler av arbeidet skal utføres ved en lav IRQL, legger det til et DPC-objekt til systemets utsatte prosedyreanropskø.
  • Før eller senere synker prosessorens IRQL-verdi under DISPATCH_LEVEL, og arbeidet som ble forsinket av avbruddet betjenes av DPC-funksjonen. DPC-manageren henter hvert DPC-objekt fra køen og kaller den tilsvarende funksjonen, en peker som er lagret i det objektet. Denne funksjonen kalles opp mens prosessoren kjører på DISPATCH_LEVEL.

Funksjoner av DPC-mekanismen

Generelt er det ikke vanskelig å jobbe med utsatte prosedyrekall, siden Windows 2000/XP/Server 2003-operativsystemene tilbyr et stort sett med systemanrop som skjuler de fleste detaljene i denne prosessen. Imidlertid bør to av de mest villedende aspektene ved å jobbe med DPC fremheves.

For det første pålegger Windows NT 5 en begrensning på at én forekomst av et DPC-objekt kan plasseres på systemets DPC-kø på et gitt tidspunkt. Forsøk på å sette et objekt inn i DPC-køen som samsvarer nøyaktig med en som allerede er der, blir avvist. Som et resultat oppstår bare ett DPC-prosedyrekall, selv om sjåføren venter på at to anrop skal foretas. Dette kan skje hvis to avbrudd ble forårsaket av en betjent enhet og behandlingen av det første utsatte prosedyrekallet ennå ikke har begynt. Den første forekomsten av DPC-objektet er fortsatt i køen, mens driveren allerede har begynt å behandle det andre avbruddet.

Driverdesignet må sørge for et slikt operasjonsforløp for DPC-mekanismen. Kanskje en ekstra DPC-forespørselteller bør gis, eller driveren kan implementere sin egen forespørselskøimplementering. Mens den faktiske utsatte prosedyren utføres, kan du sjekke telleren og dens egen forespørselskø for å finne ut hvilket spesifikt arbeid som skal gjøres.

For det andre er det betydelige synkroniseringsproblemer når du kjører på multiprosessorplattformer. Anta at kode som kjører på en enkelt prosessor utfører avbruddstjeneste og planlegger et DPC-prosedyrekall (plasserer et DPC-objekt i systemkøen). Men før avbruddet er fullstendig behandlet, kan en annen prosessor begynne DPC-behandling av et objekt plassert i systemkøen. Det oppstår således en situasjon hvor avbruddstjenestekoden utføres parallelt og samtidig med DPC-prosedyrekoden. Av denne grunn er det nødvendig å tilveiebringe tiltak for pålitelig å synkronisere tilgangen til DPC-prosedyreprogramkoden til ressurser som deles med sjåføravbruddsservicerutinen.

Hvis du ser nærmere på listen over anropsparametere IoInitializeDpcRequest Og IoRequestDpc(ment å fungere med DpcForIsr-prosedyrer), så er det lett å legge merke til at DPC-objektet er "bundet" til enhetsobjektet. Når du plasserer dette objektet i DPC-køen på det tidspunktet ISR-prosedyren kjører, spesifiseres også enhetsobjektet. Dette sikrer sikkerhet med hensyn til hvilket spesifikt DPC-prosedyrekall som er "bestilt" av ISR-prosedyren (korrelasjon etter enhetsobjekt). Dette betyr også at en driver som har laget flere enhetsobjekter (et ganske sjeldent tilfelle) også kan bruke flere DpcForIsr-prosedyrer – en for hvert enhetsobjekt.

Systemets DPC-mekanisme forhindrer samtidig behandling av DPC-objekter fra systemkøen, selv i en multiprosessorkonfigurasjon. Derfor, hvis ressurser deles av flere utsatte prosedyrer, er det ingen grunn til å bekymre deg for å synkronisere tilgangen til dem.

Ovenfor diskuterte vi bruken av DPC-prosedyrer for å fullføre avbruddsbehandling, det vil si DpcForIsr. Imidlertid kan DPC-prosedyrer brukes på andre måter, for eksempel i forbindelse med tidtakere for å organisere venting. For å gjøre dette, lag et DPC-objekt ved å ringe KeInitializeDPC, som knytter dette objektet til DPC-prosedyren inkludert i driveren. Du kan deretter stille inn tidsavbruddet i den forhåndsinitialiserte (ved å bruke KeInitializeTimer eller KeInitializeEx) timerobjekt. Anrop brukes til å stille inn venteintervallet KeSetTimer, som må sendes en peker til et initialisert DPC-objekt som en av parameterne. Når DPC-tidsavbruddet utløper, vil objektet bli lagt til systemets DPC-kø og DPC-prosedyren knyttet til det vil bli kalt opp så snart som mulig. DPC-prosedyrer av denne andre typen er betegnet i DDK-dokumentasjonen med begrepet "Custom DPC". (Denne bruken av DPC-prosedyrer gjør at de ligner APC-anrop i brukermodus.)

For å plassere objekter som tilsvarer den andre typen DPC-prosedyrer (ikke relatert til avbrudd) i systemets DPC-kø, bruk kallet KeInsertQueueDpc. Følgelig må anropsinitieringskoden operere på et IRQL-nivå som ikke er lavere enn DISPATCH_LEVEL.

For å fjerne system-DPC-køen fra egendefinerte DPC-prosedyrer, for eksempel hvis driveren må slå seg av umiddelbart, ring KeRemoveQueueDpc, som kan kalles fra kode på alle IRQL-nivåer.