Hvorfor bruger x86-CPU'er kun to ud af fire ringe?
Når du lærer mere om, hvordan operativsystemer og hardware de kører på arbejde og interagerer med hinanden, kan du blive overrasket over at se, hvad der synes at være underlige eller underudnyttelse af "ressourcer" der forekommer. Hvorfor det? Dagens SuperUser Q & A-indlæg har svaret på en nysgerrig læsers spørgsmål.
Dagens Spørgsmål & Svar session kommer til os med venlig hilsen af SuperUser-en underafdeling af Stack Exchange, en community-driven gruppe af Q & A-websteder.
Foto med tilladelse til Lemsipmatt (Flickr).
Spørgsmålet
SuperUser-læser AdHominem vil vide, hvorfor x86-CPU'er kun bruger to ud af fire ringe:
Linux og Windows-baseret x86-systemer bruger kun Ring 0 for kernel mode og Ring 3 til brugermodus. Hvorfor adskiller processorer endda fire forskellige ringe, hvis de alle ender med at bruge to af dem alligevel? Har dette ændret sig med AMD64-arkitekturen?
Hvorfor bruger x86-CPU'er kun to ud af fire ringe?
Svaret
SuperUser bidragyder Jamie Hanrahan har svaret for os:
Der er to primære årsager.
For det første er det, at selv om x86-CPU'erne tilbyder fire ringe af hukommelsesbeskyttelse, er beskyttelsesgraden af den beskyttelse, der tilbydes derved, kun på per-segmentniveau. Det vil sige, hvert segment kan indstilles til en bestemt ring (privilegiumniveau) sammen med andre beskyttelser som skriveaktiveret. Men der er ikke så mange segmentbeskrivere til rådighed. De fleste operativsystemer vil gerne have en meget finere granularitet af hukommelsesbeskyttelse, som ... for enkelte sider.
Så indtast sidebaseret beskyttelse. De fleste, om ikke alle, moderne x86-operativsystemer ignorerer mere eller mindre segmenteringsmekanismen (så meget som de kan alligevel) og stole på den beskyttelse, der er tilgængelig fra lavordensbitene i sidetabellposter. En af disse kaldes den "privilegerede" bit. Denne bit styrer, hvorvidt processoren skal være i et af de "privilegerede" niveauer for at få adgang til siden. De "privilegerede" niveauer er PL 0, 1 og 2. Men det er kun en smule, så på sidebeskyttelsesniveauet er antallet af "tilstande", der er tilgængelige med hensyn til hukommelsesbeskyttelse, kun to: En side kan være tilgængelig fra ikke-privilegeret tilstand, eller ej. Derfor er der kun to ringe. For at have fire mulige ringe for hver side, skulle de have to beskyttelsesbitar i hver sidebordindgang for at kode et af fire mulige ringnumre (ligesom segmentbeskriverne). Men det gør de ikke.
Den anden grund er et ønske om operativsystemportabilitet. Det handler ikke kun om x86; Unix lærte os, at et operativsystem kunne være relativt bærbart til flere processor arkitekturer, og at det var en god ting. Og nogle processorer understøtter kun to ringe. Ved ikke at afhænge af flere ringe i arkitekturen gjorde operativsystemets implementere operativsystemerne mere bærbare.
Der er en tredje grund, der er specifik for Windows NT-udvikling. NT's designere (David Cutler og hans team, som Microsoft hyrede fra DEC Western Region Labs) havde omfattende tidligere erfaring med VMS; Faktisk var Cutler og nogle af de andre blandt VMS oprindelige designere. Og VAX-processoren, som VMS blev designet til, har fire ringe (VMS bruger fire ringe).
Men de komponenter, der løb i VMS Ringe 1 og 2 (Record Management Services og CLI) blev udeladt af NT design. Ring 2 i VMS handlede det ikke rigtig om operativsystemsikkerhed, men snarere om at bevare brugerens CLI-miljø fra et program til det næste, og Windows havde ikke det koncept; CLI kører som en almindelig proces. Hvad angår VMS's Ring 1, RMS-koden i Ring 1 måtte ringe ind Ring 0 temmelig ofte, og ringovergange er dyre. Det viste sig at være langt mere effektivt at bare gå til Ring 0 og gøres med det snarere end at have en masse Ring 0 overgange inden for Ring 1 kode (igen, ikke at NT har noget som RMS alligevel).
Hvad angår hvorfor x86 implementerede fire ringe, mens operativsystemerne ikke brugte dem, taler du om operativsystemer med langt nyere design end x86. Mange af systemprogrammeringsfunktionerne i x86 blev designet længe før NT eller ægte Unix-ish kerner blev implementeret på det, og de vidste ikke rigtigt, hvad operativsystemet ville bruge. Det var først, indtil vi fik paging på x86, at vi kunne implementere ægte Unix-ish eller VMS-lignende kerner.
Ikke alene ignorerer moderne x86-operativsystemer i høj grad segmentering (de stiller kun C-, D- og S-segmenterne op med en baseadresse på 0 og en størrelse på 4 GB; F- og G-segmenter bruges nogle gange til at pege på vigtige operativsystemdatastrukturer ), ignorerer de også stort set ting som "task state segmenter". TSS-mekanismen var klart designet til trådkontekstskifte, men det viser sig at have for mange bivirkninger, så moderne x86-operativsystemer gør det "for hånden". Den eneste gang, x86 NT ændrer hardwareopgaver, er for nogle helt usædvanlige forhold, som en dobbeltfejl undtagelse.
Hvad angår x64-arkitekturen, blev mange af disse afbrudte funktioner udeladt. Til deres kredit talte AMD faktisk til operativsystemets kernelag og spurgte, hvad de havde brug for fra x86, hvad de ikke havde brug for eller ikke ønskede, og hvad de gerne vil tilføje. Segmenter på x64 findes kun i, hvad der kan kaldes vestigial form, task state switching eksisterer ikke, etc., og operativsystemer fortsætter med at bruge kun to ringe.
Har du noget at tilføje til forklaringen? Lyde af i kommentarerne. Vil du læse flere svar fra andre tech-savvy Stack Exchange brugere? Tjek den fulde diskussionstråd her.