Sistemi Operativi - Esercitazione 6: Comunicazione fra processi in
Transcript
Sistemi Operativi - Esercitazione 6: Comunicazione fra processi in
Sistemi Operativi Sistemi Operativi Esercitazione 6: Comunicazione fra processi in Linux PIPE Igino Corona [email protected] 17 Novembre 2009 Sistemi Operativi File In Linux, un le può essere un contenitore di informazione o uno strumento per la comunicazione fra processi o per interagire con dispositivi presenti sul calcolatore I Ecco perché spesso si dice che in Linux tutto è un le I Questa astrazione è elegante e al tempo stesso funzionale I Diverse tipologie di le sono distinte attraverso dei ag (si veda il manuale di ls, opzione -l) ·rw-rr 1 utente gruppo bytes Dec 4 16:30 nomefile I Ogni le (aperto in lettura e/o scrittura) è identicato in maniera univoca sul sistema operativo da un intero non negativo (descrittore del le) Sistemi Operativi Pipe Una pipe è un le speciale gestito con politica First In First Out (FIFO) Speciche I Tipicamente, può memorizzare 8 blocchi da 512KByte ciascuno I In generale, la costante PIPE_SIZE denisce la dimensione massima e PIPE_BUF denisce le dimensione max di ciascun blocco di dati (header limits.h) Funzionamento la pipe può essere vista come un nastro trasportatore I Un processo scrive ad una estremità della pipe (inserisce dei dati nel nastro) I Un altro processo legge all' altra estremità della pipe (preleva dei dati dal nastro) I Essenzialmente la pipe implementa una coda (algoritmo First In First Out (FIFO)) Sistemi Operativi Pipe Gestione della concorrenza Gestione dell'accesso la pipe viene gestita in maniera trasparente dal sistema operativo I La scrittura viene negata se la pipe risulta piena I La lettura viene negata se la pipe risulta vuota I La lettura viene negata se la pipe non è stata aperta in scrittura (da un qualche processo) Implementazione tramite buer circolare I Gestione della concorrenza basata sul modello produttore/consumatore Sistemi Operativi Pipe Tipologie Unnamed pipe I Named pipe Possono essere utilizzate solo da processi con qualche relazione di parentela (es. glio/glio e padre/glio) La loro esistenza è strettamente legata ai processi che le usano Come le memorizzati all'interno di una directory (hanno un preciso nome) Possono essere utilizzate da processi senza alcuna relazione di parentela I I I Sistemi Operativi Unnamed pipe Unnamed pipe Syscall pipe La syscall pipe crea una unnamed pipe. I Header richiesti <unistd.h> I Prototipo int pipe(int filedes[2]) I Prende in ingresso un array di due interi nel quale la funzione memorizza i descrittori di le I I I I filedes[0] conterrà il descrittore del le per la lettura filedes[1] conterrà il descrittore del le per la scrittura Output Restituisce 0 in caso di successo, altrimenti restituisce -1 e imposta la variabile globale errno NOTA Le prime versioni di UNIX e quelle attuali di Linux prevedono solo pipe unidirezionali Sistemi Operativi Named pipe Descrizione Named pipe Creazione Possono essere creati a livello di shell o all' interno di un programma: I La shell mette a disposizione il comando mknod per generare un le di tipo FIFO I All'interno di un programma è possibile generare delle named pipes richiamando la syscall mkfifo (quest'ultima a sua volta richiama la syscall mknod) Caratteristiche Qualunque processo sul calcolatore può accedere alla named pipe specicandone il nome (se detiene i permessi di accesso al le) Sistemi Operativi Named pipe Descrizione Named pipe Syscall mkfo La syscall mkfo crea una named pipe (le FIFO). I Header richiesti <sys/types.h>, <sys/stat.h> I Prototipo int mkfifo(const char *path, mode_t mode); I I I path è il nome del le che costituisce la FIFO mode specica i permessi sul le Output la chiamata a sistema restituisce 0 in caso di successo, -1 in caso di insuccesso. In quest'ultimo caso imposta la variabile errno Sistemi Operativi Named pipe Descrizione mode I I I mode è un intero in formato ottale che specica i permessi di accesso al le mode è nella forma ABC dove A, B, C indicano, rispettivamente, i permessi per proprietario, gruppo, altri. I permessi per ogni categoria sono determinati da R·22 +W·21 +X·20 : Read, Write, eXecution (1=permesso, 0=non permesso). Ad esempio se mode vale 231: I I I il proprietario può solo scrivere sul le (R=0,W=1,X=0: R·22 +W·21 +X·20 = 2) il gruppo può scrivere e eseguire (R=0,W=1,X=1: R·22 +W·21 +X·20 = 3) gli altri possono solo eseguirlo (R=0,W=0,X=1: R·22 +W·21 +X·20 = 1) Sistemi Operativi Named pipe Aprire un le Aprire un le Syscall open Un le può essere aperto/creato attraverso la syscall open. I Header richiesti <sys/types.h>, <sys/stat.h>, I I <fcntl.h> Prototipo int open (const char *nomefile, int flags); I nomefile è una stringa contenente il nome del le (path sul lesystem) I flags è un intero che determina la modalità di apertura del le. Esistono delle macro che identicano varie modalità, fra cui le più comuni sono le seguenti (combinabili tramite OR logico (|): O_CREAT crea il le se non presente, O_RDONLY apre il le in lettura, O_WRONLY apre il le in scrittura, O_APPEND apre il le in modalità append Output Restituisce il descrittore del le aperto in caso di successo, altrimenti, restituisce -1 e imposta la variabile errno. Sistemi Operativi Named pipe Chiudere un le Chiudere un le Syscall close Un le aperto può essere chiuso attraverso l'utilizzo della syscall close. I Header richiesti <unistd.h> I Prototipo int close(int fd); I I fd è il descrittore del le da chiudere Output Restituisce il valore 0 in caso di successo, altrimenti, restituisce -1 e imposta la variabile errno. Sistemi Operativi Named pipe Rimuovere un le Rimovere un le Syscall unlink Un le chiuso può essere rimosso dal lesystem attraverso l'utilizzo della syscall unlink. I Header richiesti <unistd.h> I Prototipo int unlink(const char *filename); I filename è il nome del le da eliminare (può contenere il percorso completo sul lesystem) I Output Restituisce il valore 0 in caso di successo, altrimenti, restituisce -1 e imposta la variabile errno. Sistemi Operativi Named pipe Scrivere su le Scrivere su le Syscall write La syscall write scrive un numero predenito di byte su le. I Header richiesti <unistd.h> I Prototipo ssize_t write(int filedes, const void *buf, size_t nbyte); I filedes è il descrittore del le su cui scrivere I buf è il buer con i dati da scrivere sul le I nbyte è il numero di byte da leggere in buf e scrivere sul le I Output Restituisce il numero di byte scritti, altrimenti, in caso di errore restituisce -1 e imposta la variabile globale errno Sistemi Operativi Named pipe Proprietà della syscall write Proprietà della syscall write I I I i byte vengono vengono accodati alla ne del le il sistema operativo garantisce la non interferenza tra più write() concorrenti su uno stesso le (se il numero di byte è minore di PIPE_BUF) di default la write() è bloccante Sistemi Operativi Named pipe Leggere da le Leggere da le Syscall read La syscall legge un numero predenito di byte da le. I Header richiesti <sys/types.h>, <sys/uio.h>, I I <unistd.h> Prototipo ssize_t read(int fildes, void *buf, size_t nbyte); I filedes è il descrittore del le da leggere I buf è il buer nel quale inserire i byte letti dal le I nbyte è il numero di byte da leggere sul le e scrivere su buf Output Restituisce il numero di byte letti, altrimenti, in caso di errore restituisce -1 e imposta la variabile globale errno Sistemi Operativi Named pipe Proprietà della syscall read Proprietà della syscall read I Le letture iniziano dalla posizione corrente Non sono previste operazioni di slittamento del puntatore (seek) read() è bloccante di default I Se il le è vuoto, il processo chiamante viene bloccato nché non vengono scritti dati o il le viene chiuso I I Sistemi Operativi Redirezione di input/output Redirezione input/output La redirezione di input e/o ouput di un processo è necessaria se I piuttosto che leggere da tastiera (standard input) abbiamo bisogno di leggere dati provenienti da un le (es. una pipe) I piuttosto che scrivere su video (standard output) abbiamo bisogno di scrivere dati su un le (es. una pipe) Con la syscall dup2 possiamo fare in modo di associare il le a uno dei descrittori seguenti: 0 standard input 1 standard output 2 standard error Sistemi Operativi Redirezione di input/output Redirezione input/output Syscall dup2 La syscall dup2 permette di associare allo stesso le un nuovo descrittore (crea cioè un descrittore di le duplicato). I Header richiesti <unistd.h> I Prototipo int dup2(int fd, int dupfd); I I I fd è il descrittore del le dupfd è il nuovo descrittore del le (duplicato) Output Restituisce il nuovo descrittore di le, altrimenti, in caso di errore restituisce -1 e imposta la variabile globale errno Sistemi Operativi Redirezione di input/output Esempio - unnamed pipe I I Le unnamed pipe sono usate dalla shell per passare l'output di un comando come input di un secondo comando Esempio ls directory | sort I Il programma ls_pipe_sort.c mostra come implementare questa operazione utilizzando le syscall fork, exec, pipe e dup2. Sistemi Operativi Redirezione di input/output Esempio - named pipe I I I Le named pipe orono la possibilità di comunicare fra processi diversi, non necessariamente con legami di parentela. Ad esempio, un processo client che raccoglie l'input da tastiera può inviare questo input ad un processo server che poi lo stampa a video. I programmi client.c e server.c mostrano come implementare questa operazione utilizzando le syscall open mkfifo, read, write e close. Sistemi Operativi Risorse utili I I I B. W. Kernighan, D. M. Ritchie, Il Linguaggio C, Prentice Hall Libreria standard GNU Linux GNU/Linux, pagine man