Linux vs Windows-enhedsdrivermodel: arkitektur, API'er og miljøsammenligning

Enhedsdrivere er dele af operativsystemet, der letter brug af hardwareenheder via visse programmeringsinterfaces, så softwareprogrammer kan kontrollere og betjene enhederne. Da hver driver er specifik for et bestemt operativsystem, skal du bruge separate Linux-, Windows- eller Unix-enhedsdrivere til at muliggøre brugen af ​​din enhed på forskellige computere. Derfor er det vigtigt, at når man ansætter en chaufførudvikler eller vælger en R & D-udbyder, er det vigtigt at se på deres erfaring med at udvikle drivere til forskellige operativsystemplatforme.

Det første skridt i driverudvikling er at forstå forskellene i, hvordan hvert operativsystem håndterer dets drivere, den underliggende drivermodel og den arkitektur, den anvender, samt tilgængelige udviklingsværktøjer. For eksempel er Linux-drivermodellen meget forskellig fra Windows. Mens Windows letter adskillelse af driverudvikling og OS-udvikling og kombinerer drivere og operativsystem via et sæt af ABI-opkald, er Linux-enhedsdriverudvikling ikke afhængig af stabile ABI'er eller API'er, idet førerkoden i stedet indgår i kernen. Hver af disse modeller har sit eget sæt fordele og ulemper, men det er vigtigt at kende dem alle, hvis du vil give en omfattende support til din enhed.

I denne artikel vil vi sammenligne Windows- og Linux-enhedsdrivere og undersøge forskellene med hensyn til deres arkitektur, API'er, udvikling og distribution, i håb om at give dig et indblik i, hvordan man begynder at skrive enhedsdrivere til hvert af disse operativsystemer .

1. Enhedsdriverarkitektur

Windows-enhedsdriverarkitektur er forskellig fra den, der bruges i Linux-drivere, hvor en af ​​dem har deres egne fordele og ulemper. Forskelle er hovedsageligt påvirket af, at Windows er et lukket kilde OS, mens Linux er open source. Sammenligning af Linux- og Windows-enhedsdriverarkitekturerne hjælper os med at forstå kerneforskellene bag Windows og Linux-drivere.

1.1. Windows driver arkitektur

Mens Linux-kerne distribueres med drivere selv, indeholder Windows-kerne ikke enhedsdrivere. I stedet skrives moderne Windows-enhedsdrivere ved hjælp af Windows Driver Model (WDM), der fuldt ud understøtter plug-and-play og strømstyring, så driverne kan indlæses og losses efter behov.

Anmodninger fra applikationer håndteres af en del af Windows-kernen kaldet IO-manager, som omdanner dem til IO Request Packets (IRP'er), som bruges til at identificere anmodningen og formidle data mellem driverlag.

WDM giver tre typer af drivere, som danner tre lag:

  • Filterdrivere giver valgfri yderligere behandling af IRP'er.
  • Funktionsdrivere er de vigtigste drivere, der implementerer grænseflader til individuelle enheder.
  • Buschauffører servicerer forskellige adaptere og buscontrollere, som værtsenheder.

En IRP passerer disse lag, da den rejser fra IO-manager ned til hardware. Hvert lag kan håndtere en IRP alene og sende den tilbage til IO-manager. Nederst er der Hardware Abstraction Layer (HAL), som giver en fælles grænseflade til fysiske enheder.

1.2. Linux driver arkitektur

Kerneforskellen i Linux-enhedsdriverarkitektur i forhold til Windows er, at Linux ikke har en standarddrivermodel eller en ren adskillelse i lag. Hver enhedsdriver implementeres som regel som et modul, der kan indlæses og losses i kernen dynamisk. Linux giver mulighed for plug-and-play-support og strømstyring, så drivere kan bruge dem til at styre enheder korrekt, men det er ikke et krav.

Moduler eksportfunktioner, de leverer og kommunikerer ved at kalde disse funktioner og passerer rundt vilkårlig datastrukturer. Anmodninger fra brugerprogrammer kommer fra filsystem eller netværksniveau, og konverteres til datastrukturer efter behov. Moduler kan stables i lag, behandler anmodninger efter hinanden, med nogle moduler, der giver en fælles grænseflade til en enhedsfamilie, såsom USB-enheder.

Linux-enhedsdrivere understøtter tre typer enheder:

  • Tegn enheder, der implementerer en byte stream interface.
  • Bloker enheder, der er vært for filsystemer og udfør IO med multibyte-blokke af data.
  • Netværksgrænseflader, der bruges til at overføre datapakker via netværket.

Linux har også et hardware abstraktionslag, der fungerer som en grænseflade til den aktuelle hardware til enhedsdrivere.

2. Enhedsdriver-API'er

Begge Linux- og Windows-driver-API'er er begivenhedsdrevne: Driverkode kører kun, når der sker en begivenhed: enten når brugerprogrammerne ønsker noget fra enheden, eller når enheden har noget at fortælle til operativsystemet.

2.1. Initialisering

På Windows er drivere repræsenteret af en DriverObject-struktur, der initialiseres under udførelsen af ​​DriverEntry-funktionen. Dette indgangspunkt registrerer også en række tilbagekaldelser for at reagere på enhedsaddition og fjernelse, chaufførlæsning og håndtering af de indgående IRP'er. Windows opretter et enhedsobjekt, når en enhed er tilsluttet, og dette enhedsobjekt håndterer alle ansøgningsanmodninger på enhedsdriverens vegne.

I sammenligning med Windows styres Linux-enhedsdriverens levetid af kernelmodulets module_init og module_exit-funktioner, som kaldes, når modulet er indlæst eller losset. De er ansvarlige for at registrere modulet til håndtering af enhedsforespørgsler ved hjælp af interne kernelgrænseflader. Modulet skal oprette en enhedsfil (eller en netværksgrænseflade), angive en numerisk identifikator for den enhed, som den ønsker at styre, og registrere et antal tilbagekaldelser, der skal kaldes, når brugeren interagerer med enhedsfilen.

2.2. Navngivning og hævning af enheder

Registrering af enheder på Windows

Windows-enhedsdriver meddeles om nytilsluttede enheder i sin AddDevice-tilbagekald. Det fortsætter derefter med at oprette et enhedsobjekt, der bruges til at identificere denne særlige driverinstans for enheden. Afhængigt af driverens art kan enhedens objekt være et fysisk enhedsobjekt (PDO), Function Device Object (FDO) eller et Filter Device Object (FIDO). Enhedsobjekter kan stables med en BOB i bunden.

Enhedsobjekter eksisterer hele tiden, hvor enheden er tilsluttet computeren. DeviceExtension struktur kan bruges til at forbinde globale data med en enhedsobjekt.

Enhedsobjekter kan have navne på formularen DeviceDeviceName, som bruges af systemet til at identificere og lokalisere dem. En applikation åbner en fil med et sådant navn ved hjælp af CreateFile API-funktionen, hvorved man får et håndtag, som derefter kan bruges til at interagere med enheden.

Normalt har dog kun PDO'er forskellige navne. Unavngivne enheder kan fås via enhedsklassens grænseflader. Enhedsdriveren registrerer en eller flere grænseflader identificeret af 128-bit globalt unikke identifikatorer (GUID'er). Brugerapplikationer kan derefter få et håndtag til en sådan enhed ved hjælp af kendte GUID'er.

Registrering af enheder på Linux

På Linux-brugerapplikationer får du adgang til enhederne via filsystemposter, som normalt findes i / dev-mappen. Modulet opretter alle nødvendige indgange under modulinitialisering ved at kalde kernelfunktioner som register_chrdev. En applikation udsender et åbent systemopkald for at få en filbeskrivelse, som derefter bruges til at interagere med enheden. Dette opkald (og yderligere systemopkald med den returnerede deskriptor som læsning, skrivning eller lukning) sendes derefter til tilbagekaldsfunktioner installeret af modulet i strukturer som file_operations eller block_device_operations.

Enhedsdrivermodulet er ansvarlig for allokering og vedligeholdelse af eventuelle datastrukturer, der er nødvendige for dets drift. En filstruktur, der er sendt ind i filsystemet tilbagekaldelser, har et privat_data felt, som kan bruges til at lagre en pointer til driverspecifikke data. API'erne til blok enhed og netværksinterface giver også tilsvarende felter.

Mens applikationer bruger filsystemknudepunkter til at lokalisere enheder, bruger Linux et koncept af større og mindre tal at identificere enheder og deres chauffører internt. EN hovednummer bruges til at identificere enhedsdrivere, mens a mindre nummer bruges af føreren til at identificere enheder, der forvaltes af den. Føreren skal registrere sig selv for at kunne administrere et eller flere faste hovednumre eller bede systemet om at tildele noget ubrugt nummer til det.

I øjeblikket bruger Linux 32-bitværdier for store mindre par, med 12-bits tildelt til hovednummeret, der giver op til 4096-klare drivere. De store mindre par er forskellige for tegn og blokke enheder, så en tegn enhed og en blok enhed kan bruge det samme par uden konflikter. Netværksgrænseflader er identificeret med symboliske navne som eth0, som igen er adskilte fra store og mindre antal både tegn og blok enheder.

2.3. Udveksling af data

Både Linux og Windows understøtter tre måder at overføre data mellem applikationer på brugerniveau og driverne på kerneliveau:

  • Buffered Input-Output, der bruger buffere styret af kernen. Til skriveoperationer kopierer kernen data fra en buffer til brugerrummet i en kernefordelingsbuffer og sender den til enhedsdriveren. Læsninger er de samme, med kernekopieringsdata fra en kernelbuffer til bufferen, der leveres af applikationen.
  • Direct Input-Output, som ikke indebærer kopiering. I stedet peger kernen på en brugerallokeret buffer i fysisk hukommelse, så den forbliver der uden at blive byttet ud, mens dataoverførsel pågår.
  • Hukommelse kortlægning kan også arrangeres af kernen, så kerne- og brugerrumsapplikationerne kan få adgang til de samme sider med hukommelse ved hjælp af forskellige adresser.

Driver IO tilstande på Windows

Støtte til Buffered IO er et indbygget træk ved WDM. Bufferen er tilgængelig for enhedsdriveren via feltet AssociatedIrp.SystemBuffer i IRP-strukturen. Føreren læser simpelthen fra eller skriver til denne buffer, når den skal kommunikere med brugerrummet.

Direkte IO på Windows er formidlet af hukommelsesbeskrivelseslister (MDI). Disse er semi-uigennemsigtige strukturer, der er tilgængelige via IRD's MdlAddress-felt. De bruges til at lokalisere den fysiske adresse på bufferen tildelt af brugerapplikationen og fastgøres i løbet af IO-anmodningen.

Den tredje mulighed for dataoverførsel på Windows hedder METHOD_NEITHER. I dette tilfælde passerer kernen simpelthen de virtuelle adresser til brugerrumsindgangs- og outputbuffere til føreren uden at validere dem eller sikre, at de kortlægges i fysisk hukommelse, der er tilgængelig af enhedsdriveren. Enhedsdriveren er ansvarlig for håndtering af dataoverførslen.

Driver IO tilstande på Linux

Linux giver en række funktioner som clear_user, copy_to_user, strncpy_from_user og nogle andre til at udføre bufferede dataoverførsler mellem kernen og brugerhukommelsen. Disse funktioner validerer pointers til databuffere og håndterer alle detaljer i dataoverførslen ved sikkert at kopiere databufferen mellem hukommelsesområder.

Imidlertid opererer drivere til blokindretninger på hele datablokke af kendt størrelse, som simpelthen kan flyttes mellem kerne- og brugeradresserum uden at kopiere dem. Denne sag håndteres automatisk af Linux-kerne for alle blokdrivere. Blokforespørgselskøen tager sig af at overføre datablokke uden overskydende kopiering, og Linux-systemopkaldsgrænsefladen tager sig af at konvertere filsystemanmodninger til blokanmodninger.

Endelig kan enhedsdriveren tildele nogle hukommelsessider fra kerneadresserummet (som ikke kan byttes) og derefter bruge funktionen remap_pfn_range til at kortlægge siderne direkte i adresserummet for brugerprocessen. Ansøgningen kan derefter få den virtuelle adresse på denne buffer og bruge den til at kommunikere med enhedsdriveren.

3. Enhedsdriverudviklingsmiljø

3.1. Enhedsdriverrammer

Windows Driver Kit

Windows er et lukket kilde operativsystem. Microsoft giver en Windows Driver Kit at lette Windows-enhedsdriverudvikling af ikke-Microsoft-leverandører. Pakken indeholder alt, hvad der er nødvendigt for at opbygge, debugge, verificere og pakke enhedsdrivere til Windows.

Windows Driver Model definerer en ren grænseflade ramme for enhedsdrivere. Windows opretholder kilde og binære kompatibilitet af disse grænseflader. Kompilerede WDM-drivere er generelt forenelige med hinanden: det vil sige, at en ældre driver kan køre på et nyere system, som det er uden at blive kompileret igen, men det vil selvfølgelig ikke have adgang til de nye funktioner, der leveres af operativsystemet. Imidlertid er chaufførerne ikke garanteret at være bagudkompatible.

Linux kildekode

I sammenligning med Windows er Linux et open source-operativsystem, og hele kildekoden til Linux er SDK'en til driverudvikling. Der findes ingen formelle rammer for enhedsdrivere, men Linux-kernen indeholder talrige delsystemer, der leverer fælles tjenester som driverregistrering. Grænsefladerne til disse delsystemer er beskrevet i kernel header-filer.

Mens Linux har definerede grænseflader, er disse grænseflader ikke stabile ved design. Linux giver ingen garantier for kompatibilitet fremad eller bagud. Enhedsdrivere skal omkompileres til at arbejde sammen med forskellige kernelversioner. Ingen stabilitetsgarantier tillader hurtig udvikling af Linux-kernen, da udviklere ikke behøver at understøtte ældre grænseflader og kan bruge den bedste fremgangsmåde til at løse de problemer, der er til stede.

Et sådant skiftende miljø udgør ikke nogen problemer, når du skriver i-tree drivere til Linux, da de er en del af kernekilden, fordi de opdateres sammen med kernen selv. Afspillede drivere skal dog udvikles separat, ud-af-træ, og de skal opretholdes for at understøtte forskellige kernelversioner. Således opfordrer Linux enhedsdriverudviklere til at opretholde deres drivere i-tree.

3.2. Byg system til enhedsdrivere

Windows Driver Kit tilføjer understøttelse af driverudvikling til Microsoft Visual Studio, og indeholder en compiler, der bruges til at opbygge driverkoden. Udvikling af Windows-enhedsdrivere er ikke meget forskellig fra at udvikle et brugerrumsapplikation i en IDE. Microsoft giver også en Enterprise Windows Driver Kit, hvilket gør det muligt at kommandolinjebyggende miljø ligner Linux.

Linux bruger Makefiles som et build system til både in-tree og out-of-tree enhedsdrivere. Linux build system er ret udviklet og normalt en enhedsdriver har brug for ikke mere end en håndfuld linjer til at producere en fungerende binær. Udviklere kan bruge nogen IDE så længe det kan klare Linux kildekode base og køre make, eller de kan nemt kompilere drivere manuelt fra terminal.

3.3. Dokumentationssupport

Windows har fremragende dokumentationsstøtte til driverudvikling. Windows Driver Kit indeholder dokumentation og sample driver kode, rigelig information om kernel grænseflader er tilgængelig via MSDN, og der findes talrige reference og vejledning bøger om driver udvikling og Windows internals.

Linux-dokumentation er ikke så beskrivende, men dette lindres med, at hele kildekoden til Linux er tilgængelig for driverens udviklere. Det Dokumentation bibliotek i kildetræet dokumenterer nogle af Linux-delsystemerne, men der er flere bøger om Linux-enhedsdriverudvikling og Linux-kerneloversigter, som er meget mere udførlige.

Linux giver ikke udpegede prøver af enhedsdrivere, men kildekoden for eksisterende produktionsk drivere er tilgængelig og kan bruges som reference til udvikling af nye enhedsdrivere.

3.4. Debugging support

Både Linux og Windows har logfiler, der kan bruges til at spore debug driver kode. På Windows ville man bruge DbgPrint-funktionen til dette, mens i Linux kaldes funktionen printk. Men ikke alle problemer kan løses ved at bruge kun logning og kildekode. Nogle gange er breakpoints mere nyttige, da de tillader at undersøge den dynamiske opførsel af førerkoden. Interaktiv fejlfinding er også vigtig for at studere årsagerne til nedbrud.

Windows understøtter interaktiv fejlsøgning via dens kerneliveau debugger WinDbg. Dette kræver to maskiner forbundet via en seriel port: en computer til at køre den fejlsøgte kerne, og en anden til at køre debuggeren og styre operativsystemet, der debugges. Windows Driver Kit indeholder fejlfindingssymboler til Windows-kernen, så Windows-datastrukturer vil være delvist synlige i debuggeren.

Linux understøtter også interaktiv fejlfinding ved hjælp af KDB og KGDB. Debugging support kan indbygges i kernen og aktiveres ved opstartstid. Derefter kan man enten debugere systemet direkte via et fysisk tastatur eller tilslutte det fra en anden maskine via en seriel port. KDB tilbyder en enkel kommandolinjegrænseflade, og det er den eneste måde at debugere kernen på den samme maskine. KDB mangler imidlertid debugging support på kildeniveau. KGDB giver en mere kompleks grænseflade via en seriel port. Det gør det muligt at bruge standardprogram debuggere som GDB til debugging Linux-kerne ligesom enhver anden userpace applikation.

4. Distribuere enhedsdrivere

4.1. Installation af enhedsdrivere

I Windows-installerede drivere beskrives tekstfiler, der hedder INF-filer, som typisk gemmes i C: WindowsINF-mappen. Disse filer leveres af chaufførleverandøren og definerer, hvilke enheder der betjenes af chaufføren, hvor du finder driverbinarierne, driverens version osv.

Når en ny enhed er tilsluttet computeren, ser Windows dog ud
installerede drivere og indlæser en passende en. Føreren aflastes automatisk, så snart enheden er fjernet.

På Linux er nogle drivere indbygget i kernen og forbliver permanent indlæst. Ikke-væsentlige er bygget som kernemoduler, som normalt gemmes i / lib / modules / kernel-version biblioteket. Denne mappe indeholder også forskellige konfigurationsfiler, ligesom moduler. Beskriver om afhængigheder mellem kernemoduler.

Mens Linux-kernen kan indlæse nogle af modulerne ved opstartstid, er generelt modulindlæsningen overvåget af brugerrumsapplikationer. For eksempel kan init-processen indlæse nogle moduler under systeminitialisering, og udev daemonen er ansvarlig for sporing af de nyligt tilsluttede enheder og indlæsning af passende moduler for dem.

4.2. Opdatering af enhedsdrivere

Windows giver en stabil binær grænseflade til enhedsdrivere, så i nogle tilfælde er det ikke nødvendigt at opdatere driverbinarier sammen med systemet. Eventuelle nødvendige opdateringer håndteres af Windows Update-tjenesten, som er ansvarlig for at lokalisere, downloade og installere up-to-date versioner af drivere, der er relevante for systemet.

Linux leverer imidlertid ikke en stabil binær grænseflade, så det er nødvendigt at genopbygge og opdatere alle nødvendige enhedsdrivere med hver kerneopdatering. Selvfølgelig opdateres enhedsdrivere, der er indbygget i kernen, automatisk, men ud af træmoduler udgør et lille problem. Opgaven med at opretholde up-to-date modul binaries er normalt løst med DKMS: En tjeneste, som automatisk genopbygger alle registrerede kernemoduler, når en ny kerneversion er installeret.

4.3. Sikkerhedshensyn

Alle Windows-enhedsdrivere skal underskrives digitalt, før Windows indlæser dem. Det er okay at bruge selvsignerede certifikater under udvikling, men driverpakker distribueret til slutbrugere skal underskrives med gyldige certifikater, der er betroet af Microsoft. Sælgere kan få en Software Publisher Certificate fra enhver autoriseret certificeringsmyndighed, der er autoriseret af Microsoft. Dette certifikat er derefter krydsattegnet af Microsoft, og det resulterende krydscertifikat bruges til at underskrive driverpakker inden udgivelsen.

Linux-kerne kan også konfigureres til at bekræfte underskrifter af kernemoduler, der indlæses og forbyde usikrede. Sættet af offentlige nøgler, der er tillid til kernen, er fastsat på byggetiden og kan konfigureres fuldt ud. Strenge kontroller udført af kernen kan også konfigureres på byggetid og spænder fra simpelthen udstedelse af advarsler for usikrede moduler til at nægte at indlæse noget med tvivlsom gyldighed.

5. konklusion

Som vist ovenfor har Windows og Linux-enhedsdriverinfrastruktur nogle ting til fælles, som f.eks. Tilgang til API, men mange flere detaljer er ret forskellige. De mest fremtrædende forskelle skyldes, at Windows er et lukket kilde operativsystem udviklet af et kommercielt selskab. Dette gør, hvad der gør god, dokumenteret, stabil driver ABI og formelle rammer et krav til Windows, mens det på Linux ville være mere en god tilføjelse til kildekoden. Dokumentationssupport er også meget mere udviklet i Windows-miljøet, da Microsoft har ressourcer, der er nødvendige for at opretholde det.

På den anden side begrænser Linux ikke udviklere af enhedsdrivere med rammer og kildekoden til kernen, og produktionsdrivere kan være lige så nyttige i de rigtige hænder. Manglen på grænsefladestabilitet har også konsekvenser, da det betyder, at up-to-date enhedsdrivere altid bruger de nyeste grænseflader, og kernen selv bærer mindre byrde af bagudkompatibilitet, hvilket resulterer i endnu renere kode.

At kende disse forskelle samt specifikationer for hvert system er et afgørende første skridt i at levere effektiv driverudvikling og support til dine enheder. Vi håber, at denne Windows og Linux-enhedsdriverudviklingssammenligning var nyttig til at forstå dem, og vil tjene som et godt udgangspunkt i din undersøgelse af enhedsdriverudviklingsprocessen.

Kilde

Giv en kommentar

Dette websted bruger Akismet til at reducere spam. Lær, hvordan dine kommentardata behandles.