Dagens tema (kapittel 15 i Englander-boken)

Like dokumenter
Prosesser. Dagens tema. Hva er en prosess? En prosess er et program under utførelse.

Dagens program. Operativsystemer Prosesser og systemkall i UNIX Hente prosessens nummer Starte prosesser Vente på prosesser Utføre programmer

Dagens tema. Parallellitet Generelt Fraktaler Polling og avbrudd Multiprosessering i UNIX Opprettelse av prosesser Signaler

Operativsystemets ansvar er å koordinere. programmers bruk av I/O

Dagens tema. Nyttige programmer Programmet make. Flyt-tall Representasjon av flyt-tall. Standarden IEEE 754. Systemkall i Unix

Brukerhåndtering av prosesser i Linux

Dagens tema: Parallellstyring

IN 147 Program og maskinvare

Prosesstabeller (PCB - Prosess Control Block) Se på PD: kommandoene ps og top Bakgrunnsprosesser Opprettelse av prosesser:

Pekere og vektorer. Dagens tema. I C gjelder en litt uventet konvensjon:

Del 1 En oversikt over C-programmering

Del 4 Noen spesielle C-elementer

IN 147 Program og maskinvare. Vanlige feil ved bruk av pekere Feilsøking Debuggere

Oppsummering av IN147 siste del Operativsystemer Parallellisering Veien videre

Oving 2. Oppgave 1. #include <stdio.h> int main(int argc, char **argv) { char *navn = argv[1]; printf ("Navnet ditt er %s\n", navn); } Oppgave 2

Programmeringsspråket C

Kapittel 1 En oversikt over C-språket

Dagens tema C, adresser og pekere

Dagens tema INF1070. Vektorer (array er) Tekster (string er) Adresser og pekere. Dynamisk allokering

Programmeringsspråket C

Programmeringsspråket C

Programmeringsspråket C Del 3

Vektorer. Dagens tema. Deklarasjon. Bruk

oppgavesett 4 INF1060 H15 Øystein Dale Hans Petter Taugbøl Kragset September 22, 2015 Institutt for informatikk, UiO

Programmeringsspråket C Del 2. Hans Petter Taugbøl Kragset

Nyttige Linux-kommandoer. Hvordan du kan jobbe mer effektivt Dag Langmyhr

Dagens tema. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

EKSAMEN. Operativsystemer. 1. Læreboken "A Practical Guide to Red Hat Linux" av Mark Sobell 2. Maks. tre A-4 ark med selvskrevne notater.

Dagens tema INF1070. Signaturer. Typekonvertering. Pekere og vektorer. struct-er. Definisjon av nye typenavn. Lister

Oversikt. Beskrivelse Bash. 1 UNIX shell. 2 Kommandolinje som brukergrensesnitt. 3 Input og output. 4 Bash builtins. 5 Linux utilities.

IN 147 Program og maskinvare

Programmering i C++ Løsningsforslag Eksamen høsten 2005

Løsningsforslag til eksamen 24. november 2015

Dagens tema. Cs preprosessor Separat kompilering av C-funksjoner C og minnet Oversikt over operatorene

HØGSKOLEN I BERGEN Avdeling for ingeniørutdanning Data

OPPGAVE 1 OBLIGATORISKE OPPGAVER (OBLIG 1) (1) Uten å selv implementere og kjøre koden under, hva skriver koden ut til konsollen?

HØGSKOLEN I SØR-TRØNDELAG

Dagens tema. Dynamisk allokering Signaturer Definisjon av typer og nye typenavn Typekonvertering Pekere, vektorer og lister Dokumentasjon

Dagens tema INF1070. Vektorer (array-er) Tekster (string-er) Adresser og pekere. Dynamisk allokering

Programmeringsspråket C Del 2

Definisjon av prosess

Løsningsforslag til 2. del av Del - EKSAMEN

Dagens tema. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

Dagens tema. Cs preprosessor Separat kompilering av C-funksjoner C og minnet Oversikt over operatorene

Oversikt. Introduksjon Kildekode Kompilering Hello world Hello world med argumenter. 1 C programmering. 2 Funksjoner. 3 Datatyper. 4 Pekere og arrays

oppgavesett 4 INF1060 H16 Hans Petter Taugbøl Kragset Øystein Dale Christian Resell 27. september 2016 Institutt for informatikk, UiO

EKSAMEN. Operativsystemer. Kontroller at oppgaven er komplett før du begynner å besvare spørsmålene.

Fra Python til Java, del 2

Oppgave 1 - Linux kommandolinje (%)

Dagens tema: 12 gode råd for en kompilatorskriver

Dagens tema. Oppsummering om assemblerspråk. Programmering i C. Bakgrunn. Et minimalt eksempel med forklaring. Datatyper i C.

EKSAMEN. Operativsystemer. Dato: 10. desember 2008 Eksamenstid: kl til kl

Dagens tema. Hva er kompilering? Anta at vi lager dette lille programmet doble.rusc (kalt kildekoden): Hva er kompilering?

Dagens tema: 12 gode råd for en kompilatorskriver. Sjekking av navn. Lagring av navn. Hvordan finne et navn?

Faglig kontakt under eksamen: Orestis Gkorgkas

Dagens tema. Perl: Mer om regulære uttrykk Filer Lister og tabeller Kompilering og interpretering (kapittel ) IN 211 Programmeringsspråk

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

public static <returtype> navn_til_prosedyre(<parameter liste>) { // implementasjon av prosedyren

Dagens tema. Kort repetisjon om rutiner. Programmering i C Variable og adresser. Vektorer. Tekster. Preprosessoren. Separat kompilering

Oppgavene 1, 2, 4, 5, 6, 9, 12 og 13 passer best til å løses ved en datamaskin.

Transkript:

Dagens tema (kapittel 15 i Englander-boken) Prosesser Hvordan starte prosesser Å vente på prosesser Å utføre programmer Hva gjør en kommandotolker? Signaler Obligatoriske oppgave 2 Ark 1 av 25

Prosesser Hva er en prosess? En prosess er et program under utførelse. Hvordan lage nye prosesser? I Unix finnes kun én måte å lage nye prosesser på: pid = fork(); Følgende skjer: ❶ fork lager en nøyaktig kopi av prosessen. Returverdien i foreldreprosessen er barnets PID («process identification number»). Barneprosessen får 0 ved retur. ❷ Begge prosessene fortsetter å kjøre i parallell. Ark 2 av 25

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. OSet kan bruke statusverdien; i mange kommandotolkere kan man for eksempel skrive cc fil.c -o fil &&./fil Ark 3 av 25

Å vente på andre prosesser Systemkallet wait benyttes til å vente på at prosessens barn skal bli ferdige. Kallet #include <sys/types.h> #include <sys/wait.h> pid_t n; int status;. n = wait(&status); vil gjøre følgende: Hvis det ikke finnes flere barneprosesser, returnerer wait øyeblikkelig med n = 1. Når det finnes barn som er ferdige, returnerer wait med følgende parametre: n er PID til barnet. status (nest nederste byte) inneholder barnets statusverdi. status (nederste byte) inneholder data om hvorledes barnet ble avsluttet; 0 angir nomal stopp. Hvis det bare finnes levende barn, blir prosessen som kaller wait blokkert til ett av barna er ferdig. Ark 4 av 25

Eksempel Filen 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=0x%x\n", (int)n, status); return 0; else{ printf("barnet har PID=%d\n", (int)getpid()); printf("barnet får status=99\n"); exit(99); $fork3 Barnet har PID=20818 Barnet får status=99 Opphavet har PID=20817, barnet har PID=20818 Nå venter opphavet... n=20818, status=0x6300 Ark 5 av 25

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 gamle prosessen med det nye innholdet kjøres fra programstart. Det er altså ingen retur fra en execve med mindre noe går galt! (Det finnes mange varianter av execve. 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.) Ark 6 av 25

Eksempel Programmet /usr/bin/pwd skriver ut hvor i fil-treet vi befinner oss (mao hvor vi flyttet med siste cd-kommando). Det har ingen parametre. Filen pwdx.c inneholder vår versjon av pwd: #include <stdio.h> #include <sys/types.h> #include <unistd.h> char *empty[1] = {NULL; int main(void) { execve("/usr/bin/pwd", empty, empty); perror("pwdx"); exit(1); $ pwdx /ifi/ganglot/a03/dag/inf103/forelesninger/kode Ark 7 av 25

Parametre til execve Andre og tredje parameter til execve angir parametre til kommandoen og omgivelsen kommandoen skal utføres i. Begge parametre er adresser til vektorer av pekere til tekster, og begge vektorene må avsluttes med en NULL-peker. 0 ls -acf Omgivelsen er de variable som overføres mellom forskjellige utgaver av kommandotolkeren. I (ba)sh angis disse variablene som export, i(t)csh med direktivet setenv. Ark 8 av 25

Filen lsx.c #include <stdio.h> #include <sys/types.h> #include <unistd.h> extern char **environ; char *par[] = { "ls", "-acf", NULL ; int main(void) { execve("/bin/ls", par, environ); perror("lsx"); exit(1); Eksempel på kjøring: $lsx./../ lsx* lsx.c test-a@ Ark 9 av 25

Program-parametre Parametrene og omgivelsesvariablene kommer som parametre til hovedprogrammet (main) og den globale pekeren environ. Eksempel Filen pars.c #include <stdio.h> extern char **environ; int main(int argc, char *argv[]) { char **ep; int i; for (i = 0; i < argc ; i++) printf("argv[%d]= %s \n", i, argv[i]); ep = environ; while (*ep) { printf("%s\n", *ep); ++ep; return 0; Antallet parametre er gitt i argc, mens listen av omgivelsesvariable avsluttes med en NULL-peker. Tidligere brukte man en tredje parameter til main for å få tak i omgivelsesvariablene. Ark 10 av 25

Kjøring $ pars -la 122 /bin/cp argv[0]= pars argv[1]= -la argv[2]= 122 argv[3]= /bin/cp PWD=/home/ansatte/03/dag/IN147/Forelesninger/Kode PAGER=less HZ=100 REMOTEHOST=vidi.ifi.uio.no HOSTNAME=virfir.ifi.uio.no. Ark 11 av 25

Hva skjer i en kommandotolker? En kommandotolker (som (ba)sh) gjør følgende når den skal utføre vanlige kommandoer: while (1) { read_command(command, params); if (fork()!= 0) { /* Foreldreprosessen venter mens... */ wait(&status); else{ /*... barneprosessen kjører programmet. */ execve(command, params, env); (Dette bildet er litt forenklet!) Ark 12 av 25

Omgivelsesvariabelen PATH Når brukeren oppgir kommandoen pwd, hvor er da den tilhørende programfilen? I Unix angir PATH hvilke filområder det skal letes i. Det første programmet med riktig navn som finnes, blir brukt. > echo $PATH /usr/bin:/bin:/local/bin:. Programmet which kan brukes til å sjekke hvilket program som velges: > which pwd /usr/bin/pwd Ark 13 av 25

Forgrunnen og bakgrunnen En prosess kan kjøres i to ulike modi: Forgrunnen Prosessen har kontakt med tastatur og skjerm. Brukeren får ikke nytt klarsignal før prosessen er ferdig. Bakgrunnen Prosessen kan skrive på skjermen men ikke lese fra tastaturet. Brukeren får nytt klarsignal med en gang. Oftest brukes en & sist på linjen til å markere bakgrunnskjøring. Ark 14 av 25

Signaler Et signal er Unix-utgaven av et avbrudd. Det sendes fra kjernen i operativsystemet til de enkelte prosesser og er en «beskjed» om at noe spesielt har skjedd. Hvis prosessen har sagt fra om at den vil håndtere signalet, startes den spesielle signal-rutinen. Hvis ikke, drepes prosessen. I noen tilfelle skrives dump av lageret (core-fil). Ark 15 av 25

Listen over alle signalene i Linux finnes på filen /usr/include/bits/signum.h: #define SIGHUP 1 /* Hangup (POSIX). */ #define SIGINT 2 /* Interrupt (ANSI). */ #define SIGQUIT 3 /* Quit (POSIX). */ #define SIGILL 4 /* Illegal instruction (ANSI). */ #define SIGTRAP 5 /* Trace trap (POSIX). */ #define SIGABRT 6 /* Abort (ANSI). */ #define SIGIOT 6 /* IOT trap (4.2 BSD). */ #define SIGBUS 7 /* BUS error (4.2 BSD). */ #define SIGFPE 8 /* Floating-point exception (ANSI). */ #define SIGKILL 9 /* Kill, unblockable (POSIX). */ #define SIGUSR1 10 /* User-defined signal 1 (POSIX). */ #define SIGSEGV 11 /* Segmentation violation (ANSI). */ #define SIGUSR2 12 /* User-defined signal 2 (POSIX). */ #define SIGPIPE 13 /* Broken pipe (POSIX). */ #define SIGALRM 14 /* Alarm clock (POSIX). */ #define SIGTERM 15 /* Termination (ANSI). */ Ark 16 av 25

#define SIGSTKFLT 16 /* Stack fault. */ #define SIGCLD SIGCHLD /* Same as SIGCHLD (System V). */ #define SIGCHLD 17 /* Child status has changed (POSIX). */ #define SIGCONT 18 /* Continue (POSIX). */ #define SIGSTOP 19 /* Stop, unblockable (POSIX). */ #define SIGTSTP 20 /* Keyboard stop (POSIX). */ #define SIGTTIN 21 /* Background read from tty (POSIX). */ #define SIGTTOU 22 /* Background write to tty (POSIX). */ #define SIGURG 23 /* Urgent condition on socket (4.2 BSD). */ #define SIGXCPU 24 /* CPU limit exceeded (4.2 BSD). */ #define SIGXFSZ 25 /* File size limit exceeded (4.2 BSD). */ #define SIGVTALRM 26 /* Virtual alarm clock (4.2 BSD). */ #define SIGPROF 27 /* Profiling alarm clock (4.2 BSD). */ #define SIGWINCH 28 /* Window size change (4.3 BSD, Sun). */ #define SIGPOLL SIGIO /* Pollable event occurred (System V). */ #define SIGIO 29 /* I/O now possible (4.2 BSD). */ #define SIGPWR 30 /* Power failure restart (System V). */ #define SIGSYS 31 /* Bad system call. */ #define SIGUNUSED 31 Under Solaris kan man benytte kommandoen man 5 signal. Ark 17 av 25

De viktigste signalene SIGINT gir et middels sterkt ønske om terminering. SIGQUIT er som SIGINT men gir core-dump. SIGKILL er en drapsordre. SIGALRM er en vekkerklokke. SIGTERM er et vennlig «klapp på skulderen». Ark 18 av 25

Hvordan sende et signal? Et signal kan oppstå på flere måter: Fra kjernen av systemet (ved feilsituasjon). Fra kjernen av systemet (vekkerklokken). Fra tastaturet ( Ctrl + C eller Ctrl + \ ). Fra systemkallet kill. Fra kommandoen kill. $ kill 123 # Send SIGTERM $ kill -9 123 # Send SIGKILL Ark 19 av 25

Hvordan fange opp et signal? Systemkallet signal brukes til å fortelle systemet hvilket signal som skal fanges opp og hvilken rutine som skal håndtere det. #include <signal.h> #include <stdio.h> #include <stdlib.h> void catch_int(int sig) { printf("\net SIGINT-signal (nr %d) fanget opp.\n", sig); exit(1); int main(void) { int i, j, k; signal(sigint, catch_int); /* Gjør et eller annet i evig løkke... */ for (i = 1; 1; i++) { for (j = 1; j <= 1000000; j++) k = k*3; printf("%5d", i); if (i % 10 == 0) putchar( \n ); > signal0 1 2 3 4 5 6 7 8 9 10 11 Ctrl + C Et SIGINT-signal (nr 2) fanget opp. Ark 20 av 25

Følgende er verdt å merke seg: I noen Unix-versjoner er det slik at når et signal først er fanget opp, må signal kalles på nytt for det signalet. I filen /usr/include/signal.h finnes prototypen til signal. Navnet SIGINT (og de andre signalnavnene) er indirekte definert der. Noen signaler ignoreres om brukeren ikke har angitt signalhåndteringsrutine; andre dreper prosessen. Signalet SIGKILL kan ikke fanges opp av en brukerprosess. Systemkallet pause vil la en prosess sove til den mottar et signal. Ark 21 av 25

Bruk av signal Dette programmet prøver å beskytte seg: #include <signal.h> #include <stdio.h> void catch_int(int sig) { printf("ha, ha! SIGINT vekker ikke meg!\n"); signal(sigint, catch_int); pause(); int main(void) { printf("nå sover jeg...\n"); signal(sigint, catch_int); pause(); Det hjelper ikke om man vet litt om signaler: > sov Nå sover jeg... Ctrl + C Ha, ha. SIGINT vekker ikke meg! Ctrl + C Ha, ha. SIGINT vekker ikke meg! Ctrl + \ Quit - core dumped > sov & [1] 28703 Nå sover jeg... > kill -2 28703 Ha, ha! SIGINT vekker ikke meg! > kill 28703 [1] Terminated sov Ark 22 av 25

Vekkerklokker Vekkerklokker er en spesiell type signaler som gjør det mulig å la prosesser vente et gitt antall sekunder og så bli vekket av en alarm. Kallet alarm(10); vil medføre at det (omtrent) 10 sekunder senere kommer et SIGALRM-signal til prosessen. #include <signal.h> #include <stdio.h> void catch_alrm(int x) { printf("nå er tiden ute.\n"); int main(void) { printf("nå tar vi 10 sekunder pause...\n"); signal(sigalrm, catch_alrm); alarm(10); pause(); printf("da er programmet ferdig.\n"); return 0; > sov10 Nå tar vi 10 sekunder pause... Nå er tiden ute. Da er programmet ferdig. Ark 23 av 25

Obligatorisk oppgave 2 Denne oppgaven går ut på å skrive en kommandotolker kalt ifish. Den skal ❶Skrive et klarsignal («prompt»). ❷ Lese en linje. ❸ Splitte opp linjen i kommandonavn og parametre. ❹ Om kommandoen er exit, skal ifish avslutte. ❺ Ellers skal ifish starte en barneprosess. ❻ Barneprosessen skal utføre execve på kommandoen. Dette gjøres ved å prøve med alle stier i omgivelsesvariabelen PATH foran. ❼ Om kommandolinjen ikke slutter med &, skal ifish vente til barneprosessen er ferdig. ❽ Gå til punkt 1 igjen. For å gjøre det enklere å løse oppgaven, er den delt i tre. Ytterligere detaljer finnes i oppgavetekstene. Ark 24 av 25

Regn med at du vil gjøre feil under programmeringen. Legg inn masse testutskrifter! #define DEBUG 1 : #if DEBUG printf(...); #endif Sjekk spesielt alt som har med tekster å gjøre. Bruk anførselstegn i testutskriftene printf("kommandoen er %s.\n", kommando); for å oppdage overfødige blanke. Sjekk hvert punkt grundig før du tar fatt på neste punkt. Sjekk at programmet ikke har minnelekkasje. Sjekk feilmeldinger fra systemkall som safefork og malloc. Skriv kommentarer fra starten av. Er det vanskelig å beskrive, er det sikkert dårlig programmert. Det er alltid en feil til! Ark 25 av 25