Ubuntu: Linux voor mensen/Processen/De levenscyclus van een proces

Uit Wikibooks
Naar navigatie springen Naar zoeken springen

Een proces aanmaken[bewerken]

Een nieuw proces wordt aangemaakt doordat een bestaand proces een exacte kopie van zichzelf maakt. Dit child process (letterlijk: het kind van het ouderproces) is eigenlijk net hetzelfde als het ouderproces, enkel het procesidentificatienummer verschilt. Deze procedure heet men een fork (letterlijk: een vork of splitsing).

Na de fork wordt de geheugenruimte van het kindproces overschreven met de nieuwe procesdata: het commando dat gevraagd werd, wordt in het geheugen geladen. Dit noemt men een exec.

Het geheel van kopiëren en overschrijven heet dan fork-and-exec. Alle processen worden op deze manier gemaakt. Zelfs init, het eerste proces met PID 1, werd zo gecreëerd door de kernel.

Onderstaand schema geeft weer hoe bijvoorbeeld een ls proces afstamt van je shell, bash:

Figuur 5.1. Het fork-and-exec mechanisme geheugeninhoud verandert.

De fork wordt hier met een horizontale pijl voorgesteld. Bemerk dat enkel het procesidentificatienummer verandert.

De verticale pijlen stellen de exec voor. Hier blijft het procesidentificatienummer gelijk, maar de geheugeninhoud wordt verwisseld.

De rol van init[bewerken]

Zoals we reeds konden zien aan de output van het pstree commando, hebben veel processen init als ouderproces, terwijl dat helemaal niet mogelijk is. Nemen we bijvoorbeeld ons systeem dat in grafische mode draait: er moeten allerlei programma's opgestart worden om het grafische loginscherm te tonen, daarna moet de desktop gestart worden door middel van een desktopmanager, dan volgt de venstermanager (windowmanager), dan start je een terminal venster en daarin draait een shell waarmee je commando's kan ingeven. Wat gebeurt hier dan?

De verklaring is tamelijk eenvoudig: veel programma's “demoniseren” hun kindprocessen, zodanig dat die kunnen blijven draaien als de ouder stopt (zie de paragraaf “Daemons”). Het init proces neemt de rol van peetvader van zulke processen: als de ouder sterft, vallen ze onder de verantwoordelijkheid van init. Voorbeeld van demoniseren

  • Start de web browser firefox vanuit een terminal venster.
  • Indien je dat nog niet gedaan had, bevries het proces en laat het verderdraaien in de achtergrond.
  • Gebruik pstree om na te gaan welk proces het ouderproces van firefox is.
  • Sluit het terminal venster.
  • firefox blijft draaien.
  • Neem een nieuw terminal venster.
  • Gebruik het pstree commando om na te gaan wat er met firefox gebeurd is.

Heel af en toe wil het nog wel eens mislopen met de “adoptie” van processen. Een proces dat geen ouderproces heeft, noemt men een zombie. Je kon deze term ook zien in de output van het top commando. Het systeem heeft geen vat meer op zo'n zombieproces, het blijft in het geheugen hangen tot je de computer herstart. Meestal duidt het voorkomen van zombieprocessen op slecht geprogrammeerde applicaties. Een proces beëindigen

Wanneer een proces normaal eindigt, geeft het een code, de exit status, door aan de ouder. Als alles goed verlopen is, is de exit status nul. Men mag ervan uitgaan dat er iets foutliep als de exit status niet nul is. De mogelijke waarden van de exit status worden gedocumenteerd in de man pages en de systeembibliotheken. Ze zijn voor elk commando verschillend en worden bijvoorbeeld in scripts gebruikt om na te gaan of een opdracht al dan niet gelukt is. Ook programmeurs maken veelvuldig gebruik van de exit status van commando's.

De waarde van de exit status van shell commando's wordt opgeslagen in een speciale variabele, aangeduid met $?. Met het echo commando kan je de inhoud van deze variabele bekijken.

Zoeken in tekst met grep[bewerken]

Hieronder een voorbeeld met grep. Een exit status van 0 betekent dat de zoekstring gevonden werd in het opgegeven bestand:

Voorbeeld code om na te doen

willy@ubuntu:~$ grep willy /etc/passwd
willy:x:1000:1000:Willy,,,:/home/willy:/bin/bash
willy@ubuntu:~$ echo $?
0

Uitleg

/etc/passwd?

Het /etc/passwd bestand bevat een lijst van alle gebruikersnamen die op je systeem gekend zijn. De informatie is gerangschikt in kolommen die gescheiden worden door dubbele punten. We zien hier over gebruiker willy het volgende:

  1. gebruikersnaam;
  2. een “x” die het wachtwoord verbergt - de wachtwoorden zitten in /etc/shadow;
  3. het identificatienummer van de gebruiker;
  4. het identificatienummer van de groep waarvan de gebruiker deel uitmaakt;
  5. omschrijving of naam van de gebruiker;
  6. het pad naar de home map van de gebruiker;
  7. de shell voor deze gebruiker;

Een exit status van 1 betekent dat de zoekstring niet gevonden werd, maar niet noodzakelijk dat de shell een foutmelding geeft:

Voorbeeld code om na te doen

willy@ubuntu:~$ grep blah /etc/passwd
willy@ubuntu:~$ echo $?
1

Een exit status van 2 lokt wel een foutmelding uit, bijvoorbeeld wanneer de optie niet herkend wordt of het opgegeven bestand niet gevonden wordt:

Voorbeeld code om na te doen

willy@ubuntu:~$ grep blah /etc/blabla
grep: /etc/blabla: Onbekend bestand of map
willy@ubuntu:~$ echo $?
2
willy@ubuntu:~$ grep --blah bleble /etc/passwd
grep: optie niet herkend `--blah'
Gebruik: grep OPTIE?... PATROON BESTAND?...
Probeer `grep --help' voor meer informatie.
willy@ubuntu:~$ echo $?
2

Deze methode om een gecodeerd resultaat terug te geven stamt van de C programmeertaal. Vandaar dat de code ook wel eens return code genoemd wordt.

Informatie afkomstig van http://nl.wikibooks.org Wikibooks NL.
Wikibooks NL is onderdeel van de wikimediafoundation.