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