Dagens tema Operativsystemer Hva er et operativsystem? En meget kort oversikt over operativsystemenes historie Systemkall i UNIX Hente prosessens nummer Starte prosesser Vente på prosesser Utføre programmer Hva gjør en kommandotolker? Ark 1 av 21 Forelesning 17.3.1998
Hva er et operativsystem? Det er to måter å se det på: Et operativsystem gir brukeren en virtuell datamaskin å arbeide med. Eksempel: Brukeren kan lese en blokk fra disk uten å tenke på sektorer, spor, formattering, plassering etc. Et operativsystem administrerer ressurser. Flere prosesser og brukere konkurrerer om ressurser: prosessor-tid, hukommelse, aksess til disken, skriver etc. Forelesning 17.3.1998 Ark 2 av 21
Operativsystemenes historie 1. generasjon (1945 55). En bruker har maskinen for seg selv. Intet egentlig operativsystem. Personlig erfaring fra en Nord-12 i 1973: 1. Les inn et hullbånd med tekstredigeringsprogrammet. 2. Les inn et hullbånd med den tidligere versjonen av kildekoden. Rett koden. 3. La maskinen skrive ut et hullbånd med den rettede kildekoden. 4. Les inn et hullbånd med assembleren. 5. Les inn hullbåndet med kildekoden. 6. Maskinen skriver ut et hullbånd med binærkode. 7. Les inn dette båndet og kjør programmet. Forelesning 17.3.1998 Ark 3 av 21
2. generasjon (1955 65) Operatørene har overtatt. En tredeling av kjøringen: 1. Brukeren leverer en bunke hullkort. Mange slike bunker (en «batch») kopieres over på magnetbånd ved hjelp av en billig maskin. 2. Hoveddatamaskinen har et primitivt operativsystem og leser én og én jobb fra magnetbåndet og utfører denne. Eventuell utskrift skrives til et annet magnetbånd. 3. Den billige datamaskinen leser magnetbåndet og skriver innholdet på en linjeskriver. Dette er starten på operativsystemene. Forelesning 17.3.1998 Ark 4 av 21
3. generasjon (1965 80) Multiprogrammering. Flere jobber kan kjøres samtidig. Dette gir flere fordeler: Jobber som krever både regnekraft og I/U kan spare tid ved å kjøres samtidig: P1: P2: Datamaskinen kan nå også lese hullkort og styre skriveren uten at det koster for mye. Tidsdeling gir brukerne direkte kontakt med maskinen. Stormaskiner og minimaskiner. Operativsystemer som MULTICS, UNIX, VMS,.... Forelesning 17.3.1998 Ark 5 av 21
4. generasjon (1980 ) Mikromaskiner; maskinen tilbake til den enkelte bruker. Operativsystemenes utvikling gjentas én gang til: 1. Uten noe egentlig operativsystem. 2. Enkle éprosesssystemer som CP/M, TOS, MS-DOS, Finder,... 3. Multiprogrammering med systemer som MP/M, OS/2, Windows 95, Windows NT,, UNIX, MACH,... Nytt er nettverk og vindussystemer. Forelesning 17.3.1998 Ark 6 av 21
Utviklingen av UNIX Kommersiell: Bell Labs: Berkeley: 1970 Version 1 Version 5 Version 6 Version 7 3BSD 1980 4.0BSD System III System V 4.2BSD System V.3 4.3BSD 1990 System V.4 IRIX,Solaris,... SunOS,Linux,... Forelesning 17.3.1998 Ark 7 av 21
Hva er en prosess i UNIX? En prosess er et program under utførelse. Prosessen består av Hurtiglager for kode, data og stakk: Stakk Tomt Data Kode Registerinnhold. Systeminformasjon, blant annet et prosessnummer (en såkalt PID). Forelesning 17.3.1998 Ark 8 av 21
Hvordan kommunisere med operativsystemet? Brukerprogrammer har behov for å kommunisere med operativsystemet, blant annet for å få utført I/U. Forskjellige operativsystemer benytter forskjellige teknikker til dette: Hopp til spesielle adresser (CP/M). Spesielle instruksjoner (som SysCall). Ulovlige instruksjoner. Systemkall (UNIX). Et systemkall er et kall på en C-rutine som ligger i operativsystemet. Forelesning 17.3.1998 Ark 9 av 21
Et enkelt systemkall $ more pid.c #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(void) { printf("prosessen har PID=%d\n", (int)getpid()); $ pid Prosessen har PID=96. $ pid Prosessen har PID=97. $ Forelesning 17.3.1998 Ark 10 av 21
Hvordan opprette en ny prosess? Den absolutt eneste måten å opprette nye prosesser på i UNIX er å benytte systemkallet fork. Fork gjør følgende: 1. En ny prosess opprettes. 2. Den nye prosessen er en nøyaktig og fullstendig kopi av foreldre-prosessen. Det eneste som er forskjellig, er at de har forskjellig PID. 3. Begge prosessene fortsetter eksekveringen etter fork-kallet. Forelesning 17.3.1998 Ark 11 av 21
$ cat fork1.c #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(void) { printf("prosessen har PID=%d\n", (int)getpid()); fork(); printf("nå er PID=%d\n", (int)getpid()); $ fork1 Prosessen har PID=40 Nå er PID=41 Nå er PID=40 $ Forelesning 17.3.1998 Ark 12 av 21
Forldre og barn Den prosessen som opprinnelig utførte fork-kallet, kalles foreldre-prosessen, og de som opprettes, kalles barne-prosesser. For å kunne skille de to fra hverandre i programmene (som er identiske), benyttes følgende løsning: Kallet på fork returnerer 0 til barne-prosessen. Det returnerer barnets PID til foreldre-prosessen. $ more fork2.c #include <stdio.h> #include <sys/types.h> #include <unistd.h> int main(void) { pid_t pid; pid = fork(); if (pid == 0) { printf("dette er barnet\n"); else { printf("barnet har PID=%d\n", (int)pid); $ fork2 Dette er barnet Barnet har PID=115 $ Forelesning 17.3.1998 Ark 13 av 21
Hvordan avslutte prosesser? En prosess kan avslutte normalt på tre forskjellige måter: Prosessen terminerer (med ukjent status) når programmet avsluttes. Hvis hovedprogrammet (main) avsluttes med en return-setning, vil dette være prosessens statusverdi. Systemkallet exit vil terminere prosessen, samt angi statusverdi. Statusverdi 0 angir «status OK»; andre verdier angir en feilsituasjon. Forelesning 17.3.1998 Ark 14 av 21
Å vente på andre prosesser Systemkallet wait benyttes til å vente på at prosessens barn skal bli ferdige. Kallet int status;. n = wait(&status); vil gjøre følgende: Hvis det ikke finnes flere barne-prosesser, returnerer wait øyeblikkelig med n = 1. Hvis det bare finnes levende barn, blir prosessen som kaller wait blokkert til ett av barna er ferdig. Returverdier som angitt i neste punkt. Når det finnes barn som er ferdige (eller drept), returnerer wait med følgende parametre: n er PID til den terminerte prosessen. status (nest nederste byte) inneholder slutt-status for den terminerte prosessen. status (nederste byte) inneholder data om hvorledes prosessen ble terminert; 0 angir nomal stopp, 0 angir nummeret til signalet som drepte prosessen. Forelesning 17.3.1998 Ark 15 av 21
$ more fork3.c #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> int main(void) { pid_t pid, n; int status; pid = fork(); if (pid) { /* Samme som (pid!= 0) */ printf("opphavet har PID=%d, ", (int)getpid()); printf("barnet har PID=%d\n", (int)pid); printf("nå venter opphavet...\n"); n = wait(&status); printf("n=%d, status=%x\n", (int)n, status); else { printf("barnet har PID=%d\n", (int)getpid()); printf("barnet får status=99\n"); exit(99); $ fork3 Barnet har PID=138 Barnet får status=99 Opphavet har PID=137, barnet har PID=138 Nå venter opphavet... n=138, status=6300 $ Forelesning 17.3.1998 Ark 16 av 21
Hvordan utføre programmer? Systemkallet execve benyttes til å utføre programmer. Kallet execve("/usr/bin/pwd", param, env); vil gjøre følgende: Alt innholdet av prosessen som utfører kallet, vil bli erstattet av innholdet av filen /usr/bin/pwd. Parametre og omgivelsen overføres. Den nye prosessen kjøres. Det er altså ingen retur fra en execve med mindre noe går galt! (Det finnes mange varianter av execve; ofte benyttes navnet exec om alle sammen. Forskjellen mellom de forskjellige dreier seg for det meste om hvorledes man kan sløyfe parametre eller gi disse på en alternativ måte. I dette kurset vil vi kun benytte execve.) Forelesning 17.3.1998 Ark 17 av 21
$ more pwdx.c #include <stdio.h> #include <sys/types.h> #include <unistd.h> char *Tom[1] = {NULL; int main(void) { execve("/usr/bin/pwd", Tom, Tom); perror("pwdx"); $ pwdx /home/beli/a/dag/in147/forelesninger/kode $ Forelesning 17.3.1998 Ark 18 av 21
Parametre til execve Andre og tredje parameter til execve angir parametre til kommandoen og omgivelsen kommandoen skal utføres i. (Omgivelsen er de variable som overføres mellom forskjellige utgaver av kommandotolkeren. I (ba)sh angis disse variablene som export, i C-shell med direktivet setenv.) Begge parametre er adresser til vektorer av pekere til tekster, og begge vektorene må avsluttes med en NULL-peker. $ more lsx.c #include <stdio.h> #include <sys/types.h> #include <unistd.h> char *par[] = { "ls", "-acf", NULL ; char *env[] = { "HOME=/home/beli/a/dag", "PATH=/bin:/usr/bin:/local/bin:", NULL ; int main(void) { execve("/bin/ls", par, env); perror("lsx"); $ lsx./../ lsx* lsx.c test-a@ $ Forelesning 17.3.1998 Ark 19 av 21
Program-parametre Parametrene og omgivelsesvariablene kommer som parametre til hovedprogrammet (main): $ more pars.c #include <stdio.h> int main(int argc, char *argv[], char *env[]) { int i; for (i = 0; i < argc ; i++) printf("argv[%d]= %s \n", i, argv[i]); i = 0; while (env[i]) { printf("env[%d]= %s \n", i, env[i]); i++; $ pars -la 122 /bin/cp argv[0]= pars argv[1]= -la argv[2]= 122 argv[3]= /bin/cp env[0]= PATH=:/bin:/usr/bin env[1]= TERM=minix env[2]= SHELL=/bin/sh. Antallet parametre er gitt i argc, mens listen av omgivelsesvariable avsluttes med en NULL-peker. Forelesning 17.3.1998 Ark 20 av 21
Hva skjer i en kommandotolker? En kommandotolker (som (ba)sh) gjør følgende når den skal utføre vanlige kommandoer: while (TRUE) { read_command(command, params); if (fork()!= 0) { wait(&status); else { execve(command, params, env); (Dette bildet er litt forenklet.) Forelesning 17.3.1998 Ark 21 av 21