Sistemi operativi, A.A. 2011/2012 (M. Cesati) Scaletta esercitazione #9, 10.05.2012 [Agg. 07.11.2012] 1 Misurare con il comando "time" la durata dell'esecuzione del comando ./mandelbrot m1.pgm -2.5 -1.5 3 (dalla esercitazione precedente) 2 Esercizio: Modificare il programma 'mandelbrot' in modo che utilizzi due processi in parallelo per costruire l'immagine [mandelbrot2.c] 2.1 Verificare con il comando 'cmp' che il file prodotto e' identico a quello del programma con un solo processo 2.2 Misurare con il comando "time" la durata dell'esecuzione del comando ./mandelbrot2 mag2.pgm -2.5 -1.5 3 2.3 Avendo due soli processi la chiamata di sistema wait() e' sufficiente per risolvere il problema di sincronizzazione; utilizzando tre o piu' processi wait() non e' piu' sufficiente 3 Sincronizzazione tra processi tramite BSD file locking 3.1 La chiamata di sistema flock() +---------------------------------+ |int flock(int fd, int operation);| +---------------------------------+ acquisisce un lock su un intero file, eventualmente bloccando il processo finche' l'operazione non diventa possibile 3.2 L'operazione e' uno dei seguenti valori +------------------------------------------------+ |LOCK_SH: accesso in condivisione | |LOCK_EX: accesso esclusivo | |LOCK_UN: rilascio del lock | |LOCK_NB: flag per rendere flock() non bloccante | +------------------------------------------------+ 3.3 Il lock e' associato alla voce della tabella dei file aperti 3.3.1 Un lock e' automaticamente rilasciato chiudendo il file (ossia applicando close() su *tutti* i descrittori di file corrispondenti al file aperto) 3.3.2 Un lock acquisito prima di una fork() puo' essere rilasciato sia dal padre che dal figlio 3.3.2b Percio' flock() non puo' essere utilizzato se il processo figlio utilizza lo stesso file aperto del padre! 3.3.3 Un lock puo' essere rilasciato tramite un descrittore di file differente da quello con cui e' stato acquisito, se questi fanno riferimento allo stesso file aperto 4 Cambiare il puntatore corrente del file 4.1 La chiamata di sistema lseek() +----------------------------------------------+ |off_t lseek(int fd, off_t offset, int whence);| +----------------------------------------------+ modifica la posizione corrente del file aperto associato al descrittore 4.2 Il parametro "whence" e' uno dei seguenti valori +----------------------------------------------------+ |SEEK_SET: posizione relativa all'inizio del file | |SEEK_CUR: posizione relativa alla posizione attuale | |SEEK_END: posizione relativa alla fine del file +1 | +----------------------------------------------------+ 4.3 Il parametro "offset" e' la nuova posizione; puo' essere un valore negativo se whence e' diverso da SEEK_SET 4.4 Il valore restituito da lseek() in assenza di errori e' la nuova posizione corrente del file come spiazzamento rispetto all'inizio 4.5 E' possibile creare "buchi" (file hole) posizionando il puntatore del file oltre la fine del file e poi scrivendo dati: il file viene esteso, e tutti i dati mancanti sono semanticamente equivalenti a zeri 4b Sincronizzazione tra processi tramite fcntl() locks [Agg. 7.11.2012] 4b.1 La chiamata di sistema fcntl() +---------------------------------+ |int fcntl(int fd, int cmd, ...); | +---------------------------------+ con cmd == F_SETLKW acquisisce un lock su un (blocco di un ) file eventualmente bloccando il processo finche' l'operazione non diventa possibile 4b.2 Il terzo argomento e' il puntatore ad una struttura che include i campi: 4b.2.1 l_type: F_RDLCK, F_WRLCK, F_UNLCK 4b.2.2 l_whence: SEEK_SET, SEEK_CUR, SEEK_END 4b.2.3 l_start: posizione iniziale del blocco del file 4b.2.4 l_len: lunghezza del blocco del file (0 == fino a EOF) 4b.3 Il lock e' associato all'inode 4b.3.1 Il lock viene rilasciato se il file viene chiuso 4b.3.2 Un lock non e' passato al figlio dopo fork(), ma e' ereditato da execve() se il file resta aperto 4b.3.3 Un lock viene rilasciato se il file lockato viene riaperto richiuso (con un altro file descriptor) dallo stesso processo 5 Esercizio: Modificare il programma 'mandelbrot2' in modo che utilizzi tre processi in parallelo per costruire l'immagine [mandelbrot3.c] utilizzare fcntl file locking e lseek 5.1 Misurare con il comando "time" la durata dell'esecuzione del comando ./mandelbrot3 m3.pgm -2.5 -1.5 3 5.2 Spiegare perche' il programma ha prestazioni molto peggiori di quello che usa solo due processi ==========