170 likes | 276 Views
Simulering af spisende filosoffer. // philosopher.c #include <forks.h> #include <think_and_eat.h> philosopher(int i) { while (TRUE) { think(); take_fork(i); take_fork((i+1) % 5); eat(); put_fork(i); put_fork(i+1); } }. Middagsselskab simuleres
E N D
Simulering af spisende filosoffer // philosopher.c #include <forks.h> #include <think_and_eat.h> philosopher(int i) { while (TRUE) { think(); take_fork(i); take_fork((i+1) % 5); eat(); put_fork(i); put_fork(i+1); } } • Middagsselskab simuleres • med fem (mindst) samtidige • processer. • Krav til simulering • ingen gaffeldeling • spisning kræver to gafler • ingen deadlock • mindst mulig forsinkelse • .. kræver raffineret brug af IPC • = Inter-Proces Communication
Kildetekstfiler forks.h forks.c think_and_eat.h think_and_eat.c philosopher.h philosopher.c dinner.c
Skabelse af filosofprocesser • // dinner.c • #include <philosopher.h> • main() { • int philosophers = 5,i,pid; • for (i=0; i<philosophers; i++) { • pid = fork(); • switch(pid) { • case -1: printf("error"); exit(1); • case 0: philosopher(i); exit(0); • } • } • } • Filosof skabes alene med fork(), dvs. uden exec(). • "Middagsselskab" og "filosof" deler programtekst. • Filosof-procedure kaldes i betinget sætning.
Beskyttelse af kritisk region • Problem: race-conditions • fejl, inkonsistens el.lign. opstår hvis flere processer tilgår samme ressource • eksempel: flere processer læser og skrive i samme datafil ..; første tilgang til ressource ressource; .. sidste tilgang til ressource; ..; Test og sæt lås Kritisk region Lås op igen • Løsninger • semaforer, låsefiler, m.m. • Krav til løsningerne: • lås kun hvis nødvendigt • ingen race conditions i selve test-og-sæt-lås programdelen • ingen deadlock
Hvor er kritiske region(er) ? // philosopher.c #include <forks.h> #include <think_and_eat.h> philosopher(int i) { while (TRUE) { think(); take_fork(i); take_fork((i+1) % 5); eat(); put_fork(i); put_fork(i+1); } }
Kritiske regioner (I) philosopher(int i) { while (TRUE) { think(); take_fork(i); take_fork((i+1) % 5); eat(); put_fork(i); put_fork(i+1); } } (II) philosopher(int i) { while (TRUE) { think(); take_fork(i); //1 take_fork((i+1) % 5); //1 eat(); put_fork(i); //2 put_fork(i+1); //3 } }
Naiv implementation af "test og sæt lås" #define TRUE 1 #define FALSE 0 int available; while (! available){ sleep(1); } available = FALSE; available = TRUE ..; første tilgang af ressource; .. sidste tilgang til ressource; ..;
Implementation af "test og sæt lås" med låsefil char lock[] = "LockFile" while (open(lock,O_RDWR|O_CREAT|O_EXCL,0666)<0){ sleep(1); } remove(lock); ..; første tilgang af ressource; .. sidste tilgang til ressource; ..; • open() tester og (evt.) låser i udelelig sekvens. • Test = findes filen ? • Låsning = skab filen
Implementation af "test og sæt lås" med semafor(forenklet) semaphore sem; down(sem); up(sem); ..; første tilgang af ressource; .. sidste tilgang til ressource; ..; • Hvad er en semafor ? • Har talværdi som altid er større end eller lig nul. • Har atomisk "down" operation som trækker 1 fra hvis muligt, ellers blokeres. • Har atomisk "up" operation som lægger 1 til og vækker blokerede processer.
Skitse af semafor-implementation a la Tanenbaum ? • down(int *sem) { • if (*sem == 0) { SLEEP}; • (*sem)-- ; • } • up(int *sem) { • (*sem)++; • {WAKE UP ONE SLEEPING PROCESS}; • } • Skitse bruger pointer for at modificere variabel i kaldsomgivelser. • Skitse mangler sikring af atomicitet og kommunikation (WAKE UP). SLEEP (*sem)-- (*sem)++ WAKE UP
Pointer-opgave #include <stdio.h> main() { char ch = 'A',*p = &ch; printf("(1) %d %c \n",ch,ch); // hvad udskrives ? ch = ch*2 - 64; printf("(2) %d %c \n",*p,*p); // hvad udskrives ? }
Systemkald til at arbejde medsemaforer • Atomicitet via disabling af interrupt. • "Sleep" og "wake up" håndteres af operativsystemet. • Uafhængige processer kan tilgå samme semafor. • Navngivning af semaforer med heltal. • Faciliteter til gruppering, initialisering, m.m. int semget(<nøgle>,<antal>,<flag: rettigheder, betingelser>) int semop(<id>,<nr;ændring;flag>,<antal>) int semctl(<id>,<nr>,<flag:SETVAL>,<værdi;..>); Normalt +1 eller -1
Producent / forbruger(jf. Tanenbaum fig. 2-11 s. 43) producent forbruger • Løsning med semaforer • mutex (0-1) • empty (0-1-2-3-4-5) // tomme poster • full (0-1-2-3-4-5) // fyldte poster • Krav: • undgå kaos (samtidig læs/skriv) • undgå overflow • undgå "underflow"
Shellscripts Et shellscript er en fil med kommandoer der kan forstås og udføres af shellen. Shellscripts kan begynde med #!/bin/sh for at fortælle operativsystemet, at sciptet skal fortolkes af det angivne program (shellen). Samme effekt af følgende: <prompt> Kommando <prompt> /bin/sh Fil hvis Fil indeholder Kommando <prompt> Fil hvis Fil indeholder #!/bin/sh samt Kommando
#!/bin/bash # bytecounter (kommentar) if [ $# != 1 ] # test, antal par. then echo "usage: bytecounter katalog" # udskrivning exit # terminering fi cd $1 # ref. til par. for file in $(ls) # loop; stdout af ls do if [ -f $file ] # er det en fil ? then wc -c $file # antal tegn udskrives else if [ -d $file ] # et katalog ? then echo "Går til katalog: $file" $0 $file # prøv & and exec her echo "Tilbage i katalog: $1" fi fi done
Udførelse af delopgave "p"(selvstændigt program) Program F vil have udført program P start-vent start-fortsæt overlejring F F F P P P
Processkabelse i C vs. shellscripts • Start "p" og vent: • shellscript: p • c-program: fork(); exec(p,..) // wait() • Start "p" og fortsæt: • shellscript: p & • c-program: fork(); exec(p,..) // - • Fortsæt som "p": • shellscript: exec p • c-program: exec(p,..)