Processen en systeemaanroepen

Leer hoe een besturingssysteem één CPU deelt tussen veel draaiende programma's en toch elk programma op zijn plaats houdt. Je ziet wat een proces is en hoe het wisselt tussen de toestand in uitvoering, de gereedtoestand en de geblokkeerde toestand. Je maakt in C processen met fork, voert nieuwe programma's uit met exec en verzamelt hun resultaten met wait. Uiteindelijk bouw je een kleine shell met omleiding en pipes. Daarna kijk je onder de motorkap: gebruikersmodus en kernelmodus, hoe een systeemaanroep via een trap de kernel binnengaat, hoe excepties en interrupts verschillen en hoe het besturingssysteem met beperkte directe uitvoering en de timerinterrupt de CPU terugkrijgt en van het ene proces naar het andere overschakelt.

GemiddeldLes 1 van 9 in Cursus Besturingssystemen: processen, geheugen, threads en bestandssystemen

Wat je leert

  1. Beschrijf de belangrijkste taken van het besturingssysteem en de geschiedenis en ontwerpideeën die verklaren waarom het de machine op deze manier deelt en beschermt.
    • Beschrijf de belangrijkste taken van een besturingssysteem
      Leg uit hoe het besturingssysteem ruwe hardware omzet in gebruiksvriendelijkere, gedeelde en beschermde bronnen voor programma's.
    • Leg uit hoe multiprogrammering en tijdsverdeling het besturingssysteem hebben gevormd
      Volg de stappen van batchverwerking naar multiprogrammering en tijdsverdeling, zie waarom elke stap nieuwe bescherming vereiste en vergelijk de belangrijkste manieren om een kernel te organiseren.
  2. Leg uit wat een proces is, wat het besturingssysteem over elk proces vastlegt en hoe processen wisselen tussen de toestand in uitvoering, de gereedtoestand en de geblokkeerde toestand.
    • Leg uit wat een proces is en welke gegevens het besturingssysteem erover bijhoudt
      Onderscheid een programma van een proces, beschrijf de machinetoestand en adresruimte van een proces en leg uit hoe het besturingssysteem een proces aanmaakt en bijhoudt.
    • Volg de toestandsveranderingen van een proces
      Gebruik de toestanden in uitvoering, gereed en geblokkeerd en hun overgangen om te volgen hoe processen één CPU delen, en herken de extra toestanden die echte systemen rapporteren.
  3. Gebruik de Unix-proces-API in C om kindprocessen aan te maken, daarin nieuwe programma's uit te voeren, hun resultaten te verzamelen, ze te beëindigen en deze aanroepen tot een eenvoudige shell te combineren.
    • Maak een kindproces met fork
      Roep fork aan, onderscheid ouderproces en kindproces aan de hand van de retourwaarde en voorspel wat elk proces ziet en afdrukt.
    • Voer een ander programma uit met exec
      Vervang het programma in een proces met exec, geef argumenten correct door en leg uit waarom Unix het aanmaken van een proces scheidt van het laden van een programma.
    • Wacht op kindprocessen, lees de afsluitstatus en beëindig processen
      Beëindig processen met exit en signalen, haal het resultaat van een kindproces op met wait en waitpid, decodeer zijn status en voorkom dat zombie- en weesprocessen problemen veroorzaken.
    • Bouw een eenvoudige shell met fork, exec, wait en omleiding
      Combineer de procesaanroepen in een shelllus die commando's uitvoert, invoer en uitvoer omleidt, commando's met pipes verbindt en taken op de achtergrond uitvoert.
  4. Leg uit hoe de hardware geprivilegieerde kernelcode scheidt van gebruikersprogramma's en hoe programma's die grens gecontroleerd overschrijden via systeemaanroepen, excepties en interrupts.
    • Onderscheid gebruikersmodus van kernelmodus
      Leg uit wat elke CPU-modus toestaat, welke bewerkingen geprivilegieerd zijn en wat er gebeurt wanneer een programma de grenzen van zijn modus overschrijdt.
    • Leg stap voor stap uit hoe een systeemaanroep werkt
      Volg een systeemaanroep vanaf de wrapperfunctie in de bibliotheek via de trap naar de kernel en terug, en interpreteer de retourwaarde en fouten.
    • Onderscheid traps, excepties en interrupts
      Deel de gebeurtenissen in die de CPU naar de kernel laten overschakelen, leg uit hoe de afhandelaartabel van de kernel werkt en voorspel wat na elk soort gebeurtenis gebeurt.
  5. Leg uit hoe het besturingssysteem programma's rechtstreeks op volle snelheid op de CPU uitvoert en tegelijk de controle behoudt, en hoe het de CPU van het ene proces naar het andere overschakelt.
    • Leg beperkte directe uitvoering uit
      Leg de twee problemen uit van programma's rechtstreeks op de CPU uitvoeren en hoe gebruikersmodus, traps en de timerinterrupt die oplossen, stap voor stap van opstarten tot procesbeëindiging.
    • Volg een contextwisseling en schat de kosten ervan
      Volg elke stap bij het overschakelen van de CPU van het ene proces naar het andere, onderscheid een contextwisseling van een moduswisseling en schat hoeveel CPU-tijd de wisseling kost.

Processen en systeemaanroepen: uitleg

5 hoofdstukken

1

Leg uit wat een besturingssysteem doet

Het besturingssysteem geeft gewone programma's bruikbare manieren om te rekenen, gegevens op te slaan en apparaten te gebruiken, terwijl ze de machine veilig delen. Zijn taken verklaren waarom een desktoptoepassing geen eigen schijfstuurprogramma nodig heeft en waarom één programma met een fout niet alles zou moeten stoppen. Volg de ontwikkeling van computers met één taak naar interactieve systemen en vergelijk daarna hoe verschillende kernelontwerpen geprivilegieerd werk verdelen.

1.1 Beschrijf de belangrijkste taken van een besturingssysteem

Een browser, een compiler en een muziekspeler kunnen allemaal voortgang maken op één computer. Elk heeft CPU-tijd, geheugen en toegang tot apparaten nodig. Het besturingssysteem biedt die bronnen via diensten die programma's kunnen gebruiken zonder de hele machine te besturen.

Geef programma's bruikbare bronnen

Virtualisatie zet een fysieke bron om in een handige virtuele bron. CPU-virtualisatie laat veel processen werken alsof elk een eigen processor heeft. Het besturingssysteem voert elk proces een tijdje uit en bewaart zijn toestand tussen de beurten. Geheugenvirtualisatie geeft elk proces zijn eigen adresruimte: de adressen die zijn instructies kunnen gebruiken.

Een abstractie verbergt details achter een bruikbare interface. Een bestand is een abstractie voor opgeslagen bytes. Een programma kan write aanroepen zonder te weten of die bytes naar een SSD of een netwerkschijf gaan. Een systeemaanroep biedt een gecontroleerde manier om een dienst van de kernel aan te vragen. Apparaatspecifiek werk blijft achter de interface.

Deel bronnen en bescherm programma's

Als beheerder van bronnen beslist het besturingssysteem wie CPU-tijd, geheugen en apparaatdiensten krijgt. Het probeert de hardware nuttig te benutten en programma's tegelijk redelijke toegang te geven. Delen vereist ook bescherming: één programma mag het afgeschermde geheugen van een ander niet overschrijven of de timer uitschakelen om de CPU te behouden.

De hardware helpt deze grens af te dwingen. Instructies van toepassingen draaien in de gebruikersmodus met beperkte rechten. Kernelcode draait met de privileges die nodig zijn om de machine te beheren. Een timer kan een programma onderbreken, zelfs als dat programma nooit iets aan het besturingssysteem vraagt.

Volg bij een laptop die een bestand downloadt terwijl hij code compileert drie afzonderlijke taken:

  1. Het netwerkapparaat meldt binnenkomende gegevens. De kernel stelt die beschikbaar aan het downloadproces.
  2. Het besturingssysteem verdeelt CPU-tijd tussen de browser, de compiler en andere gereedstaande processen.
  3. De compiler vraagt bestandsbewerkingen aan om zijn uitvoer op te slaan. Zijn code stuurt de opslagcontroller niet rechtstreeks aan.
Onderscheid de kernel van de interface

De kernel is de geprivilegieerde kern. De shell, de desktop en de meeste systeembibliotheken draaien als gewone programma's, zelfs wanneer ze met het besturingssysteem worden meegeleverd. Een desktopvenster sluiten verwijdert de kernel niet. Een server zonder grafische interface heeft nog steeds procesbeheer, geheugenbescherming en apparaatdiensten nodig.

Op één logische CPU wisselen gebruikerscode en kernelcode elkaar af. Terwijl de compiler gewone gebruikersinstructies uitvoert, wordt de kernel niet ook op die CPU uitgevoerd. Systeemaanroepen, excepties en hardware-interrupts geven de kernel de controle terug.

Kies hoe en kies daarna wie

Een mechanisme biedt een bewerking; beleid bepaalt hoe die wordt gebruikt. De registers van het ene proces opslaan en die van een ander herstellen is een mechanisme. Kiezen welk gereed proces de volgende beurt krijgt is beleid. Door die te scheiden kan het besturingssysteem zijn planningskeuzes veranderen zonder het wisselmechanisme te vervangen.

Bij het ontwerp van een besturingssysteem worden bruikbare abstracties, prestaties, bescherming, betrouwbaarheid, beveiliging en energieverbruik tegen elkaar afgewogen. De extra CPU-tijd en het extra geheugen die aan beheer worden besteed, zijn overhead. In het hele vakgebied keren drie thema's terug: virtualisatie, gelijktijdigheid (activiteiten die tegelijk bezig zijn) en persistentie, waardoor opgeslagen gegevens de levensduur van een programma of een stroomuitval overleven.

Belangrijkste punten

  • Virtualisatie geeft programma's handige weergaven van gedeelde hardware.
  • Abstracties zoals bestanden verbergen apparaatdetails achter bruikbare bewerkingen.
  • De kernel is geprivilegieerd; de shell en de desktop zijn gewone programma's.
  • Een mechanisme biedt een bewerking; beleid bepaalt wanneer of voor wie die wordt gebruikt.
  • Bescherming en lage overhead zijn beide doelen bij het ontwerp van een besturingssysteem.

1.2 Leg uit hoe multiprogrammering en tijdsverdeling het besturingssysteem hebben gevormd

Besturingssystemen ontwikkelden zich toen computers van het uitvoeren van afzonderlijke taken overgingen naar het bedienen van veel activiteiten tegelijk. Elke verandering loste een praktisch probleem op: ongebruikte hardware, trage interactie of fouten die zich tussen programma's verspreidden.

Van batches naar overlappend werk

Bij batchverwerking worden ingediende taken achter elkaar uitgevoerd zonder interactie met degene die ze heeft ingediend. Vroege ondersteunende software hielp vooral bij het laden van taken en het uitvoeren van veelvoorkomende I/O-bewerkingen. Als de huidige taak op een apparaat moest wachten, kon de CPU ongebruikt blijven.

Multiprogrammering houdt meerdere taken in het geheugen. Wanneer één taak voor I/O blokkeert, kan een andere rekenen. Stel dat een taak telkens 20 ms rekent en 80 ms op schijf-I/O wacht. Als die alleen draait, is de CPU-bezettingsgraad 20 / 100 = 20%. Met twee van zulke taken en geschikte overlap kunnen nuttige berekeningen 40% van de verstreken tijd vullen. De vertraging van het apparaat is niet korter geworden; CPU-tijd die anders ongebruikt bleef, is benut.

De winst hangt ervan af of er werk gereedstaat. Door taken toe te voegen kan de CPU-bezettingsgraad niet boven 100% komen en taken die op hetzelfde apparaat wachten, kunnen nog steeds een knelpunt tegenkomen. Meerdere taken in het geheugen hebben ook bescherming nodig: de ene mag de andere niet overschrijven of de eigen gegevens van het besturingssysteem beschadigen.

Maak interactie snel

Tijdsverdeling geeft processen korte beurten op de CPU. Een terminal of desktop kan reageren terwijl andere programma's blijven werken. Het zou heel anders aanvoelen als een batchtaak eerst moest eindigen voordat een toetsaanslag van een andere gebruiker werd verwerkt.

Manier van delenWat wordt verdeeldVoorbeeld
TijdsverdelingGebruik van een bron over opeenvolgende intervallenCPU-beurten
RuimteverdelingCapaciteit waarover verschillende gebruikers tegelijk beschikkenGeheugengebieden of schijfruimte

Gelijktijdigheid betekent dat meerdere activiteiten in dezelfde periode bezig zijn. Hun instructies kunnen op één logische CPU worden afgewisseld. Parallellisme betekent dat instructies daadwerkelijk gelijktijdig op verschillende verwerkingsbronnen worden uitgevoerd. Multiprogrammering vereist geen parallelle hardware.

Plaats diensten binnen of buiten de kernel
OntwerpWaar de meeste diensten draaienBelangrijkste afweging
Monolithische kernelBestandssystemen, stuurprogramma's en netwerkfuncties draaien in de kernelmodusRechtstreekse aanroepen zijn efficiënt; een fout in een stuurprogramma kan de kernel beschadigen
MicrokernelEen kleine geprivilegieerde kern ondersteunt dienstprocessen in de gebruikersmodusIsolatie van diensten helpt fouten te beperken; communicatie kost extra werk
Hybride kernelCombineert elementen van beide benaderingenDe exacte grens tussen diensten hangt af van het ontwerp

Linux is monolithisch en kan kernelmodules laden. MINIX 3, QNX en seL4 zijn voorbeelden van microkernelontwerpen. Windows NT en XNU van Apple worden doorgaans beschreven als hybride ontwerpen. Een stuurprogramma in de gebruikersmodus kan na een crash vaak opnieuw worden gestart, terwijl een geprivilegieerd stuurprogramma toegang heeft waardoor een fout het hele systeem kan treffen.

Vroege systemen voor personal computers zoals MS-DOS en het klassieke Mac OS misten de procesgeheugenbescherming die tegenwoordig wordt verwacht. Moderne systemen combineren regels van het besturingssysteem met handhaving door de hardware. Korte CPU-beurten alleen zouden niet voorkomen dat een programma het geheugen van een ander programma verandert; delen en bescherming lossen verschillende delen van het probleem op.

Belangrijkste punten

  • Multiprogrammering vult I/O-wachttijd met berekeningen van een andere taak.
  • Tijdsverdeling ondersteunt interactief gebruik met korte CPU-beurten.
  • Gelijktijdig werk kan op één CPU worden afgewisseld; parallel werk wordt op hetzelfde moment uitgevoerd.
  • Tijdsverdeling verdeelt beurten; ruimteverdeling verdeelt capaciteit.
  • Bij de kernelorganisatie worden rechtstreekse aanroepen tussen diensten afgewogen tegen sterkere isolatie van diensten.
  • Meerdere taken in het geheugen vereisen geheugenbescherming en bescherming door privilegeniveaus.
2

Beschrijf processen en de toestanden die ze doorlopen

Een programmabestand is slechts het beginpunt. Om het uit te voeren bouwt het besturingssysteem een actief proces op en houdt het dat bij, met geheugen, registers, open descriptoren en een plaats in de processenlijst. Leer die toestand lezen en volg daarna twee processen terwijl CPU-werk overlapt met het wachten op apparaten. Het verschil tussen wachten op een CPU en wachten op een gebeurtenis verklaart welk proces de scheduler kan kiezen.

2.1 Leg uit wat een proces is en welke gegevens het besturingssysteem erover bijhoudt

Een uitvoerbaar bestand op schijf kan herhaaldelijk worden gestart. Elke start vereist een eigen veranderlijke toestand, zodat één instantie onafhankelijk kan pauzeren, hervatten of mislukken. Die actieve instantie is een proces.

Herken de draaiende instantie

Een programma bestaat uit opgeslagen instructies en statische gegevens. Een proces combineert een programma met zijn huidige geheugen, CPU-registers en I/O-toestand. Drie shells kunnen hetzelfde uitvoerbare bestand draaien en tegelijk verschillende variabelen, huidige directory's en geschiedenissen bijhouden.

De programmateller (PC) duidt de volgende instructie aan. De stackpointer geeft de locatie van de actieve stack aan. Algemene registers bevatten tussenwaarden. Wanneer een proces stopt met draaien, moet voldoende toestand worden bewaard om het bij de juiste instructie met de juiste waarden te laten doorgaan.

Lees de indeling van de adresruimte

De adresruimte van een proces is het geheugen dat zijn instructies kunnen adresseren. Een veelgebruikte indeling in leermateriaal plaatst code en statische gegevens bij lagere adressen, een heap daarboven en een stack bij hogere adressen. De heap ondersteunt dynamisch toegewezen objecten; de stack ondersteunt functieaanroepen en lokale toestand. In deze indeling groeit de heap naar hogere adressen en de stack naar lagere adressen. De werkelijke indeling hangt af van het systeem en implementaties van malloc kunnen op meer dan één manier geheugen verkrijgen.

Twee processen kunnen voor een variabele hetzelfde virtuele adres afdrukken en daar toch verschillende waarden bevatten. Virtuele adressen horen bij de geheugenweergave van een proces. Gelijke adresnummers betekenen niet dat schrijfbare opslag wordt gedeeld.

Start een programma

Om een nieuw programmabeeld te starten, richt het besturingssysteem deze onderdelen in:

  1. De uitvoerbare code en gegevens, waarvan delen op moderne systemen worden geladen wanneer ze nodig zijn.
  2. Een initiële gebruikersstack en opstartinformatie, waaronder de argumentstrings en argumentvector die de runtime gebruikt om main aan te roepen.
  3. Geheugen voor dynamische toewijzing en de initiële registertoestand.
  4. Een I/O-omgeving, inclusief geërfde bestandsdescriptoren.
  5. Een ingangspunt waar de opstartcode van het programma begint.

Op Unix zijn bestandsdescriptoren kleine gehele getallen die open I/O-bronnen aanduiden. Volgens de shellconventie is 0 standaardinvoer, 1 standaarduitvoer en 2 standaardfoutuitvoer. Ze zijn vaak met een terminal verbonden. Een proces kan extra descriptoren erven; de drie bekende nummers zijn geen limiet en geen garantie dat elk proces ze altijd open heeft.

Bekijk de gegevens van de kernel

Het procesbesturingsblok (PCB) bevat informatie die de kernel nodig heeft om één proces te beheren: PID, toestand, opgeslagen uitvoeringscontext, geheugengegevens, open descriptoren, ouderproces, eigenaar, huidige directory en gebruiksgegevens. Linux gebruikt task_struct; xv6 gebruikt struct proc. Een processentabel of processenlijst ordent deze gegevens.

Terwijl een proces draait, staan zijn actuele registers in de CPU. Bij binnenkomst in de kernel worden zijn gebruikersregisters op zijn kernelstack opgeslagen; een contextwisseling bewaart ook de uitvoeringscontext van de kernel. Het PCB is geen voortdurend bijgewerkte afspiegeling van elk gebruikersregister.

Een Linux-uitvoer van ps kan bijvoorbeeld 8240 8200 S bash en 8291 8240 R ps bevatten. Het tweede proces heeft PID 8291 en ouder-PID 8240, dus het is een kindproces van de shell. R omvat zowel processen in uitvoering als gereedstaande processen. Een PID identificeert een actief proces binnen zijn PID-naamruimte, maar na het opruimen kan dat nummer opnieuw worden gebruikt.

Belangrijkste punten

  • Een proces is een instantie van een programma met een geheugen-, register- en I/O-toestand.
  • Identieke virtuele adressen in verschillende processen kunnen verschillende gegevens aanduiden.
  • Het PCB bevat de beheergegevens van de kernel, geen voortdurend actuele CPU-registers.
  • Bestandsdescriptoren worden geërfd; 0, 1 en 2 hebben afgesproken rollen.
  • PID's kunnen opnieuw worden gebruikt nadat een proces is beëindigd en opgeruimd.

2.2 Volg de toestandsveranderingen van een proces

Een proces kan bestaan zonder op dit moment een instructie uit te voeren. Zijn toestand vertelt het besturingssysteem of het een CPU kan gebruiken of eerst op iets anders moet wachten. Dit onderscheid verklaart waarom een drukke computer veel processen kan hebben waarvan er op een bepaald moment maar enkele worden uitgevoerd.

Bepaal wat het proces nodig heeft
ToestandBetekenisVoorbeeld
In uitvoeringWordt uitgevoerd op een CPUEen compiler die instructies genereert
GereedKan worden uitgevoerd, wacht op CPU-tijdEen berekening waarvan de beurt net is geëindigd
GeblokkeerdWacht op een gebeurtenis voordat het verder kanEen leesbewerking van de terminal die op invoer wacht

Een geblokkeerd proces verbruikt geen CPU-tijd zolang het geblokkeerd is. Het apparaat of de gebeurtenis kan nog wel voortgang maken. Een gereed proces heeft al wat het nodig heeft, behalve een CPU.

De basisovergangen zijn gereed → in uitvoering wanneer het proces wordt gekozen, in uitvoering → gereed wanneer het van de CPU wordt gehaald, in uitvoering → geblokkeerd wanneer het moet wachten en geblokkeerd → gereed wanneer de gebeurtenis plaatsvindt. Door voltooiing van de gebeurtenis komt een proces in aanmerking voor uitvoering; het krijgt niet onmiddellijk de CPU. Kiezen tussen processen die in aanmerking komen is de taak van de scheduler.

Volg overlappend werk

Gebruik één logische CPU en negeer wisseloverhead. Proces A rekent 2 ms, wacht 3 ms op schijf-I/O en rekent daarna 1 ms. Proces B heeft 4 ms CPU-tijd nodig. A begint eerst.

IntervalCPUToestand van AToestand van B
0–2 msAIn uitvoeringGereed
2–5 msBGeblokkeerdIn uitvoering
5–6 msBGereedIn uitvoering
6–7 msAIn uitvoeringKlaar

Op 2 ms start A de I/O en blokkeert. B rekent terwijl de schijf werkt. Op 5 ms is de I/O van A voltooid, maar het besturingssysteem laat B zijn vierde CPU-milliseconde afmaken voordat het A uitvoert. Dit is een beleidskeuze, geen extra toestandsovergang rechtstreeks van geblokkeerd naar in uitvoering.

Het totale CPU-werk is 2 + 1 + 4 = 7 ms en beide zijn na 7 ms klaar. Als A volledig zou draaien voordat B begon, zou de verstreken tijd 2 + 3 + 1 + 4 = 10 ms zijn. De CPU-bezettingsgraad zou 7 / 10 = 70% zijn, omdat geen ander werk de I/O-wachttijd vulde.

Lees toestanden op een echt systeem

Linux ps combineert in uitvoering en gereed als R. Het toont onderbreekbare slaap als S, niet-onderbreekbare slaap, vaak voor I/O, als D, een gestopt proces als T en een beëindigd proces waarvan de status nog niet is opgehaald als Z. Een gestopt proces wacht niet simpelweg op de voltooiing van een gewone I/O-bewerking. Een zombieproces is klaar met uitvoeren en behoudt alleen de gegevens die nodig zijn om zijn resultaat te melden.

Een nieuw proces doorloopt ook de aanmaakfase voordat het gereed is. Op een systeem met vier logische CPU's kunnen hoogstens vier processen met één thread tegelijk worden uitgevoerd. Gereedwachtrijen ordenen werk dat voor uitvoering in aanmerking komt; lijsten met geblokkeerde processen houden bij welke gebeurtenissen die processen nodig hebben. Een contextwisseling bewaart de uitvoeringstoestand van het ene proces en herstelt die van een ander wanneer het besturingssysteem verandert welk proces draait.

Belangrijkste punten

  • Gereed betekent wachten op een CPU; geblokkeerd betekent wachten op een gebeurtenis.
  • De voltooiing van I/O maakt een geblokkeerd proces gereed.
  • Wachttijd op apparaten laten overlappen met nuttig CPU-werk kan de totale verstreken tijd verkorten.
  • Linux rapporteert gereed en in uitvoering met dezelfde code, R.
  • Een zombieproces is beëindigd, maar zijn beëindigingsstatus is nog niet opgehaald.
  • Het aantal logische CPU's beperkt de gelijktijdige uitvoering van processen met één thread.
3

Maak en bestuur processen met fork, exec en wait

De Unix-procesinterface scheidt het aanmaken van een kindproces, het vervangen van zijn programma en het ophalen van zijn resultaat. Volg wat elke aanroep verandert en behoudt, waaronder afgeschermde variabelen en gedeelde toestand van geopende bestanden. Combineer de aanroepen daarna tot gedrag van een shell: commando's op de voorgrond, omleiding, pijplijnen en achtergrondtaken. Bij elke stap moet je weten welk proces die uitvoert.

3.1 Maak een kindproces met fork

fork() maakt vanuit het aanroepende ouderproces een kindproces aan. Beide gaan direct na de aanroep verder, zodat één pad in de broncode twee uitvoeringen wordt. De retourwaarde vertelt elk proces welke rol het heeft.

Handel alle drie de resultaten af
pid_t rc = fork();
if (rc < 0) {
    perror("fork");
    exit(1);
} else if (rc == 0) {
    printf("child %ld\n", (long) getpid());
} else {
    printf("parent of %ld\n", (long) rc);
}

Gebruik <unistd.h> voor fork en getpid, <stdio.h> voor afdrukken en <stdlib.h> voor exit. Bij succes ontvangt het ouderproces de positieve PID van het kindproces; het kindproces ontvangt 0. Bij een fout ontvangt de aanroeper -1, geeft errno de fout aan en bestaat er geen kindproces.

Als het ouderproces PID 5000 heeft en het kindproces 5001, drukt het ouderproces “parent of 5001” af en het kindproces “child 5001”. Het is niet gegarandeerd welk proces eerst draait. getpid() geeft de eigen PID van de aanroeper terug; getppid() geeft de PID van zijn ouderproces terug. Het kindproces begint main niet opnieuw en herhaalt geen instructies van vóór de fork.

Volg afgeschermd geheugen en gedeelde I/O

Ouderproces en kindproces beginnen met dezelfde gewone geheugeninhoud in afzonderlijke adresruimten. Als x vóór de aanroep 10 is en het kindproces zijn kopie op 20 zet, blijft de kopie van het ouderproces 10. Zelfs het afgedrukte adres van x kan gelijk zijn: die gelijke virtuele adressen horen bij verschillende procesadresruimten.

Kopiëren bij schrijven voorkomt dat elke geheugenpagina direct wordt gekopieerd. Ouderproces en kindproces delen aanvankelijk fysieke pagina's die tegen schrijven zijn beschermd. Wanneer een van beide naar een afgeschermde pagina schrijft, zorgt de kernel voor een eigen kopie voordat hij de schrijfbewerking toestaat. Zo blijft het gedrag van gescheiden geheugen behouden, terwijl de kosten lager zijn als een kindproces snel daarna exec aanroept.

Bestandsdescriptoren gedragen zich anders. Hun gekopieerde vermeldingen verwijzen naar dezelfde onderliggende beschrijving van een geopend bestand (open file description), die de huidige bestandspositie bevat. Opeenvolgende leesbewerkingen via een geërfde descriptor verschuiven die gedeelde positie. De descriptortabel wordt gekopieerd, maar de onderliggende toestand van het geopende bestand in de kernel kan gedeeld blijven.

Tel alleen forks die een proces bereikt

Als elke aanroep slaagt, laat fork(); fork(); vier processen over: beide processen die door de eerste aanroep ontstaan, voeren de tweede uit. Een lus met drie iteraties die door alle processen wordt bereikt, laat 23=8 processen over, inclusief het oorspronkelijke proces. Een fork in een tak die alleen het ouderproces uitvoert, wordt door minder processen bereikt, zodat herhaalde verdubbeling niet langer het hele programma beschrijft.

Leeg gebufferde tekst bewust

printf kan tekst in een buffer in de gebruikersruimte achterlaten. fork kopieert die buffer samen met de rest van het geheugen. Als uitvoer wordt omgeleid naar een volledig gebufferde stroom, kan tekst die vóór de fork is afgedrukt door beide processen bij normale beëindiging worden weggeschreven.

Bij printf("start\n"); fork(); schrijft een gebruikelijke regelgebufferde terminal de regel met het regelafbrekingsteken vóór de fork weg. Bij omleiding naar een bestand kan de tekst in de buffer blijven staan en tweemaal worden weggeschreven. fflush(stdout) vóór fork() schrijft de wachtende tekst eenmaal weg. De dubbele uitvoer komt door gekopieerde gebufferde gegevens, niet doordat de eerdere printf tweemaal wordt uitgevoerd.

Belangrijkste punten

  • fork() geeft in het ouderproces een PID van een kindproces terug, in het kindproces 0 en bij een fout -1.
  • Beide processen gaan na een geslaagde aanroep direct na fork() verder.
  • Wijzigingen in gewoon afgeschermd geheugen van het kindproces veranderen de waarden van het ouderproces niet.
  • Geërfde descriptoren kunnen één beschrijving van een geopend bestand en één bestandspositie delen.
  • Het aantal processen hangt af van welke processen elke fork bereiken.
  • Schrijf wachtende uitvoer vóór een fork weg als dubbel wegschrijven ongewenst zou zijn.

3.2 Voer een ander programma uit met exec

Een proces kan zijn identiteit behouden terwijl het van programma verandert. De exec-familie voert die vervanging uit. Door die met fork te combineren kan een ouderproces zijn werk voortzetten terwijl een kindproces een ander programma gaat uitvoeren.

Vervang het beeld, behoud het proces

Een geslaagde exec vervangt de oude code, statische gegevens, heap en stack. De kernel bereidt de argumenten en begintoestand van het nieuwe programma voor en begint daarna met de opstartcode. De oude aanroepplek bestaat niet meer, dus een geslaagde exec keert daar nooit naar terug.

De PID, de relatie met het ouderproces en de huidige directory blijven behouden. Open descriptoren blijven behouden, behalve die welke zijn gemarkeerd om bij exec te sluiten. Signalen waarvoor een afhandelaar was ingesteld, krijgen weer hun standaardactie; genegeerde signalen blijven doorgaans genegeerd. De gebruikers- en groepsidentiteit blijft meestal gelijk, maar de set-user-ID- of set-group-ID-rechten van een uitvoerbaar bestand kunnen de effectieve identiteit veranderen als het systeem dat toestaat.

BewerkingNieuw proces?Belangrijkste effect
fork()JaMaakt een kindproces met gekopieerde uitvoeringstoestand
Geslaagde execNeeVervangt het programmabeeld van het aanroepende proces
Bouw een geldige argumentvector

Om wc -l notes.txt uit te voeren kan het kindproces dit gebruiken:

char *args[] = {"wc", "-l", "notes.txt", NULL};
execvp(args[0], args);
perror("execvp");
_exit(127);

De strings zijn afzonderlijke argumenten, geen gecombineerde opdrachtregel. Volgens afspraak geeft args[0] het programma aan. De afsluitende NULL is een pointer die het einde van de array markeert; het is niet de string “NULL”. Zonder geldige afsluiting kan de aanroep voorbij de array lezen.

De regels na execvp handelen een fout af. Als het programma niet kan worden gevonden, geeft exec -1 terug en stelt errno in, bijvoorbeeld op ENOENT. _exit beëindigt het kindproces dan zonder geërfde uitvoerbuffers van C te legen. Na een fout terugkeren naar de shelllus zou onbedoeld een extra uitvoeringspad van de shell creëren.

Lees de naam van de variant

De v in execv betekent dat argumenten als vector binnenkomen; l-varianten ontvangen een lijst. Een p-variant zoekt in PATH naar een programmanaam. Een e-variant geeft een expliciete omgeving door. De onderliggende systeemaanroep van Linux is execve; de bibliotheek biedt de handige varianten.

execvp("wc", args) zoekt in PATH. execv("wc", args) behandelt “wc” als een relatieve padnaam in de huidige directory. Een absolute padnaam zoals /usr/bin/wc kan worden gebruikt waar dat uitvoerbare bestand is geïnstalleerd. Exec ontleedt geen shellsyntaxis: een string > in args is gewoon een argument, tenzij een programma die zelf interpreteert.

Gebruik de tijd vóór vervanging

In het voorbeeld met ouderproces PID 6000 en kindproces PID 6001 gaat het kindproces wc uitvoeren, maar behoudt het PID 6001. Zijn ouderproces kan op die PID wachten. Vóór exec kan het kindproces descriptoren omleiden, een pipe aansluiten of van directory veranderen; het vervangende programma erft de voorbereide omgeving.

Deze scheiding staat centraal in de Unix-shell. Windows CreateProcess combineert het aanmaken van een proces en het laden van een programma en gebruikt parameters om het nieuwe proces te configureren. POSIX biedt ook posix_spawn voor een gecombineerde bewerking.

Belangrijkste punten

  • Exec vervangt een programmabeeld zonder een proces aan te maken of zijn PID te veranderen.
  • Bij succes keert exec nooit terug; de daaropvolgende opdrachten handelen fouten af.
  • Sluit argumentvectoren af met een NULL-pointer.
  • p-varianten zoeken in PATH; een variant die alleen een padnaam gebruikt doet dat niet.
  • Door descriptoren vóór exec in te stellen kan een ongewijzigd programma aan omleiding en pipes deelnemen.

3.3 Wacht op kindprocessen, lees de afsluitstatus en beëindig processen

Een ouderproces moet weten of een kindproces klaar is en hoe het is geëindigd. Procesbeëindiging en het ophalen van het resultaat zijn afzonderlijke stappen: het kindproces eindigt en daarna haalt het ouderproces de resterende gegevens bij de kernel op.

Beëindig een proces

Terugkeren uit main of exit(status) aanroepen beëindigt de uitvoering normaal. exit leegt C-uitvoerbuffers en voert geregistreerde beëindigingsafhandelaars uit. _exit(status) beëindigt zonder die opruimactie van de bibliotheek, wat nuttig is na een mislukte exec in een met fork aangemaakt kindproces. Volgens afspraak betekent 0 succes en een waarde anders dan nul een fout.

Een signaal kan een proces ook beëindigen. SIGTERM vraagt om beëindiging en kan worden afgehandeld; SIGKILL kan niet worden opgevangen of genegeerd. SIGSTOP stopt de uitvoering en kan ook niet worden opgevangen of genegeerd; SIGCONT hervat een gestopt proces. Een terminal stuurt normaal SIGINT bij Ctrl-C en SIGTSTP bij Ctrl-Z naar de taak op de voorgrond. Een signaal is een softwaremelding aan een proces, geen hardware-interrupt.

Wacht op één resultaat

wait(&status) wacht op één kindproces en geeft zijn PID terug. waitpid(pid, &status, 0) selecteert een bepaalde positieve PID van een kindproces. De status van een geëindigd kindproces die nog niet is opgehaald, kan direct worden opgehaald. Anders onderbreekt een gewone blokkerende wachtbewerking het ouderproces totdat een passend resultaat beschikbaar is.

Met WNOHANG geeft waitpid 0 terug wanneer passende kindprocessen bestaan, maar geen daarvan een resultaat klaar heeft. Een positief resultaat geeft aan welk kindproces is opgehaald. Een resultaat van -1 is een fout: ECHILD betekent dat er geen passend kindproces meer is; EINTR betekent dat een signaalafhandelaar het wachten heeft onderbroken.

Decodeer de status vóór gebruik
int status;
pid_t r;
do {
    r = waitpid(child, &status, 0);
} while (r == -1 && errno == EINTR);
if (r == -1) {
    perror("waitpid");
} else if (WIFEXITED(status)) {
    printf("exit %d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
    printf("signal %d\n", WTERMSIG(status));
}

Dit gebruikt <sys/wait.h>, <errno.h> en <stdio.h>. De opgeslagen status codeert zowel de manier van beëindigen als een resultaat. WEXITSTATUS is zinvol nadat WIFEXITED waar is gebleken; WTERMSIG volgt op WIFSIGNALED.

Alleen de laagste acht bits van een normale afsluitwaarde zijn beschikbaar. exit(300) levert daarom 44 op, terwijl exit(-1) 255 oplevert. Op Linux levert exit(3) doorgaans de ruwe wachtstatus 768 op; dat ruwe gehele getal afdrukken is niet hetzelfde als de afsluitcode decoderen.

Haal zombieprocessen op en herken weesprocessen

Een zombieproces is beëindigd, maar behoudt zijn PID en resultaat totdat een wachtbewerking die ophaalt. Het voert geen code uit, dus SIGKILL sturen kan het niet verwijderen. Een langlopend ouderproces moet de beëindigingsstatus van elk kindproces ophalen. Om alle kindprocessen op te halen blijf je na elke positieve PID wachten, probeer je opnieuw bij EINTR en stop je bij ECHILD; andere fouten meld je.

Een weesproces heeft zijn ouderproces verloren en kan nog draaien. Linux geeft het een passend subreaperproces of het initproces van de naamruimte als nieuw ouderproces, dat later zijn resultaat kan ophalen. Gewone rechten om signalen te sturen hangen af van gebruikersidentiteiten en privileges. Als root draaien geeft rechten, maar betekent niet dat de uitvoering in de kernelmodus plaatsvindt.

Belangrijkste punten

  • Elke geslaagde wachtbewerking haalt het resultaat van één kindproces op.
  • Decodeer normale beëindiging en beëindiging door een signaal met de bijbehorende statusmacro's.
  • WNOHANG geeft 0 terug als er een passend kindproces bestaat maar nog geen resultaat klaar heeft.
  • Probeer een onderbroken wachtbewerking opnieuw bij EINTR; ECHILD betekent dat er geen passend kindproces meer is.
  • Een zombieproces is geëindigd; een weesproces heeft zijn ouderproces verloren en kan nog draaien.
  • SIGKILL en SIGSTOP kunnen niet worden opgevangen of genegeerd.
  • exit leegt C-buffers; _exit doet dat niet.

3.4 Bouw een eenvoudige shell met fork, exec, wait en omleiding

Een shell zet commandotekst om in het aanmaken van processen, het instellen van descriptoren en het ophalen van resultaten. Het is een gewoon gebruikersprogramma dat dezelfde beschermde diensten van het besturingssysteem gebruikt als andere programma's.

Start een extern commando

Voor wc -l notes.txt bouwt de shell de argumentvector en start hij het commando. De ontlede woorden vormen een met een nullpointer afgesloten argumentvector, args:

pid_t child = fork();
if (child == -1) {
    perror("fork");
} else if (child == 0) {
    execvp(args[0], args);
    perror("execvp");
    _exit(127);
} else {
    int status;
    pid_t result;
    do {
        result = waitpid(child, &status, 0);
    } while (result == -1 && errno == EINTR);
    if (result == -1) perror("waitpid");
    else if (WIFEXITED(status)) {
        printf("exit %d\n", WEXITSTATUS(status));
    } else if (WIFSIGNALED(status)) {
        printf("signal %d\n", WTERMSIG(status));
    }
}

Dit gebruikt <unistd.h>, <sys/wait.h>, <errno.h> en <stdio.h>. De omringende shell leest en ontleedt elk commando, voert dit startpad uit en toont daarna de volgende prompt.

Alleen het kindproces vervangt zijn programma; de shell kan het crashen van een commando als beëindigingsresultaat ophalen. Ingebouwde commando's zoals cd moeten de eigen toestand van de shell veranderen: als een kindproces van directory verandert, blijft de directory van de oudershell ongewijzigd.

Leid een descriptor om vóór exec

Voor ls -l > out.txt opent het kindproces de bestemming om te schrijven en maakt het bestand aan of wijzigt de lengte ervan naar nul. Daarna laat het standaarduitvoer naar dat bestand verwijzen:

int fd = open("out.txt", O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1) { perror("open"); _exit(1); }
if (dup2(fd, STDOUT_FILENO) == -1) {
    perror("dup2"); _exit(1);
}
if (fd != STDOUT_FILENO && close(fd) == -1) {
    perror("close"); _exit(1);
}

open heeft <fcntl.h> nodig; descriptoraanroepen en _exit gebruiken <unistd.h>. De rechten voor het aanmaken worden gefilterd door het bestandsaanmaakmasker van het proces. De controle fd != STDOUT_FILENO houdt descriptor 1 open, ook als open zelf 1 teruggaf. Na een geslaagde instelling behoudt exec descriptor 1 en schrijft ls normaal zonder iets van de omleiding te weten.

Een oudere aanpak sluit descriptor 1 voordat het bestand wordt geopend: open geeft de laagste ongebruikte descriptor terug. dup2 geeft de bestemming expliciet aan. Invoeromleiding verbindt op dezelfde manier een leesbaar bestand met descriptor 0.

Verbind twee commando's

Voor ls | wc -l maakt pipe(fds) een leeskant fds[0] en een schrijfkant fds[1]. Het producerende kindproces verbindt de schrijfkant met descriptor 1. Het consumerende kindproces verbindt de leeskant met descriptor 0. Na het dupliceren sluit elk proces de oorspronkelijke pipedescriptoren die het niet nodig heeft. Het ouderproces sluit zijn kopieën en wacht op beide kindprocessen.

Maak beide kindprocessen aan voordat je op een ervan wacht. Een producent kan de pipe vullen en blokkeren; de lezer moet bestaan om de pipe leeg te maken. De lezer bereikt het bestandseinde pas wanneer alle schrijfdescriptoren zijn gesloten en de gebufferde pipegegevens zijn verbruikt. Een ongebruikte schrijfkant die het ouderproces openhoudt, kan wc voor altijd laten wachten.

Houd de prompt beschikbaar

Voor sleep 60 & start de shell het kindproces en toont hij de volgende prompt zonder direct te wachten. Later gebruikt hij niet-blokkerende wachtbewerkingen of reageert hij op SIGCHLD om de status van beëindigde kindprocessen op te halen.

De afsluitstatus bepaalt ook commandocombinaties. make && ./app start het tweede commando alleen na succes; make || echo failed start het tweede alleen na een fout. Deze beslissingen gebruiken het gedecodeerde resultaat, niet de ruwe gecodeerde wachtstatus.

Belangrijkste punten

  • Een extern commando draait in een kindproces; een ingebouwd commando dat de toestand verandert draait in de shell.
  • Omleiding verandert descriptoren in het kindproces vóór exec.
  • Een pipe verbindt de standaarduitvoer van een producent met de standaardinvoer van een consument.
  • Start beide kanten voordat je wacht en sluit ongebruikte pipekanten.
  • Voor bestandseinde moet elke schrijfkant van de pipe gesloten zijn nadat gebufferde gegevens zijn verbruikt.
  • Uitvoering op de achtergrond stelt het wachten uit; de shell moet de beëindigingsstatus van het kindproces later nog ophalen.
4

Leg gebruikersmodus, kernelmodus en systeemaanroepen uit

Gebruikersprogramma's hebben diensten van het besturingssysteem nodig zonder de controle over de machine te krijgen. Privilegemodi van de hardware vormen die grens en gecontroleerde toegangspaden laten de kernel op verzoeken en gebeurtenissen reageren. Volg een systeemaanroep via de wrapperfunctie in de bibliotheek en de kernelafhandelaar en onderscheid daarna bewuste traps, instructiefouten en apparaatinterrupts aan de hand van hun oorzaken en mogelijke gevolgen.

4.1 Onderscheid gebruikersmodus van kernelmodus

De kernel moet programma's snel laten rekenen en tegelijk bewerkingen tegenhouden waarmee de controle over de machine kan worden overgenomen. De privilegemodus van de CPU is de hardwaregrens die beide mogelijk maakt.

Scheid berekeningen van geprivilegieerde besturing

In de gebruikersmodus kunnen instructies toegang krijgen tot toegestaan procesgeheugen en gewone berekeningen uitvoeren. Ze kunnen de hardwareconfiguratie die andere programma's beschermt niet vrij veranderen. In de kernelmodus, ook supervisormodus of geprivilegieerde modus genoemd, kan het besturingssysteem de beschermde bewerkingen uitvoeren die nodig zijn om de machine te beheren.

Geprivilegieerde bewerkingen zijn onder meer de timer programmeren, interrupts uitschakelen, interruptafhandelaars instellen, besturingsregisters voor geheugenvertaling veranderen, beschermde apparaten rechtstreeks aansturen en de CPU stilzetten. Als elke toepassing de timer kon uitschakelen, zouden korte CPU-beurten afhangen van de medewerking van die toepassing.

PlatformToepassingsmodusKernelmodus
x86-64 op Linux of WindowsRing 3Ring 0
AArch64EL0EL1

AArch64 biedt ook EL2 voor hypervisors en EL3 voor beveiligde firmware. Deze namen duiden privilegeniveaus van de hardware aan, geen verschillende soorten gebruikersaccounts.

Ga binnen op een gecontroleerd adres

Gebruikerscode kan haar eigen privileges niet verhogen en niet zomaar een kerneladres kiezen om code uit te voeren. De overgang vindt plaats via een systeemaanroep, een door een instructie veroorzaakte exceptie of een hardware-interrupt. De CPU draagt de controle over aan een ingangspunt dat door het besturingssysteem is ingesteld. De terugkeercode van de kernel herstelt de opgeslagen gebruikerstoestand en verlaagt het privilegeniveau om de toepassingscode te hervatten.

De kernel beschermt zijn gegevens ook met geheugentoegangsrechten. Een proces kan kerneladressen in zijn virtuele indeling hebben en toch geen rechten hebben om die in de gebruikersmodus te benaderen. Een adres kennen geeft geen toegang tot de bytes op dat adres.

Neem een x86-64 Linux-toepassing die hlt uitvoert, een instructie die is bedoeld om een CPU tot een gebeurtenis stil te zetten. In de gebruikersmodus veroorzaakt de instructie een exceptie. Linux stuurt normaal SIGSEGV, waarvan de standaardactie dat proces beëindigt. De toepassing zet niet de hele computer stil; de beschermingsgrens verandert de poging tot een geprivilegieerde bewerking in een gebeurtenis die de kernel afhandelt.

Houd identiteit en modus gescheiden

Een root- of beheerdersproces is nog steeds een programma in de gebruikersmodus terwijl zijn eigen instructies draaien. Zijn gebruikersidentiteit geeft het ruimere rechten om diensten aan te vragen. Het gaat nog steeds via gecontroleerde paden de kernel binnen en de kernel controleert het verzoek.

Een geprivilegieerd onderhoudsprogramma mag bijvoorbeeld een beschermd bestand openen. Het programma vraagt dat via een systeemaanroep; het wordt geen kernelcode alleen omdat het verzoek is toegestaan. Omgekeerd wordt kernelcode die een read van een gewone gebruiker afhandelt in de kernelmodus uitgevoerd, ook al heeft de aanroeper geen beheerdersidentiteit.

Op één logische CPU is dit een volgorde: gebruikersinstructies, toegang tot de kernel, kernelwerk, terugkeer naar gebruikersinstructies. Het is geen gelijktijdige uitvoering van een programma en een tweede taak van het besturingssysteem op dezelfde CPU. Afzonderlijke logische CPU's kunnen op hetzelfde moment verschillende modi uitvoeren.

Belangrijkste punten

  • De gebruikersmodus staat gewone berekeningen toe en beperkt bewerkingen die de machine besturen.
  • De toegang tot de kernel verloopt via ingangspunten die het besturingssysteem heeft ingesteld.
  • Root is een gebruikersidentiteit; de kernelmodus is een privilegetoestand van de CPU.
  • Een verboden gebruikersinstructie veroorzaakt een exceptie zodat de kernel kan reageren.

4.2 Leg stap voor stap uit hoe een systeemaanroep werkt

Een C-programma lijkt vaak een gewone functie aan te roepen wanneer het een dienst van het besturingssysteem nodig heeft. Onder de wrapperfunctie van een systeemaanroep zorgt een gecontroleerde CPU-overgang ervoor dat kernelcode dat verzoek kan controleren en uitvoeren.

Onderscheid een bibliotheekaanroep van een kernelverzoek

De C-bibliotheek implementeert strlen in de gebruikersruimte zonder systeemaanroep. printf maakt gegevens op en kan die bufferen; een latere write draagt bytes via de kernel over. Een dunne wrapperfunctie voor read zet argumenten klaar volgens de systeemaanroepconventie van het platform en voert de toegangsinstructie uit.

POSIX beschrijft interfaces voor Unix-achtige systemen. Linux implementeert veel diensten die grofweg zijn ingedeeld in procesbesturing, bestands- en apparaatbewerkingen, informatie, communicatie en bescherming. Een systeemaanroepnummer selecteert een dienst uit de dispatchtabel van de kernel. Nummers zijn platformspecifiek: Linux x86-64 gebruikt 1 voor write en 39 voor getpid; AArch64 gebruikt 64 voor write.

Volg één schrijfverzoek

Volg voor write(1, "hi\n", 3) op Linux x86-64 het verzoek in volgorde:

  1. De wrapperfunctie plaatst dienstnummer 1 in rax, descriptor 1 in rdi, het bufferadres in rsi en het aantal 3 in rdx.
  2. syscall bewaart het retouradres en de vlaggen in registers, gaat naar de kernelmodus en springt naar het ingestelde ingangspunt. De instructie wisselt niet automatisch van stack.
  3. Ingangscode van de kernel richt de kernelstack van het proces in en slaat de resterende gebruikerstoestand op.
  4. De kernel kiest via zijn dispatchtabel write; de implementatie controleert de descriptor, de toegang tot de gebruikersbuffer en het verzoek voordat ze bytes doorgeeft aan de uitvoerbron.
  5. Bij een volledig geslaagde schrijfbewerking is het resultaat 3 bytes. Terugkeercode van de kernel herstelt de gebruikerstoestand en hervat de wrapperfunctie, die terugkeert naar de aanroeper.

Descriptor 1 kan een terminal, bestand of pipe aanduiden. Het nummer alleen geeft niet aan welk uitvoerapparaat wordt gebruikt. Een schrijfbewerking kan ook met succes een kleiner aantal bytes teruggeven; aanroepers die elke byte moeten overdragen houden bij hoeveel daadwerkelijk is geschreven.

Controleer fouten bij de interface

De kernel behandelt gebruikerspointers en andere argumenten als onbetrouwbaar. Een verzoek om uit een ontoegankelijke buffer te kopiëren kan mislukken met EFAULT; gecontroleerd kopiëren voorkomt dat de aanroeper toegang krijgt tot kernelgeheugen.

Op Linux is een kernelfout een negatieve foutcode. De gebruikelijke C-wrapperfunctie rapporteert -1 en stelt errno in. Als open("missing.txt", O_RDONLY) bijvoorbeeld mislukt omdat het bestand niet bestaat, is errno ENOENT. perror("missing.txt") kan “missing.txt: No such file or directory” tonen. Bekijk errno na een gemelde fout, niet als primaire test voor succes: een geslaagde aanroep hoeft een eerdere fout niet te wissen.

Houd rekening met tijd in de kernel

Een aanroep die meteen kan worden voltooid, kan naar hetzelfde proces terugkeren. Een blokkerende leesbewerking van de terminal kan dat proces daarentegen in de geblokkeerde toestand brengen en een ander laten draaien. De invoergebeurtenis maakt de lezer gereed; zodra die wordt ingepland, voltooit hij het terugkeerpad.

Toegang tot de kernel kost meer werk dan een normale functieaanroep: toestand opslaan, privileges veranderen, argumenten controleren en de uitvoering herstellen. Buffering in de bibliotheek kan kleine uitvoerstukken combineren tot minder schrijfbewerkingen. Op Linux voert strace ls het commando ls uit en rapporteert daarbij de systeemaanroepen, argumenten en resultaten.

Belangrijkste punten

  • Een bibliotheekfunctie kan al haar werk in de gebruikersruimte doen of systeemaanroepen uitvoeren.
  • Een dienstnummer selecteert een kernelbewerking; de aanroeper kiest geen willekeurig kerneladres.
  • Kernelcode controleert descriptoren, pointers en andere argumenten.
  • Gebruik de retourwaarde om een fout te ontdekken en bekijk daarna errno.
  • Een blokkerende systeemaanroep kan een contextwisseling veroorzaken; alleen de kernel binnengaan hoeft dat niet te doen.
  • Systeemaanroepnummers en registerconventies hangen af van het besturingssysteem en de architectuur.

4.3 Onderscheid traps, excepties en interrupts

Toegang tot de kernel kan een dienstverzoek, een instructieprobleem of een apparaatgebeurtenis betekenen. Door de oorzaak in te delen kun je voorspellen wat het besturingssysteem zal doen en of dezelfde instructie opnieuw moet worden uitgevoerd.

Vraag wat de gebeurtenis veroorzaakte
GebeurtenisOorzaakTijdstip ten opzichte van de huidige instructie
SysteemaanroeptrapHet programma vraagt bewust om een dienstSynchroon
Exceptie of foutDe huidige instructie vereist speciale afhandelingSynchroon
Hardware-interruptEen timer of apparaat geeft een signaal aan de CPUAsynchroon

Synchroon betekent gekoppeld aan de instructie die wordt uitgevoerd. Het betekent niet dat dezelfde invoer bij elke uitvoering precies dezelfde fouten veroorzaakt. Een laadinstructie kan een fout veroorzaken wanneer de pagina ontbreekt en later slagen wanneer die pagina in het geheugen staat. Asynchroon betekent dat de oorzaak van de gebeurtenis onafhankelijk is van de huidige instructie, zoals een schijf die eerder werk voltooit.

CPU-handleidingen gebruiken deze termen op verschillende manieren. Let op de oorzaak: een bewust dienstverzoek, een door een instructie veroorzaakte gebeurtenis of een hardwaremelding.

Verwijs door naar de juiste afhandelaar

Bij het opstarten installeert het besturingssysteem beschermde adressen van afhandelaars. Een trap- of interrupttabel koppelt soorten gebeurtenissen aan kernelroutines. Op x86-64 dient de interruptdescriptortabel (IDT) voor interrupts en excepties; syscall gebruikt een ingangsadres in een speciaal processorregister. Alleen geprivilegieerde code kan deze bestemmingen instellen.

Bij een interrupt vanuit de gebruikersmodus slaat x86-64-hardware een terugkeerframe op een kernelstack op. Ingangscode slaat extra registers op voordat de afhandeling begint. Het syscall-pad bewaart de initiële terugkeertoestand in registers en vertrouwt op ingangscode om de kernelstack in te richten. Als je alle toegangspaden als identieke hardwareacties behandelt, verberg je een belangrijk verschil in implementatie.

Kies de uitkomst

Een geldige pagina die niet in het geheugen staat, kan worden geladen, waarna de instructie die de fout veroorzaakte opnieuw wordt geprobeerd. Toegang tot geheugen dat het proces niet mag gebruiken, leidt er normaal toe dat Linux SIGSEGV stuurt. Een exceptie is dus niet altijd fataal en ook niet altijd een verzoek om de huidige instructie over te slaan.

Bij een daadwerkelijke x86-64-instructie idiv voor deling van gehele getallen met deler nul veroorzaakt de CPU een deelfoutexceptie. Linux levert normaal SIGFPE af; de bekende melding noemt drijvendekommagetallen, ook bij deze instructie voor gehele getallen. De instructie voor deling van gehele getallen op AArch64 geeft daarentegen nul bij een deler nul. Deling door nul in C is ongedefinieerd gedrag, dus overdraagbare C-code kan niet op een van beide machine-uitkomsten vertrouwen.

Wanneer een leesbewerking van de schijf eindigt, legt de interruptafhandelaar de voltooiing vast en maakt het wachtende proces gereed. Dat proces kan later draaien. Een timerinterrupt geeft het besturingssysteem de kans opnieuw te bepalen welk proces de CPU gebruikt, maar de afhandelaar kan ook naar hetzelfde proces terugkeren.

Onderscheid een signaal van een interrupt

Een hardware-interrupt stelt de CPU op de hoogte; een signaal stelt via het besturingssysteem een proces op de hoogte. Een exceptie kan ertoe leiden dat de kernel een signaal stuurt en één proces kan via kill om een signaal voor een ander proces vragen. Normale voltooiingen van apparaatbewerkingen zijn interrupts en betekenen niet dat er programmafouten zijn.

Kernelcode moet ook gedeelde gegevens beschermen terwijl gebeurtenissen optreden. De kernel kan interrupts op een CPU kort uitschakelen en waar nodig vergrendelingen gebruiken. Lange perioden met uitgeschakelde interrupts vertragen de afhandeling van apparaten; alleen lokale interrupts uitschakelen voorkomt niet dat een andere CPU toegang krijgt tot gedeelde gegevens.

Belangrijkste punten

  • Traps en excepties ontstaan door de huidige instructie; hardware-interrupts hebben een externe oorzaak.
  • Een herstelbare fout kan worden verholpen en de bijbehorende instructie kan opnieuw worden geprobeerd.
  • Beschermde toegangstabellen voorkomen dat gebruikersprogramma's kernelafhandelaars vervangen.
  • Een signaal is gericht op een proces; een hardware-interrupt is gericht op afhandeling door de CPU.
  • Voltooiing van een apparaatbewerking maakt een geblokkeerd proces gereed en een timerinterrupt hoeft niet tot een proceswisseling te leiden.
5

Leg uit hoe het besturingssysteem de CPU deelt met beperkte directe uitvoering

Snelle uitvoering en controle door het besturingssysteem moeten samengaan. Beperkte directe uitvoering laat gewone instructies op de hardware draaien terwijl modi, beschermde ingangspunten en een timer de kernel de controle laten behouden. Volg wat gebeurt wanneer het besturingssysteem naar hetzelfde proces terugkeert en wanneer het een ander proces hervat. De opgeslagen toestand en wisselkosten verklaren hoe korte CPU-beurten interactief werk kunnen ondersteunen.

5.1 Leg beperkte directe uitvoering uit

Elke instructie van een toepassing in een softwaresimulator uitvoeren zou het delen van de CPU duur maken. Een toepassing onbeperkte controle over de machine geven zou delen onveilig maken. Beperkte directe uitvoering (LDE) gebruikt gewone uitvoering op de hardware met een beschermd pad terug naar het besturingssysteem.

Los twee verschillende besturingsproblemen op

Directe uitvoering betekent dat de gewone instructies van een proces op de CPU zelf worden uitgevoerd. Het besturingssysteem onderzoekt en keurt niet elke rekeninstructie goed. Twee problemen blijven over: bewerkingen beperken die de machine kunnen beschadigen en de controle terugkrijgen wanneer een programma niet vrijwillig stopt.

De gebruikersmodus lost het beperkingsprobleem op. Via systeemaanroeptraps kan een programma diensten aanvragen zonder willekeurige geprivilegieerde code te kiezen. Een hardwaretimer lost het besturingsprobleem op: die kan een toepassing onderbreken die helemaal geen aanroepen doet. Samen ondersteunen deze mechanismen CPU-virtualisatie met weinig overhead.

Bereid de uitvoering van toepassingen voor

Bij het opstarten stelt de kernel gebeurtenisafhandelaars in en initialiseert hij de timer. Deze instelbewerkingen zijn geprivilegieerd. Latere gebruikersprogramma's kunnen de afhandelaars niet omleiden of de timer uitschakelen om te voorkomen dat hun beurt eindigt.

Om een proces te starten maakt het besturingssysteem zijn beheervermelding en geheugenbeeld aan, bereidt het opstartargumenten en een gebruikersstack voor en stelt het initiële registerwaarden in. Het zorgt voor een initiële opgeslagen context zodat de normale terugweg van kernel naar gebruiker het programma kan starten. Conceptueel begint het proces door terug te keren uit een trap die het nooit heeft veroorzaakt.

De gedetailleerde indeling van het opgeslagen frame hangt af van de CPU en het besturingssysteem. Het bruikbare ontwerpidee is hergebruik: dezelfde herstelmechanismen kunnen een onderbroken proces hervatten of een nieuw voorbereid proces starten.

Keer vrijwillig terug naar de kernel

Tijdens een systeemaanroep bewaart de hardware de initiële terugkeertoestand en draagt de controle over. Ingangscode van de kernel slaat de extra registers op de kernelstack van het proces op. Na voltooiing van een niet-blokkerend verzoek herstelt de kernel het proces en keert terug naar de gebruikersmodus. Als het verzoek blokkeert, kan eerst een ander gereed proces draaien.

Wanneer main terugkeert, vraagt de beëindigingsverwerking van de runtime uiteindelijk aan de kernel om het proces te beëindigen. Het geheugen kan worden vrijgegeven terwijl de beëindigingsgegevens bewaard blijven totdat een ouderproces die ophaalt.

Keer terug zonder medewerking

Een coöperatief systeem is afhankelijk van programma's die aanroepen doen, de CPU-beurt afstaan of excepties veroorzaken. Een eindeloze lus die geen van die dingen doet, kan een CPU monopoliseren. Het klassieke Mac OS illustreert deze zwakte.

Een niet-coöperatief ontwerp gebruikt een timerinterrupt om toegang tot de kernel af te dwingen. Neem een leermodel met één logische CPU en een periodieke timer die om de 4 ms afgaat. De timer produceert 1.000 / 4 = 250 tikken per seconde. Een gebruikersproces dat vastzit in while (1) { } wordt bij de volgende tik onderbroken. De kernel kan dan een ander gereed proces uitvoeren; de lus hoeft niet eerst een systeemaanroep te bereiken.

De tik is een kans om te handelen, geen verplichting om van proces te wisselen. De scheduler kan het onderbroken proces laten doorgaan. Timerafhandeling en herstel van de opgeslagen toestand zijn mechanismen; de keuze van de scheduler is beleid. De werkelijke responstijd hangt ook af van kernelwerk en van wanneer interrupts kunnen worden afgehandeld, dus een timerperiode op zichzelf garandeert geen responstijd van een toepassing.

Belangrijkste punten

  • LDE voert gewone gebruikersinstructies rechtstreeks uit met beperkingen die door de hardware worden afgedwongen.
  • De gebruikersmodus beperkt bewerkingen; systeemaanroepen bieden gecontroleerde geprivilegieerde diensten.
  • Een timer laat het besturingssysteem de controle terugkrijgen zonder medewerking van gebruikerscode.
  • Instellingen bij het opstarten beschermen de adressen van afhandelaars en de timerconfiguratie.
  • Een timertik geeft de scheduler een keuze; die vereist geen proceswisseling.

5.2 Volg een contextwisseling en schat de kosten ervan

Naar de kernelmodus gaan verandert niet noodzakelijk het draaiende proces. Een contextwisseling vindt plaats wanneer de kernel de uitvoeringstoestand van het ene proces bewaart en die van een ander hervat. Dit vereist zowel het bewaren van de gebruikerstoestand als een verandering in de eigen uitvoeringscontext van de kernel.

Volg hoe A wordt onderbroken en B wordt hervat

Volg voor een wisseling op x86-64 door de timer de lagen:

  1. A voert gebruikersinstructies uit. De timer onderbreekt A.
  2. De hardware gaat naar de kernelmodus en slaat het interruptterugkeerframe van A op de kernelstack van A op. Ingangscode slaat daar de overige gebruikersregisters van A op.
  3. De scheduler kiest B. De wisselroutine slaat de uitvoeringscontext van de kernel voor A op en herstelt de opgeslagen kernelcontext van B, inclusief zijn kernelstackpointer.
  4. De kernel schakelt waar nodig naar de adresruimtecontext van B. De kernel draait nu namens B met de kernelstack van B.
  5. De afsluitcode van de kernel herstelt de gebruikersregisters van B. De terugkeerinstructie herstelt de terugkeertoestand van B en gaat naar de gebruikersmodus. B gaat verder waar het eerder stopte.

De eerste opslag bewaart de onderbroken gebruikersuitvoering van A. De tweede bewaart waar de kernel was tijdens de afhandeling voor A. Het zijn geen twee identieke volledige kopieën van dezelfde registerverzameling. Een PCB of bijbehorende contextstructuur en de kernelstack per proces werken samen om de toestand te bewaren.

Herken de gebeurtenis en de beslissing

Een blokkerende aanroep, procesbeëindiging of een beslissing bij een timerinterrupt kan tot een wisseling leiden. Een apparaatinterrupt kan een ander proces gereed maken, waarna de scheduler dat kan kiezen. Alle wisselmechanismen draaien in de kernel; een toepassing slaat haar eigen registers niet op om zich voor onderbreking beschikbaar te stellen.

SituatieModusovergang?Ander proces?
Niet-blokkerende dienst keert terug naar de aanroeperGebruiker → kernel → gebruikerNee
Timer afgehandeld, hetzelfde proces wordt hervatGebruiker → kernel → gebruikerNee
A blokkeert en B wordt hervatToegang tot kernel, daarna terugkeerpad van BJa

Een contextwisseling bewaart de uitvoeringstoestand die nodig is om door te gaan. De tijd verstrijkt en de buitenwereld kan veranderen: gedeelde bestandsposities en externe invoer worden niet bevroren terwijl een proces is onderbroken.

Houd rekening met directe en indirecte kosten

Direct werk omvat het uitvoeren van de scheduler, het opslaan en herstellen van registers en het selecteren van een adresruimte. Vertaalcaches moeten mogelijk worden aangepast; vertalingen met labels kunnen voorkomen dat alle oude vermeldingen worden weggegooid. Indirecte kosten volgen wanneer B CPU-caches of gecachte adresvertalingen opnieuw moet vullen die door A zijn verdrongen. De kosten hangen af van hardware en werklast, dus gebruik gemeten of gegeven waarden wanneer je overhead berekent.

Stel dat een wisseling, inclusief de relevante effecten, 5 µs kost en nuttige CPU-beurten 10 ms duren. Zet 10 ms om naar 10.000 µs. Het wisselaandeel is 5 / (10.000 + 5), ongeveer 0,05%. Voor nuttige beurten van 1 ms is dat 5 / 1005, ongeveer 0,50%; bij 0,1 ms is dat 5 / 105, ongeveer 4,8%.

De noemer bevat nuttig werk plus wisseltijd voor één herhaalde cyclus. Een kortere beurt kan meer kansen bieden voor interactief werk, maar besteedt een groter aandeel aan herhaald wisselen. De timer en wisselcode maken korte beurten mogelijk; het planningsbeleid moet die kosten afwegen tegen de reactiesnelheid.

Belangrijkste punten

  • Na toegang tot de kernel kan de uitvoering naar hetzelfde proces terugkeren zonder contextwisseling.
  • Het opslaan van de gebruikerstoestand bij binnenkomst en van de kernelcontext tijdens een wisseling dient verschillende doelen.
  • Om B te hervatten zijn de kernelstack, opgeslagen registers en adresruimtecontext van B nodig.
  • Wisselkosten omvatten directe administratie en het later opnieuw vullen van caches of adresvertalingen.
  • Het overheadaandeel is de wisselkosten gedeeld door de nuttige beurt plus de wisselkosten.
  • Kortere beurten vergroten het wisselaandeel bij vaste kosten per wisseling.

Processen en systeemaanroepen: voorbeelden

5 Walkthroughs

1

Bekijk wat het besturingssysteem bijdraagt

12 stappen
Volg gedeelde bronnen van een toepassingsverzoek naar kerneldiensten en vergelijk daarna de ontwerpen die gedeeld gebruik mogelijk maken.
  1. 1
    IntroductieBegin met meerdere programma's

    Stel je een laptop voor die een project compileert terwijl hij muziek afspeelt en netwerkgegevens ontvangt. Elke toepassing heeft CPU-tijd, geheugen en I/O nodig, maar geen enkele bestuurt de hele machine.

    Volg wie die bronnen levert, hoe meerdere taken voortgang maken en waar de geprivilegieerde diensten draaien. De terugkerende vraag is concreet: welk werk vraagt de toepassing aan en welk werk moet het besturingssysteem beheren?

  2. 2
    UitlegVerberg de apparaatdetails

    Het besturingssysteem biedt abstracties: bruikbare interfaces die de onderliggende werking verbergen. Een programma opent een bestand en leest bytes zonder commando's voor elk opslagapparaat te implementeren.

    Een systeemaanroep vraagt via een gecontroleerde interface een kerneldienst aan. De kernel controleert en voert het beschermde werk uit. De toepassing beslist nog steeds welke gegevens ze wil; ze krijgt geen toestemming om het apparaat rechtstreeks aan te sturen.

  3. 3
    VoorbeeldVolg een uitvoerbestand van een compiler

    Een compiler produceert bytes voor een uitvoerbaar bestand en vraagt een schrijfbewerking aan. De kernel controleert de uitvoerbron en handelt het opslagwerk achter de bestandsinterface af.

    Tegelijk beheert het besturingssysteem het geheugen van de compiler en deelt het CPU-tijd met de muziekspeler. Eén handeling, een bestand opslaan, valt dus onder meerdere taken van het besturingssysteem: abstractie, beheer van bronnen en bescherming van de andere programma's.

  4. 4
    KernpuntGeef elk proces een bruikbare machine

    Virtualisatie presenteert een fysieke bron via een bruikbare afgeschermde weergave. Een proces kan voortgang maken alsof het een eigen processor heeft, ook al worden zijn instructies afgewisseld met die van andere processen.

    Ook zijn geheugenweergave is afgeschermd: het adres dat het gebruikt hoeft in een ander proces niet dezelfde fysieke bytes aan te duiden. CPU- en geheugenvirtualisatie geven programma's handige modellen terwijl het besturingssysteem de werkelijke gedeelde hardware beheert.

  5. 5
    UitdagingZoek het geprivilegieerde deel

    Op een computer is geen grafische desktop geïnstalleerd, maar hij voert diensten uit, slaat bestanden op en verdeelt CPU-tijd. Is de essentiële kern van het besturingssysteem verdwenen? Leg uit.

    ---reveal---

    Nee. De kernel beheert nog steeds processen, geheugen en apparaatdiensten. Een grafische desktop is een gebruikersprogramma boven op die diensten. Door het ontbreken ervan verandert de interface die iemand ziet, maar blijft het beheer van bronnen door de kernel nodig.

  6. 6
    UitlegScheid de bewerking van de keuze

    Een mechanisme maakt een handeling mogelijk. De registers van het ene proces opslaan en die van een ander herstellen biedt het mechanisme om te wisselen.

    Beleid bepaalt hoe je dat gebruikt, bijvoorbeeld door te beslissen welk gereed proces de volgende CPU-beurt krijgt. Het onderscheid is van belang wanneer een ontwerp verandert: een nieuwe keuzeregel kan dezelfde betrouwbare wisselcode hergebruiken. Efficiënte mechanismen alleen bepalen niet wat eerlijk is.

  7. 7
    UitlegBenut anders ongebruikte wachttijd

    Een batchsysteem kan de CPU ongebruikt laten terwijl de huidige taak op I/O wacht. Multiprogrammering houdt andere taken beschikbaar en voert er tijdens die wachttijd één uit.

    De wachtende taak rekent niet en het apparaat is niet sneller geworden. De winst komt van overlappend onafhankelijk werk: het ene proces wacht terwijl een ander de CPU gebruikt. Meerdere programma's in het geheugen vereisen ook bescherming zodat het ene niet het geheugen van het andere kan overschrijven.

  8. 8
    VoorbeeldBereken de winst in bezettingsgraad

    Een taak rekent 20 ms en wacht daarna 80 ms op I/O. Als de taak alleen draait, bevat één cyclus van 100 ms slechts 20 ms CPU-werk: de bezettingsgraad is 20%.

    Met een tweede dergelijke taak en geschikte overlap kan nog eens 20 ms aan berekeningen anders ongebruikte tijd vullen, wat in dit voorbeeld tot 40% oplevert. De verbetering benut wachttijd productief; taken toevoegen kan de CPU-bezettingsgraad niet boven 100% brengen.

  9. 9
    VerbandGeef interactief werk korte beurten

    Tijdsverdeling geeft processen korte CPU-beurten zodat interactief werk niet op een volledige batchtaak hoeft te wachten. Dit is gelijktijdigheid, zelfs op één logische CPU: meerdere activiteiten maken voortgang door afwisseling.

    Parallellisme vereist daadwerkelijke gelijktijdige uitvoering op afzonderlijke verwerkingsbronnen. Geheugen- en schijfcapaciteit illustreren een andere verdeling, ruimteverdeling, waarbij verschillende gebruikers tegelijk over afzonderlijke delen beschikken.

  10. 10
    UitlegKies een grens voor diensten

    Een monolithische kernel, zoals Linux, voert de meeste diensten samen met privileges uit. Rechtstreekse aanroepen zijn efficiënt, maar een defect stuurprogramma kan de kerneltoestand beschadigen.

    Een microkernel, zoals seL4, laat meer diensten in afzonderlijke gebruikersprocessen draaien. Isolatie kan een storing in een dienst beperken, ten koste van communicatie en modusovergangen. Windows NT en XNU combineren benaderingen. De grens bepaalt welke storingen zich kunnen verspreiden en welke diensten opnieuw kunnen worden gestart.

  11. 11
    UitdagingVerbind delen en bescherming

    Een systeem met één CPU voert meerdere taken uit en schakelt naar een andere wanneer er één op schijf-I/O wacht. Een voorstel zou elke taak elk geheugenadres laten overschrijven. Leg het voordeel voor de bezettingsgraad en de fout in dit voorstel uit.

    ---reveal---

    Multiprogrammering vult I/O-wachttijd met berekeningen van een andere taak. Onbeperkt schrijven zou één taak een andere of het besturingssysteem laten beschadigen. Overlappend werk verbetert het gebruik van bronnen, maar gedeeld gebruik vereist nog steeds afgedwongen bescherming van geheugen en privileges.

  12. 12
    SamenvattingBeoordeel een ontwerp met drie vragen

    Vraag bij het ontwerp van een besturingssysteem welke bron wordt gedeeld, welke interface een programma ziet en welke grens ander werk beschermt.

    Deze vragen verbinden CPU-virtualisatie met procesbeurten, bestanden met verborgen apparaatdetails en kernelorganisatie met foutisolatie. Mechanismen voeren beschermde bewerkingen uit; beleid bepaalt hoe het gebruik ervan wordt verdeeld. Gelijktijdigheid kan voortkomen uit afwisseling op één CPU.

2

Volg een proces tijdens CPU- en I/O-werk

13 stappen
Lees de gegevens van een proces en bouw daarna een tijdlijn die uitvoering, wachten op een CPU en wachten op een gebeurtenis onderscheidt.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieVolg een actieve instantie
  2. 2
    UitlegMaak van een bestand een proces
  3. 3
    UitlegBewaar de volgende instructie
  4. 4
    VoorbeeldLees een processenoverzicht
  5. 5
    UitdagingInterpreteer gelijke adressen
  6. 6
    TipBekijk descriptoren als geërfde bronnen
  7. 7
    UitlegVraag wat ontbreekt
  8. 8
    VoorbeeldBegin de tijdlijn
  9. 9
    VoorbeeldVoltooi de tijdlijn
  10. 10
    UitdagingVerander de keuze voor een gereed proces
  11. 11
    VerbandHerken echte toestandsnamen
  12. 12
    UitdagingVerbind procesgegevens met CPU-capaciteit
  13. 13
    SamenvattingLees de toestand als geschiktheid voor uitvoering
3

Bouw een commando met procesaanroepen

23 stappen
Volg een kindproces vanaf fork via programmavervanging, het ophalen van het resultaat en omleiding tot een aangesloten pijplijn.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieGeef elke aanroep één taak
  2. 2
    UitlegSplits één uitvoering in twee
  3. 3
    VoorbeeldVolg een afgeschermde waarde
  4. 4
    VoorbeeldTel een vertakking, niet de aanroepen in de broncode
  5. 5
    UitdagingTel de paden die afdrukken
  6. 6
    TipControleer wat is gekopieerd
  7. 7
    UitlegVervang het programma van het kindproces
  8. 8
    VoorbeeldGeef afzonderlijke argumentstrings door
  9. 9
    UitdagingVoorspel een geslaagde vervanging
  10. 10
    KernpuntGebruik de tijd vóór exec
  11. 11
    UitlegHaal één resultaat van een kindproces op
  12. 12
    VoorbeeldDecodeer normale beëindiging
  13. 13
    UitlegLaat geen resultaten ongehaald
  14. 14
    UitdagingHandel onderbreking correct af
  15. 15
    TipKies een beëindigingsverzoek
  16. 16
    UitlegKeer terug naar een prompt op de voorgrond
  17. 17
    VoorbeeldLeid uitvoer om vóór vervanging
  18. 18
    UitdagingBehoud de uitvoerbestemming
  19. 19
    VoorbeeldVerbind de twee kanten van de pipe
  20. 20
    KernpuntStart voordat je wacht
  21. 21
    VerbandHoud achtergrondwerk bij
  22. 22
    UitdagingVolg een lege pijplijn
  23. 23
    SamenvattingHoud identiteit, beeld en resultaat bij
4

Volg een verzoek over de privilegegrens

15 stappen
Volg een dienstverzoek naar de kernel en vergelijk het daarna met instructiefouten en externe apparaatgebeurtenissen.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieVraag waarom de kernel is binnengegaan
  2. 2
    UitlegBeperk wat toepassingen kunnen besturen
  3. 3
    VoorbeeldScheid identiteit van privileges
  4. 4
    UitdagingVoorspel een verboden instructie
  5. 5
    UitlegZoek de werkelijke systeemaanroep
  6. 6
    VoorbeeldBereid één schrijfbewerking voor
  7. 7
    VoorbeeldGa binnen en controleer
  8. 8
    VoorbeeldInterpreteer de retourwaarde
  9. 9
    UitdagingVolg een geblokkeerde leesbewerking
  10. 10
    UitlegDeel in op basis van de oorzaak
  11. 11
    VoorbeeldHerstel of beëindig
  12. 12
    TipHoud signalen op procesniveau
  13. 13
    UitdagingDeel een voltooiing van een apparaatbewerking in
  14. 14
    UitdagingOnderscheid twee soorten toegang
  15. 15
    SamenvattingVolg oorzaak, controles en uitkomst
5

Behoud controle terwijl programma's rechtstreeks worden uitgevoerd

15 stappen
Volg de door de timer gestuurde controle tot een wisseling tussen processen en schat daarna welk deel van de tijd het wisselen verbruikt.

Sla deze les op om elke Walkthrough stap voor stap te volgen.

  1. 1
    IntroductieCombineer snelheid en controle
  2. 2
    UitlegLos twee besturingsproblemen op
  3. 3
    VoorbeeldBereid de machine en het proces voor
  4. 4
    VerbandBekijk de zwakte van de coöperatieve aanpak
  5. 5
    VoorbeeldOnderbreek een eindeloze lus
  6. 6
    UitdagingBepaal welk mechanisme ontbreekt
  7. 7
    UitlegSla het onderbroken gebruikerspad op
  8. 8
    VoorbeeldSla ook het kernelpad op
  9. 9
    VoorbeeldKeer terug via de opgeslagen toestand van B
  10. 10
    UitdagingHerken een overgang zonder proceswisseling
  11. 11
    UitlegTel de kosten na een wisseling
  12. 12
    VoorbeeldBouw de noemer voor de volledige cyclus op
  13. 13
    UitdagingSchat een veranderde beurtlengte
  14. 14
    UitdagingVerbind een geblokkeerde aanroep met hervatting
  15. 15
    SamenvattingVolg bij wie het terugkeerpad hoort

Processen en systeemaanroepen: oefenvragen

50 Oefenvragen in 5 sets

Set 1: Maak en vervang een proces en haal zijn resultaat op10 Oefenvragen

Vraag 1 van 10

Een ouderproces ontvangt 7421 van een geslaagde fork. Welke waarde geeft diezelfde fork terug in het kindproces?
  1. 7421
  2. -1
  3. 0
  4. De PID van het ouderproces
Toon antwoordVerberg antwoord
Antwoord: C
Het geslaagde pad van het kindproces ontvangt 0, terwijl het ouderproces de positieve PID van het kindproces ontvangt, hier 7421. Het kindproces kan getpid() aanroepen om zijn eigen identificatie te vinden. Als in beide paden de PID van het kindproces werd teruggegeven, zou het onderscheid in retourwaarden verdwijnen waarmee gedrag voor ouderproces en kindproces wordt gekozen.

Vraag 2 van 10

Elke fork slaagt. Hoeveel processen bereiken puts("done") in deze code?

if (fork() == 0) {
    fork();
}
puts("done");
  1. 2
  2. 3
  3. 4
  4. 5
Toon antwoordVerberg antwoord
Antwoord: B
De eerste fork maakt een ouderproces en een kindproces aan. Alleen het kindproces gaat de vertakking in en voert nog eenmaal fork uit, dus het oorspronkelijke ouderproces plus twee processen aan de kant van het kindproces bereiken puts: in totaal drie. Als je twee aanroepen in de broncode telt als automatische verdubbeling tot vier, negeer je de vertakking die het oorspronkelijke ouderproces uitsluit.

Vraag 3 van 10

Een programma met één thread laat “ready” achter in een volledig gebufferde uitvoerstroom zonder die tekst weg te schrijven en voert daarna met succes fork uit. Beide processen roepen exit aan zonder verdere uitvoer. Wat kan de bestemming ontvangen?
  1. Geen kopie, omdat fork wachtende uitvoer wist
  2. Eén kopie, omdat de stroom één descriptor heeft
  3. Eén kopie, alleen als het kindproces eerst eindigt
  4. Twee kopieën, omdat elk proces een gekopieerde buffer wegschrijft
Toon antwoordVerberg antwoord
Antwoord: D
De wachtende tekst staat in gebruikersgeheugen, dat naar de afgeschermde toestand van het kindproces wordt gekopieerd. Bij beide normale beëindigingen wordt de eigen kopie weggeschreven, zodat de bestemming “ready” tweemaal kan ontvangen. Een gedeeld onderliggend uitvoerbestand voegt de twee buffers in de gebruikersruimte niet samen tot één buffer.

Vraag 4 van 10

Een proces met PID 8502 voert met succes een nieuw programma uit met exec. Wat is de proces-ID van het nieuwe programma?
  1. 8502
  2. 8503
  3. 0
  4. De PID van het ouderproces
Toon antwoordVerberg antwoord
Antwoord: A
Exec vervangt het programmabeeld binnen het aanroepende proces, dus het proces behoudt PID 8502. Het maakt geen kindproces aan en kent geen nieuwe procesidentiteit toe. Een nieuwe PID hoort bij het aanmaken van een ander proces, niet bij een geslaagde vervanging van het programma van een bestaand proces.

Vraag 5 van 10

Een programma is geïnstalleerd op /opt/course/bin/checker en PATH bevat /opt/course/bin. Er is geen bestand met de naam checker in de huidige directory. Waarom kan execv("checker", args) het niet vinden?
  1. Execv doorzoekt PATH alleen als args[0] een absolute padnaam is.
  2. Execv doorzoekt alleen de directory van het aanroepende programma.
  3. Execv behandelt de naam als padnaam en doorzoekt PATH niet.
  4. Execv doorzoekt PATH pas nadat zoeken in de huidige directory is mislukt.
Toon antwoordVerberg antwoord
Antwoord: C
execv gebruikt het padnaamargument rechtstreeks, dus “checker” verwijst in dit geval naar de huidige directory. execvp zou de opgegeven PATH-omgeving doorzoeken. De argumentvectorvorm betekent niet dat PATH wordt doorzocht; dat gedrag hoort bij de p-variant.

Vraag 6 van 10

Een kindproces roept exit(515) aan. Wat rapporteert WEXITSTATUS na een geslaagde wachtbewerking en een WIFEXITED-test die waar is?
  1. 515
  2. 512
  3. 255
  4. 3
Toon antwoordVerberg antwoord
Antwoord: D
Alleen de laagste acht bits van de normale afsluitwaarde worden gerapporteerd, dus 515 modulo 256 is 3. Het ouderproces moet eerst vaststellen dat de beëindiging normaal was voordat het WEXITSTATUS gebruikt. Wie de oorspronkelijke waarde 515 terugverwacht, houdt geen rekening met de resultaatinterface van acht bits; die is niet hetzelfde als de opslag van een willekeurig geheel getal in C.

Vraag 7 van 10

Een ouderproces heeft één draaiend kindproces. Zijn waitpid(child, &status, WNOHANG) geeft 0 terug. Wat is er gebeurd?
  1. Het kindproces is met succes geëindigd.
  2. Er is geen resultaat van het kindproces klaar, dus het ouderproces gaat verder.
  3. Het kindproces hoort niet meer bij het ouderproces.
  4. Het ouderproces heeft een kindproces met PID 0 opgehaald.
Toon antwoordVerberg antwoord
Antwoord: B
Met WNOHANG betekent nul dat het passende kindproces bestaat, maar dat geen gevraagd resultaat beschikbaar is. Het ouderproces keert onmiddellijk terug zonder de beëindigingsstatus op te halen. Het is niet de afsluitcode van het kindproces: de retourwaarde van waitpid identificeert bij succes een kindproces en gebruikt een afzonderlijk statusobject om te melden hoe dat kindproces eindigde.

Vraag 8 van 10

Een kindproces van een server heeft toestand Z. Na het sturen van SIGKILL blijft de vermelding zichtbaar. Welke handeling maakt de bewaarde resultaatgegevens van dit kindproces vrij?
  1. Het ouderproces haalt de status op met een wachtbewerking.
  2. Het kindproces handelt SIGTERM af en roept exit aan.
  3. De scheduler geeft het kindproces nog een CPU-beurt.
  4. Het ouderproces stuurt SIGCONT en daarna SIGSTOP.
Toon antwoordVerberg antwoord
Antwoord: A
Het kindproces is al beëindigd; zijn zombievermelding blijft bestaan zodat het ouderproces zijn resultaat kan ophalen. Een geslaagde wachtbewerking haalt de beëindigingsstatus op en maakt de bewaarde gegevens vrij. SIGKILL kan het proces niet opnieuw laten eindigen en er is geen uitvoeringspad in het kindproces meer om een ander signaal af te handelen.

Vraag 9 van 10

Een shell leidt de standaarduitvoer van een kindproces om naar een bestand en voert een commando uit met exec. Het commando schrijft normaal, eindigt met succes en de shell toont weer een prompt. Waarom had het commando geen code voor omleiding nodig?
  1. Het ouderproces stuurt de uitvoer van het kindproces door nadat wait terugkeert.
  2. Exec interpreteert de omleidingstekst in de argumentvector.
  3. De descriptorinstellingen van het kindproces blijven behouden bij programmavervanging.
  4. Exec geeft het commando een nieuwe kopie van de descriptoren van het ouderproces.
Toon antwoordVerberg antwoord
Antwoord: C
Het kindproces verbindt descriptor 1 vóór exec met het bestand en die descriptor blijft behouden tenzij die is gemarkeerd om bij exec te sluiten. Het vervangende programma schrijft via zijn geërfde standaarduitvoer. Argumentstrings voeren shellomleiding niet automatisch uit en wachten in het ouderproces stuurt de schrijfbewerkingen van het kindproces niet door.

Vraag 10 van 10

Een shell start producer | consumer. De producent eindigt, maar de consument blijft na het lezen van alle beschikbare bytes eindeloos wachten. De shell heeft zijn kopieën van de pipe gesloten; de consument houdt zijn geërfde oorspronkelijke descriptor voor de schrijfkant nog open. Wat verhelpt het vastlopen?
  1. Wacht op de consument voordat je de leeskant van de shell sluit.
  2. Sluit de ongebruikte schrijfkant in de consument vóór exec.
  3. Sluit de leeskant van de consument wanneer de producent eindigt.
  4. Laat de shell de status van de producent ophalen voordat de leesbewerking begint.
Toon antwoordVerberg antwoord
Antwoord: B
De ongebruikte schrijfdescriptor van de consument houdt een schrijfkant open, zodat zijn eigen leesbewerking het bestandseinde niet kan bereiken nadat de gebufferde gegevens zijn verbruikt. Sluit die ongebruikte kant vóór exec. Wachten in de shell sluit geen descriptor die de consument openhoudt en de kanten van de pipe omwisselen zou niet de bedoelde bytestroom opleveren.
Set 2: Bronnen, processen en bescherming10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Een programma schrijft een bestand zonder te weten of de gegevens naar een SSD of een netwerkschijf gaan. Welk idee van het besturingssysteem maakt dit mogelijk?
  1. Tijdsverdeling van het opslagapparaat
  2. Een abstractie voor bestandsbewerkingen
  3. Parallelle uitvoering van apparaatverzoeken
  4. Een planningsbeleid voor het programma
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Een besturingssysteem verandert welk gereed proces de volgende beurt krijgt, maar laat zijn routine voor het opslaan van registers ongewijzigd. Wat is veranderd?
  1. De indeling van de adresruimte
  2. Het privilegiemechanisme
  3. Het registerformaat
  4. Het planningsbeleid
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Een taak rekent herhaaldelijk 15 ms en wacht daarna 45 ms op I/O. Welke CPU-bezettingsgraad bereikt de taak als ze de enige taak is en je wisseloverhead negeert?
  1. 25%
  2. 33,3%
  3. 75%
  4. 15%
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Twee programma's krijgen herhaaldelijk om de beurt één logische CPU voordat een van beide klaar is. Hoe wordt hun uitvoering beschreven?
  1. Parallel, met uitvoering op hetzelfde moment
  2. Sequentieel, waarbij elk eerst wordt voltooid
  3. Gelijktijdig, met afwisselende uitvoering
  4. Met ruimteverdeling en blijvende CPU-indeling
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een processenoverzicht toont PID 9641, PPID 9600 en commandonaam “sort”. Welk proces is het ouderproces?
  1. Het proces met PID 9600
  2. Het proces met PID 9641
  3. Elk proces met de naam “sort”
  4. Het proces aangemaakt na 9641
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Twee afzonderlijk gestarte exemplaren van een programma drukken hetzelfde virtuele adres af voor een afgeschermde variabele. Eén exemplaar verandert zijn waarde. Wat volgt daaruit voor het andere exemplaar?
  1. Het ziet dezelfde schrijfbewerking omdat de virtuele adressen gelijk zijn.
  2. Het ziet de schrijfbewerking pas als beide processen weer de kernel binnengaan.
  3. Het behoudt zijn waarde alleen tot zijn volgende opgeslagen context wordt hersteld.
  4. Het behoudt zijn waarde omdat zijn adresruimte gescheiden is.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een proces kan verder rekenen, maar de timer heeft zijn CPU-beurt beëindigd. Wat is nu zijn basistoestand?
  1. Geblokkeerd, wachtend op voltooiing van de timer
  2. Gereed, wachtend op een volgende CPU-beurt
  3. Gestopt, wachtend op een hervattingssignaal
  4. Zombie, wachtend tot het ouderproces de status ophaalt
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Op één logische CPU draait M terwijl N voor een leesbewerking geblokkeerd is. Het apparaat voltooit de leesbewerking van N en de kernel keert terug naar M. Wat zijn direct daarna de twee basistoestanden?
  1. M gereed; N in uitvoering
  2. M in uitvoering; N geblokkeerd
  3. M in uitvoering; N gereed
  4. M geblokkeerd; N gereed
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Een onderhoudsprogramma draait met de identiteit root en vraagt een beschermde bestandsbewerking aan. In welke modus worden zijn eigen toepassingsinstructies uitgevoerd?
  1. Kernelmodus, omdat root toegangscontroles omzeilt
  2. Supervisormodus totdat het bestand is gesloten
  3. Gebruikersmodus alleen als het gevraagde bestand openbaar is
  4. Gebruikersmodus, waarbij de kernel de rechten controleert
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een nieuw besturingssysteem dwingt beperkingen in de gebruikersmodus en beschermde toegang via systeemaanroepen af, maar krijgt de CPU alleen terug wanneer een programma een aanroep doet of een fout veroorzaakt. Een gebruikersprogramma komt in een eindeloze rekenlus terecht. Waarom kan dit ontwerp tekortschieten bij het delen van één CPU?
  1. De lus kan elke ingestelde route terug naar het besturingssysteem vermijden.
  2. De lus staat automatisch de CPU-beurt af bij elke volgende vertakking.
  3. De kernel draait naast de lus op dezelfde logische CPU.
  4. De bescherming van de gebruikersmodus dwingt na elke instructie een keuze voor een gereed proces af.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 3: Volg toegang tot de kernel en CPU-wisselingen10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Waarom moet het wijzigen van de tabel met interruptafhandelaars geprivilegieerd zijn?
  1. Om te voorkomen dat gebruikerscode beschermde toegang tot de kernel omleidt
  2. Om te zorgen dat elk programma een ander systeemaanroepnummer gebruikt
  3. Om alle hardwaregebeurtenissen synchroon met gebruikersinstructies te maken
  4. Om bij toegang tot elke afhandelaar een nieuw proces te vereisen
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Een C-functie maakt meerdere korte berichten op in een uitvoerbuffer en draagt ze later met één schrijfbewerking over. Welke kosten vermindert deze bundeling?
  1. Het aantal tekens dat de toepassing moet opmaken
  2. De hoeveelheid geheugen voor het uitvoerbare bestand
  3. Het aantal processen dat de berichten moet bevatten
  4. Herhaalde administratie voor toegang tot de kernel en systeemaanroepen
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Een C-wrapperfunctie geeft bij open -1 terug en errno is ENOENT. Wat moet de aanroeper concluderen?
  1. Het bestand is met een ongebruikelijke descriptor geopend.
  2. Het verzoek is mislukt omdat het genoemde bestand niet is gevonden.
  3. Het verzoek heeft een kindproces aangemaakt dat nog niet klaar is.
  4. Het bestand is geopend maar het aantal bytes is afgekapt.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Een netwerkcontroller meldt dat een pakket is aangekomen terwijl een proces gehele getallen optelde. Wat voor gebeurtenis veroorzaakt hier toegang tot de kernel?
  1. Een synchrone rekenexceptie
  2. Een bewuste systeemaanroeptrap
  3. Een asynchrone hardware-interrupt
  4. Een softwaresignaal van de optelinstructie
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een instructie benadert een geldige pagina die momenteel niet in het geheugen aanwezig is. De kernel laadt de pagina met succes. Hoe kan de uitvoering verdergaan?
  1. Sla de instructie over omdat het resultaat al is opgeslagen.
  2. Beëindig het proces omdat elke exceptie fataal is.
  3. Maak een nieuw proces om de resterende instructies uit te voeren.
  4. Probeer de instructie opnieuw nu de benodigde pagina beschikbaar is.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Hoeveel timertikken per seconde treden op in een periodiek timermodel met één tik per 5 ms?
  1. 200
  2. 50
  3. 500
  4. 5000
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een proces gaat de kernel binnen voor een niet-blokkerende dienst. De afhandelaar is klaar en keert terug naar hetzelfde proces. Wat is er gebeurd?
  1. Een contextwisseling zonder verandering van privilegeniveau
  2. Een modusovergang zonder procescontextwisseling
  3. Een proceswisseling met behoud van de oorspronkelijke PID
  4. Een vervanging van het programma van het proces via exec
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Op één logische CPU doet A een niet-blokkerende schrijfbewerking waarna de uitvoering naar A terugkeert; daarna gaat een timerinterrupt de kernel binnen en keert de uitvoering terug naar A. Vervolgens doet A een blokkerende leesbewerking en wordt B hervat; B eindigt later via een systeemaanroep en C wordt hervat. Er zijn geen andere toegangen tot de kernel. Hoe vaak wordt van gebruikersmodus naar kernelmodus overgegaan en hoeveel procescontextwisselingen vinden plaats?
  1. 4 keer naar de kernel; 4 proceswisselingen
  2. 3 keer naar de kernel; 2 proceswisselingen
  3. 4 keer naar de kernel; 2 proceswisselingen
  4. 4 keer naar de kernel; 3 proceswisselingen
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Een toepassing plaatst een adres van beschermd kernelgeheugen in een schrijfbufferargument en doet een systeemaanroep. Waarom geeft gecontroleerde toegang op zichzelf geen toestemming voor de gevraagde leesbewerking vanaf dat adres?
  1. De kernel moet de buffertoegang van de aanroeper nog controleren.
  2. Het dienstnummer alleen staat elk opgegeven bufferadres toe.
  3. De registerinstelling van de wrapperfunctie bewijst al dat de pointer toegankelijk is.
  4. De moduswisseling maakt beschermd geheugen deel van de gebruikersbuffer.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een herhaalde CPU-cyclus biedt 2 ms nuttige uitvoering, gevolgd door contextwisselkosten van 8 µs. Welk deel van de cyclus wordt ongeveer aan wisselen besteed?
  1. 4,00%
  2. 0,004%
  3. 0,80%
  4. 0,398%
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 4: Volg procesgedrag en het delen van bronnen10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Eén logische CPU voert J 3 ms uit. J wacht daarna 5 ms op I/O en heeft nog 2 ms CPU-tijd nodig. K is aanvankelijk gereed en heeft 6 ms CPU-tijd nodig. K draait telkens wanneer J blokkeert en gaat door tot het klaar is; wisselkosten worden genegeerd. Wanneer zijn beide klaar?
  1. 10 ms
  2. 11 ms
  3. 14 ms
  4. 16 ms
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Met welke opgeslagen waarde kan de kernel de volgende instructie bepalen wanneer hij een onderbroken uitvoeringscontext hervat?
  1. De huidige directory
  2. De bestandspositie
  3. De PID van het ouderproces
  4. De programmateller
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Een proces met één thread heeft een afgeschermde x gelijk aan 6. Elke fork slaagt. Alle processen bereiken puts. Hoeveel regels bevatten “9”?

pid_t p = fork();
if (p == 0) x += 3;
fork();
if (x == 9) puts("9");
  1. 2
  2. 1
  3. 3
  4. 4
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Vóór een geslaagde fork verwijst een bestandsdescriptor naar positie 0 in een geopend bestand met “ABCDEFGH”. Het ouderproces leest precies drie bytes, waarna het kindproces via de geërfde descriptor precies twee bytes leest. Er vinden geen andere bewerkingen plaats. Wat leest het kindproces?
  1. “AB”
  2. “BC”
  3. “DE”
  4. “FG”
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een kindproces roept execvp aan voor een programma dat niet bestaat. De volgende opdracht drukt een fout af. Waarom kan die opdracht worden uitgevoerd?
  1. Exec start het nieuwe programma naast het oude aanroeppad.
  2. Elke geslaagde exec keert eenmaal terug voordat geheugen wordt vervangen.
  3. Het ouderproces voert automatisch alle foutopdrachten van het kindproces uit.
  4. De mislukte exec keert terug zonder het oude programma te vervangen.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Een ouderproces met twee actieve kindprocessen roept wait aan. Een signaalafhandelaar onderbreekt de aanroep, wat -1 en errno EINTR oplevert. Wat moet het ouderproces doen om de resultaten van kindprocessen te blijven ophalen?
  1. Stoppen omdat de status van beide kindprocessen is opgehaald.
  2. Opnieuw wachten in plaats van EINTR als voltooiing te behandelen.
  3. De ongewijzigde status decoderen met WEXITSTATUS.
  4. SIGKILL naar de eigen processentabelvermelding sturen.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een shell roept chdir alleen in een met fork aangemaakt kindproces aan om cd te implementeren, wacht op dat kindproces en start daarna een ander commando. Waarom begint het volgende commando in de oude directory?
  1. Wait zet de directory van het ouderproces altijd terug naar de beginwaarde.
  2. Exec negeert elke geërfde instelling van de huidige directory.
  3. De directorywijziging van het kindproces veranderde de oudershell niet.
  4. Chdir vereist dat de shell zelf in de kernelmodus draait.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Een shell maakt een pipe, maakt met fork alleen de producent aan en wacht daarop voordat hij de consument aanmaakt. De producent schrijft meer dan de pipe kan bevatten. Waarom kan deze startvolgorde vastlopen?
  1. De producent blokkeert op een volle pipe terwijl geen consument die kan legen.
  2. De kopie van de leeskant van het ouderproces verbruikt pas bytes nadat wait terugkeert.
  3. De producent bereikt het bestandseinde wanneer de pipe voor het eerst vol raakt.
  4. De producent kan zijn uitvoer niet sluiten voordat de status van het ouderproces is opgehaald.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

Een apparaatdienst draait in een afzonderlijke server in de gebruikersmodus en crasht. Het besturingssysteem start die dienst opnieuw terwijl niet-gerelateerde toepassingen doorgaan. Welke eigenschap van het kernelontwerp helpt deze uitkomst te verklaren?
  1. Alle diensten delen dezelfde geprivilegieerde adresruimte.
  2. Elk apparaatverzoek omzeilt de beschermingsregels van de kernel.
  3. De scheduler garandeert dat elke toepassing parallel draait.
  4. De dienst is geïsoleerd van de kleine geprivilegieerde kern.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Hetzelfde programma met dezelfde invoer veroorzaakt bij de ene uitvoering een paginafout maar bij een andere niet, omdat de benodigde pagina al in het geheugen staat. Hoe moet de fout bij de eerste uitvoering worden ingedeeld?
  1. Asynchroon, omdat de twee uitvoeringen verschilden
  2. Synchroon, omdat de geheugeninstructie die veroorzaakte
  3. Een hardware-interrupt die alleen door verstreken tijd ontstaat
  4. Een signaal dat rechtstreeks door de C-bibliotheekbuffer is aangemaakt
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Set 5: Analyseer interacties tussen processen en kernel10 Oefenvragen

Sla deze les op om elk antwoord te zien en elke set te oefenen.

Vraag 1 van 10

Het resultaat van een kindproces slaagt voor WIFSIGNALED nadat waitpid is geslaagd. Welke macro geeft het nummer van het beëindigende signaal?
  1. WEXITSTATUS(status)
  2. WIFEXITED(status)
  3. WTERMSIG(status)
  4. WNOHANG
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 2 van 10

Een wrapperfunctie voor schrijven meldt dat 5 bytes zijn geschreven uit een aangevraagde buffer van 9 bytes. Hoeveel aangevraagde bytes moeten nog worden overgedragen?
  1. 4 bytes
  2. 5 bytes
  3. 9 bytes
  4. 14 bytes
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 3 van 10

Een proces leest op Linux een ongeldig adres en de kernel levert SIGSEGV af. Welke volgorde onderscheidt de twee gebeurtenissen?
  1. Een processignaal wordt gevolgd door een geheugenexceptie van de CPU.
  2. Een asynchrone apparaatinterrupt wordt rechtstreeks als SIGSEGV afgeleverd.
  3. Een bewuste systeemaanroeptrap vraagt om aflevering van SIGSEGV.
  4. Een instructie-exceptie wordt gevolgd door een signaal van het besturingssysteem aan het proces.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 4 van 10

Een besturingssysteem dwingt beperkingen in de gebruikersmodus af en ontvangt timerinterrupts. De timerafhandelaar slaat gebruikersregisters op, maar keert altijd terug naar hetzelfde proces. Een voorgestelde oplossing verandert alleen hoe vaak de timer afgaat. Andere processen blijven gereed. Waarom kan deze oplossing er nog steeds niet in slagen die processen CPU-beurten te geven?
  1. Toegang via de timer garandeert zelf eerlijke beurten vóór de afhandelaar terugkeert.
  2. Controle terugkrijgen biedt een mechanisme, geen eerlijk selectiebeleid.
  3. Beperkingen in de gebruikersmodus laten elk gereed proces bij de volgende timertik draaien.
  4. Gebruikersregisters opslaan gaat automatisch verder naar het volgende gereedstaande proces.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 5 van 10

Een werklast herhaalt nuttige CPU-beurten van 600 µs met 6 µs wisselkosten. Dat verandert naar beurten van 1200 µs met dezelfde kosten. Hoe verandert het wisselaandeel?
  1. Het stijgt van ongeveer 0,50% naar ongeveer 0,99%.
  2. Het daalt van ongeveer 0,99% naar ongeveer 0,50%.
  3. Het blijft ongeveer 1% omdat de wisselkosten gelijk blijven.
  4. Het daalt van ongeveer 9,9% naar ongeveer 5,0%.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 6 van 10

Een shell opent een bestand voor invoeromleiding en ontvangt descriptor 0 omdat standaardinvoer gesloten was. Hij roept dup2(fd, 0) aan, sluit fd onvoorwaardelijk en voert het commando uit met exec. Waarom kan de standaardinvoer van het commando gesloten zijn?
  1. Fd sluiten sluit alleen een oude vermelding; descriptor 0 blijft een aparte kopie.
  2. Exec sluit descriptor 0 omdat dup2 de vlag voor sluiten bij exec heeft ingesteld.
  3. dup2 wijst gelijke descriptornummers af en verwijdert de invoervermelding.
  4. Fd is al gelijk aan 0, dus fd sluiten sluit de bedoelde invoer.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 7 van 10

Een programma heeft een afgeschermde x gelijk aan 2. Elke fork slaagt. Hoeveel processen drukken “hit” af?

pid_t p = fork();
if (p > 0) {
    x = 7;
    fork();
}
if (x == 7) puts("hit");
  1. 2
  2. 3
  3. 4
  4. 1
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 8 van 10

Een shell start twee kindprocessen. Het ene eindigt normaal met status 0; het andere wordt door een signaal beëindigd. De shell moet beide uitkomsten rapporteren. Welke aanpak voor de resultaatafhandeling is nodig?
  1. Haal beide resultaten eenmaal op en decodeer beide als normale beëindigingen.
  2. Haal één resultaat op en decodeer het eenmaal als afsluiting en eenmaal als signaal.
  3. Haal beide resultaten op en kies voor elk afzonderlijk de decodeermacro's.
  4. Haal beide resultaten op maar decodeer hun ruwe gehele getallen als afsluitcodes.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 9 van 10

A blokkeert in een leesbewerking van de terminal en B draait. Nadat invoer A gereed maakt, kiest de scheduler A. Een voorgestelde wisseling herstelt de gebruikersprogrammateller van A maar behoudt de kernelstack en adresruimtecontext van B. Waarom kan dit de wachtende leesbewerking van A niet correct hervatten?
  1. Het gebruikersterugkeerframe van A herstelt automatisch de rest van zijn kernelpad.
  2. De gebruikersprogrammateller veranderen selecteert ook de bijpassende kernelstack.
  3. De leesbewerking kan op de kernelstack van B eindigen met alleen de gebruikersregisters van A.
  4. De eigen kernelcontext, stack en adresruimtecontext van A moeten worden geselecteerd.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Vraag 10 van 10

Een gebruikersprogramma kent het adres van een kernelroutine en het nummer van een geldige systeemaanroep. Waarom kan het de dienst aanvragen maar dat geprivilegieerde adres niet gewoon als een normale functie aanroepen?
  1. Een trap gaat een ingesteld kernelpad binnen dat het verzoek controleert en doorstuurt.
  2. Een rechtstreekse aanroep krijgt privileges zodra zijn doel met een geldig dienstnummer overeenkomt.
  3. Een dienstnummer geeft de aanroeper kerneltoegang voordat de argumenten zijn gecontroleerd.
  4. Een rechtstreekse aanroep en een trap erven beide privileges uitsluitend van het doeladres.
Toon antwoordVerberg antwoord

Sla deze les op om dit antwoord te zien.

Kom je niet uit je eigen opgave? Huiswerkhulp

Kernbegrippen

75 Kernbegrippen, elk met een definitie

A

abstractie
Een abstractie is een bruikbare interface of een bruikbaar model dat onderliggende implementatiedetails verbergt en tegelijk de bewerkingen behoudt die programma's nodig hebben.
De bestandsabstractie laat een programma bytes lezen zonder het commandoformaat van het opslagapparaat te kennen.
achtergrondtaak
Een achtergrondtaak is werk dat wordt gestart zonder dat de shell direct op voltooiing wacht, zodat commando-invoer kan doorgaan.
De shell toont een prompt terwijl een achtergrondtaak draait, maar moet nog steeds de beëindigingsstatus van het kindproces ophalen wanneer die taak eindigt.
adresruimte
Een adresruimte is de verzameling geheugenadressen die voor een proces beschikbaar zijn en de code, gegevens, heap en stack die in die weergave zijn gekoppeld.
Gelijke virtuele adressen in twee afgeschermde adresruimten kunnen naar verschillende waarden in het fysieke geheugen verwijzen.
adresvertaalbuffer
Een adresvertaalbuffer (TLB) bewaart adresvertalingen in een cache zodat de CPU die niet telkens opnieuw in het geheugen hoeft op te zoeken.
Een proceswisseling kan vereisen dat vertalingen opnieuw worden opgehaald, hoewel vermeldingen met labels nuttige gecachte vertalingen kunnen behouden.
afsluitstatus
Een afsluitstatus is het kleine resultaat dat een proces bij normale beëindiging rapporteert, volgens afspraak 0 voor succes en een waarde anders dan nul voor een fout.
Na controle van normale beëindiging haalt het ouderproces de afsluitstatus op met de bijbehorende wachtmacro.
argumentvector
Een argumentvector is een met een nullpointer afgesloten array van stringpointers die aan een nieuw programma wordt doorgegeven als zijn opdrachtregelargumenten.
Een argumentvector voor een telcommando heeft afzonderlijke vermeldingen voor de programmanaam, optie en bestandsnaam.

B

batchverwerking
Batchverwerking verzamelt ingediende taken en voert ze uit zonder interactieve invoer van degene die elke taak heeft ingediend.
Bij batchverwerking wacht een ingediende berekening op eerdere taken in plaats van direct een beurt te krijgen.
beleid
Beleid is een regel om te kiezen hoe beschikbare mechanismen worden gebruikt, bijvoorbeeld om te beslissen welk gereed proces CPU-tijd moet krijgen.
Een planningsbeleid kan veranderen terwijl de code voor het opslaan van registers bij proceswisselingen gelijk blijft.
beperkte directe uitvoering
Beperkte directe uitvoering voert gebruikersinstructies uit op hardware terwijl privilegebeperkingen en toegang via de timer de controle van het besturingssysteem behouden.
Een toepassing in een lus wordt rechtstreeks uitgevoerd maar kan nog steeds de timer die haar kan onderbreken niet uitschakelen.
beschermingsring
Een beschermingsring is een hardwareprivilegeniveau van x86; gangbare systemen gebruiken normaal ring 0 voor kernels en ring 3 voor toepassingen.
De overgang van toepassingsring 3 naar kernelring 0 volgt een gecontroleerd toegangspad dat door het besturingssysteem is ingesteld.
beschrijving van een geopend bestand
Een beschrijving van een geopend bestand is door de kernel bijgehouden toestand voor een geopend bestand, waaronder de bestandspositie, die meerdere descriptoren kunnen delen.
Leesbewerkingen van ouderproces en kindproces via een geërfde descriptor verschuiven de bestandspositie in één beschrijving van een geopend bestand.
bestandsdescriptor
Een bestandsdescriptor is een klein geheel getal in de descriptortabel van een proces dat verwijst naar een geopend bestand of een andere I/O-bron.
Een shell verbindt bestandsdescriptor 1 met een bestand voordat hij een commando uitvoert waarvan de uitvoer wordt omgeleid.
bestandseinde
Bestandseinde is een leesresultaat dat aangeeft dat geen gegevens meer beschikbaar zijn; voor een pipe vereist het een lege buffer en geen open schrijfkanten.
Een lezer kan blijven wachten in plaats van bestandseinde te ontvangen als de shell per ongeluk een schrijfkant van de pipe openhoudt.
besturingssysteem
Een besturingssysteem beheert hardwarebronnen en biedt diensten waarmee programma's veilig kunnen draaien, communiceren en gegevens opslaan.
Het besturingssysteem verdeelt CPU-tijd tussen een browser en een compiler en beheert hun bestandsverzoeken.

C

contextwisseling
Een contextwisseling slaat de ene uitvoeringscontext op en herstelt een andere; een proceswisseling selecteert ook de juiste adresruimte.
Wanneer een lezer blokkeert, laat een contextwisseling een gereedstaande berekening hervatten op dezelfde logische CPU.
coöperatieve besturing
Coöperatieve besturing vertrouwt erop dat programma's de CPU-beurt afstaan, systeemaanroepen doen of excepties veroorzaken zodat het besturingssysteem de uitvoering op de CPU terugkrijgt.
Een eindeloze gebruikerslus laat de zwakte van coöperatieve besturing zien als die nooit een pad terug naar het besturingssysteem bereikt.
CPU-bezettingsgraad
De CPU-bezettingsgraad is het deel van een verstreken interval waarin de CPU bezig is, uitgedrukt als verhouding of percentage.
Als nuttige berekeningen 9 ms van een verloop van 12 ms zonder overhead innemen, is de CPU-bezettingsgraad 75%.

E

errno
errno is een foutindicator van de C-bibliotheek die door veel interfaces bij een fout wordt ingesteld en wordt bekeken nadat de retourwaarde een fout meldt.
Een mislukte open-aanroep kan errno op ENOENT instellen, terwijl een latere geslaagde aanroep die eerdere waarde niet hoeft te wissen.
exceptie
Een exceptie is een gebeurtenis die door de huidige instructie ontstaat en speciale afhandeling door CPU en kernel vereist, zoals een paginafout.
Een verboden geheugentoegang veroorzaakt een exceptie voordat de toepassing normaal kan doorgaan.
exceptieniveau
Een exceptieniveau is een uitvoeringsprivilegeniveau van AArch64, waaronder EL0 voor toepassingen en normaal EL1 voor de kernel van het besturingssysteem.
AArch64 noemt privilegeniveaus anders dan x86-ringen, maar scheidt toepassingen nog steeds van de kernel.
exec
Exec vervangt het programmabeeld van het aanroepende proces door een nieuw programma en behoudt daarbij de procesidentiteit en bepaalde bronnen.
Het kindproces behoudt zijn PID wanneer exec de code van de shell vervangt door de code van het gevraagde commando.

F

fork
Fork is de Unix-bewerking voor het aanmaken van een proces die een kindproces maakt en na dezelfde aanroep terugkeert naar zowel ouderproces als kindproces.
Na een geslaagde fork ontvangt het ouderproces de PID van het kindproces en ontvangt het kindproces de retourwaarde 0.

G

geblokkeerde toestand
De geblokkeerde toestand betekent dat een proces pas verder kan wanneer een gebeurtenis plaatsvindt, zoals het beschikbaar komen van aangevraagde invoer.
Een blokkerende leesbewerking van de terminal brengt een proces in de geblokkeerde toestand totdat invoer het verzoek laat doorgaan.
gebruikersmodus
De gebruikersmodus is het privilegeniveau van de CPU waarin toepassingsinstructies draaien met beperkte toegang tot beschermd geheugen en beschermde bewerkingen.
De teksteditor van een beheerder draait nog steeds in de gebruikersmodus en gebruikt systeemaanroepen om beschermde diensten aan te vragen.
gelijktijdigheid
Gelijktijdigheid betekent dat meerdere activiteiten in dezelfde periode bezig zijn, ook wanneer hun instructies worden afgewisseld.
Twee programma's zijn gelijktijdig op één logische CPU wanneer elk herhaaldelijk een beurt krijgt voordat een van beide klaar is.
geprivilegieerde instructie
Een geprivilegieerde instructie verandert beschermde machinetoestand en kan niet vrij door gewone code in de gebruikersmodus worden uitgevoerd.
Interrupts uitschakelen is geprivilegieerd omdat dit anders zou kunnen voorkomen dat het besturingssysteem de controle terugkrijgt.
gereedtoestand
De gereedtoestand betekent dat een proces kan worden uitgevoerd maar wacht tot een CPU beschikbaar komt of de scheduler het selecteert.
Een timer kan een onvoltooide berekening zonder I/O van de toestand in uitvoering naar de gereedtoestand brengen.

H

hardware-interrupt
Een hardware-interrupt is een melding van een apparaat of timer die de CPU een gebeurtenis laat afhandelen onafhankelijk van de huidige instructie.
Een opslagcontroller veroorzaakt een hardware-interrupt wanneer een eerder aangevraagde overdracht is voltooid.

I

ingebouwd commando
Een ingebouwd commando is een bewerking die door de shell zelf is geïmplementeerd, zodat die de eigen blijvende procestoestand van de shell kan veranderen.
Het ingebouwde commando cd verandert de directory van de shell zodat latere commando's de nieuw gekozen directory erven.

K

kernel
De kernel is de geprivilegieerde kern van een besturingssysteem die beschermde hardwarebewerkingen bestuurt en bronnen voor processen beheert.
Een terminaltoepassing vraagt de kernel om invoer te lezen in plaats van het toetsenbordapparaat zelf te besturen.
kernelcontext
Een kernelcontext is de opgeslagen register- en stacktoestand die nodig is om het uitvoeringspad van de kernel voor een onderbroken proces te hervatten.
Bij het overschakelen naar proces B herstelt de wisselroutine de kernelcontext van B voordat de afsluitcode van de kernel de gebruikersregisters van B kan herstellen.
kernelmodus
De kernelmodus is het privilegeniveau van de CPU dat het besturingssysteem toestaat beschermde hardwaretoestand te beheren en geprivilegieerde instructies uit te voeren.
De CPU gaat naar de kernelmodus om een verzoek van de toepassing van een gewone gebruiker af te handelen.
kernelstack
Een kernelstack bevat opgeslagen gebruikerstoestand en kerneluitvoeringsgegevens terwijl de kernel namens een proces of uitvoeringscontext draait.
Overschakelen naar een ander proces omvat het herstellen van de kernelstack die door het opgeslagen terugkeerpad van dat proces wordt gebruikt.
kindproces
Een kindproces is een nieuw proces dat door een ouderproces is aangemaakt, met een eigen identiteit en een kopie van het gewone afgeschermde geheugen van het ouderproces.
Het kindproces kan na fork een afgeschermde variabele veranderen zonder de waarde van het ouderproces te veranderen.
kopiëren bij schrijven
Kopiëren bij schrijven deelt aanvankelijk beschermde fysieke geheugenpagina's en maakt eigen kopieën wanneer schrijfbewerkingen afzonderlijke inhoud vereisen.
Een kindproces dat onmiddellijk exec aanroept, kan geërfde pagina's verwijderen zonder eerst elke pagina te kopiëren.

M

mechanisme
Een mechanisme is de manier om een bewerking van het besturingssysteem uit te voeren, zoals de toestand van het ene proces bewaren en die van een ander herstellen.
Het mechanisme voor contextwisseling ondersteunt verschillende mogelijke regels om te bepalen welk gereed proces als volgende draait.
microkernel
Een microkernel houdt een kleine geprivilegieerde kern en plaatst meer diensten van het besturingssysteem in afzonderlijke processen in de gebruikersmodus die via berichten communiceren.
Een mislukt stuurprogramma in de gebruikersmodus kan in een microkernelontwerp vaak opnieuw worden gestart terwijl andere diensten doorgaan.
moduswisseling
Een moduswisseling verandert het privilegeniveau van de CPU, zoals bij toegang tot de kernel voor een dienst en terugkeer naar hetzelfde gebruikersproces.
Een niet-blokkerende systeemaanroep kan moduswisselingen omvatten zonder dat een ander proces wordt hervat.
monolithische kernel
Een monolithische kernel voert de meeste diensten van het besturingssysteem samen in de kernelmodus uit, waardoor rechtstreekse aanroepen mogelijk zijn maar de risico's van fouten in geprivilegieerde code worden gedeeld.
Een Linux-stuurprogrammamodule wordt onderdeel van de monolithische kernel en kan de kerneltoestand beschadigen als die een ernstige fout bevat.
multiprogrammering
Multiprogrammering houdt meerdere taken beschikbaar in het geheugen zodat de ene de CPU kan gebruiken terwijl een andere voor I/O is geblokkeerd.
Multiprogrammering laat een compiler rekenen terwijl een ander proces wacht tot een leesbewerking van de opslag is voltooid.

N

niet-blokkerend wachten
Niet-blokkerend wachten controleert of een resultaat van een kindproces beschikbaar is en keert terug zonder de aanroeper te onderbreken wanneer geen resultaat klaar is.
Een shell gebruikt niet-blokkerend wachten om voltooide achtergrondtaken op te halen en tegelijk de prompt beschikbaar te houden.

O

omleiding
Omleiding verandert de descriptor voor standaardinvoer, standaarduitvoer of standaardfoutuitvoer van een commando zodat die naar een andere open I/O-bron verwijst.
Uitvoeromleiding laat een ongewijzigd programma zijn gewone standaarduitvoer naar een gekozen bestand schrijven.
ophalen van de beëindigingsstatus
Ophalen van de beëindigingsstatus is het met een wachtbewerking ophalen van het resultaat van een beëindigd kindproces, zodat de kernel de resterende procesgegevens kan vrijgeven.
Eén geslaagde wachtbewerking haalt de status van één kindproces op; een ouderproces met meerdere kindprocessen moet resultaten blijven ophalen.
ouderproces
Een ouderproces is het proces dat een kindproces aanmaakt; het kan wachtbewerkingen gebruiken om het beëindigingsresultaat van dat kindproces op te halen.
Een shell blijft het ouderproces terwijl zijn kindproces zijn eigen programma vervangt door een extern commando.
overhead
Overhead is de extra tijd of het extra geheugen dat wordt besteed aan het beheer van een bewerking in plaats van rechtstreeks aan het nuttige werk van de toepassing.
Registers opslaan tijdens een contextwisseling voegt overhead toe voordat een ander proces zijn berekeningen hervat.

P

paginafout
Een paginafout is een door een instructie veroorzaakte gebeurtenis bij geheugentoegang waarvan de vertaling of toegangsrechten speciale afhandeling vereisen.
Een geldige ontbrekende pagina kan na een paginafout worden geladen, zodat de kernel de onderbroken instructie opnieuw kan proberen.
parallellisme
Parallellisme betekent dat werk op hetzelfde moment wordt uitgevoerd op afzonderlijke verwerkingsbronnen, zoals verschillende logische CPU's.
Een compiler en een renderprogramma kunnen parallel worden uitgevoerd wanneer elk op een andere logische CPU draait.
PATH
PATH is een omgevingsvariabele met een lijst van directory's waarin interfaces zoals execvp naar namen van uitvoerbare bestanden zoeken.
Een commando dat via PATH wordt gevonden, kan met execvp starten, ook als het bestand niet in de huidige directory staat.
pipe
Een pipe is een door de kernel beheerd eenrichtingskanaal voor bytes met een leeskant en een schrijfkant dat samenwerkende processen kan verbinden.
Een shell verbindt de uitvoer van een producent met een pipe en de invoer van een consument met de leeskant van diezelfde pipe.
proces
Een proces is een actieve instantie van een programma samen met het geheugen, de registerwaarden en de I/O-toestand die nodig zijn voor de uitvoering ervan.
Twee processen die hetzelfde uitvoerbare bestand draaien, kunnen verschillende afgeschermde variabelen en huidige directory's hebben.
proces-ID
Een proces-ID (PID) is een numerieke identificatie die aan een proces wordt toegekend en uniek is onder actieve processen in dezelfde PID-naamruimte.
Een processenoverzicht gebruikt PID en ouder-PID om te tonen dat een commando door een bepaalde shell is gestart.
procesbesturingsblok
Een procesbesturingsblok (PCB) bevat de gegevens die de kernel over één proces bijhoudt, waaronder zijn identiteit, toestand, bronnen en opgeslagen context.
De kernel raadpleegt een procesbesturingsblok om de geheugengegevens en het ouderproces van een gestopt proces te vinden.
programma
Een programma bestaat uit opgeslagen instructies en gegevens die voor uitvoering kunnen worden geladen; het bestand zelf heeft geen veranderlijke uitvoeringstoestand.
Hetzelfde shellprogrammabestand kan worden gebruikt om afzonderlijke processen in drie terminalvensters te starten.
programmateller
De programmateller is een CPU-register dat het adres van de volgende instructie in een uitvoeringscontext bevat.
Door de programmateller te herstellen kan een onderbroken proces na een wisseling bij de juiste instructie verdergaan.

R

ruimteverdeling
Ruimteverdeling verdeelt de capaciteit van een bron in delen waarover verschillende processen of gebruikers tegelijk beschikken.
Afzonderlijke geheugengebieden kunnen aan meerdere processen toegewezen blijven terwijl slechts één proces de CPU heeft.

S

scheduler
De scheduler is het onderdeel van het besturingssysteem dat kiest welke uitvoeringscontext die daarvoor in aanmerking komt als volgende CPU-tijd krijgt.
Na voltooiing van een leesbewerking van de schijf kan de scheduler het huidige proces laten doorgaan voordat hij de lezer selecteert.
shell
Een shell is een gebruikersprogramma dat commando's interpreteert en proces- en descriptorbewerkingen gebruikt om andere programma's te starten en te verbinden.
Een shell op de voorgrond wacht op het kindproces van zijn commando voordat hij de volgende prompt toont.
signaal
Een signaal is een softwaremelding die het besturingssysteem aan een proces aflevert, met een standaardactie of ingesteld afhandelingsgedrag.
Een terminal stuurt SIGINT naar de taak op de voorgrond wanneer de gebruiker Ctrl-C indrukt, wat de taak normaal beëindigt.
sluiten bij exec
Sluiten bij exec is een descriptorvlag die aangeeft dat de descriptor automatisch moet worden gesloten wanneer een proces zijn programma met succes vervangt.
Een shell kan voorkomen dat een interne descriptor bij het commando terechtkomt door die te markeren om bij exec te sluiten.
stackpointer
De stackpointer is een register dat de huidige positie aangeeft op een stack die voor functieaanroepen en uitvoeringstoestand wordt gebruikt.
Een contextwisseling herstelt de stackpointer zodat de hervatte uitvoering haar eigen opgeslagen stack gebruikt.
systeemaanroep
Een systeemaanroep is een gecontroleerd verzoek van een gebruikersprogramma om een kerneldienst, gedaan via een vastgelegde toegangsinterface.
Een bestand openen vereist een systeemaanroep omdat kernelcode de toegang tot de bron van het geopende bestand beheert.
systeemaanroepnummer
Een systeemaanroepnummer is een architectuurspecifieke identificatie waarmee de kernel een bepaalde dienstimplementatie selecteert.
Linux gebruikt verschillende systeemaanroepnummers voor write op x86-64 en AArch64, dus ruwe nummers zijn niet overdraagbaar.

T

terugkeer uit een trap
Een terugkeer uit een trap herstelt opgeslagen uitvoeringstoestand en keert vanuit kernelafhandeling terug naar de bedoelde gebruikersuitvoeringscontext.
Het besturingssysteem kan de begintoestand van een nieuw proces zo voorbereiden dat het herstelpad dat programma voor het eerst start.
tijdschijf
Een tijdschijf is een interval van CPU-uitvoering dat aan werk wordt toegekend voordat de planning een ander proces dat daarvoor in aanmerking komt een beurt kan geven.
Bij vaste wisselkosten vergroot een kortere tijdschijf het deel van de tijd dat aan wisselen wordt besteed.
tijdsverdeling
Tijdsverdeling verdeelt toegang tot een bron in opeenvolgende beurten, zodat meerdere processen of gebruikers die in de loop van de tijd kunnen delen.
Tijdsverdeling geeft een teksteditor opnieuw een CPU-beurt terwijl een lange berekening nog bezig is.
timerinterrupt
Een timerinterrupt is een hardwaregebeurtenis van een ingestelde timer die de kernel gelegenheid geeft de controle over een CPU terug te krijgen.
Een timerinterrupt kan de kernel binnengaan terwijl het huidige proces een lus zonder systeemaanroepen uitvoert.
toestand in uitvoering
De toestand in uitvoering betekent dat een proces op dat moment instructies uitvoert op een CPU, in plaats van voor uitvoering in aanmerking te komen of op een gebeurtenis te wachten.
Wanneer een gereedstaande compiler een CPU krijgt, komt die in de toestand in uitvoering en kan hij zijn volgende instructie uitvoeren.
trap
Een systeemaanroeptrap is bewuste toegang tot de kernel door een dienstverzoek van een programma, via een beschermde toegangsinstructie.
Het verzoek om uitvoer te schrijven veroorzaakt een systeemaanroeptrap, ook wanneer er geen fout in het programma zit.
traptabel
Een traptabel koppelt soorten gebeurtenissen aan beschermde bestemmingen van kernelafhandelaars; de precieze organisatie hangt af van de CPU.
Bij het opstarten bereidt het besturingssysteem bestemmingen van afhandelaars voor, zodat gebruikerscode latere toegang tot de kernel niet kan omleiden.

U

uitvoerbuffer
Een uitvoerbuffer is opslagruimte in de gebruikersruimte die opgemaakte uitvoer bevat voordat een bibliotheek die bytes aan de kernel overdraagt.
Wachtende tekst in een uitvoerbuffer kan door fork worden gekopieerd en later door elk proces eenmaal worden weggeschreven.

V

virtualisatie
Virtualisatie presenteert een gedeelde fysieke bron als een bruikbare virtuele bron die elk programma via een eenvoudiger weergave kan gebruiken.
CPU-virtualisatie laat honderden processen voortgang maken op een machine met slechts enkele logische CPU's.

W

wachtstatus
Een wachtstatus is een gecodeerde waarde die beschrijft hoe een kindproces is geëindigd of van toestand is veranderd en die met de bijbehorende wachtmacro's wordt geïnterpreteerd.
Een ruwe wachtstatus van 768 op Linux kan normale afsluitcode 3 coderen, dus die rechtstreeks afdrukken geeft de verkeerde code.
weesproces
Een weesproces is een proces waarvan het ouderproces is geëindigd en dat een nieuw ouderproces krijgt, zodat een ander proces later zijn resultaat kan ophalen.
Een weesproces kan blijven rekenen nadat zijn oorspronkelijke ouderproces eindigt; het is niet noodzakelijk zelf beëindigd.
wrapperfunctie in een bibliotheek
Een wrapperfunctie in een bibliotheek is code in de gebruikersruimte die een aanroepbare interface biedt en de argumenten en toegang voor een kerneldienst regelt.
De wrapperfunctie voor write in de bibliotheek volgt de registerconventie voor systeemaanroepen voordat ze de kernel binnengaat.

Z

zombieproces
Een zombieproces is een beëindigd proces waarvan de resultaatgegevens in de kernel blijven bestaan omdat het ouderproces dat resultaat nog niet heeft opgehaald.
Een langlopende server voorkomt dat zombieprocessen zich ophopen door de beëindigingsstatus van voltooide kindprocessen op te halen.

Over deze les

Door StudeliFout melden

Maak je eigen Studiemateriaal

Maak van je aantekeningen, slides en documenten Leermodules, Oefenvragen, Flashcards en 6 andere tools.

Aan de slag