Lezione 14 Comunicazione

Download Report

Transcript Lezione 14 Comunicazione

Lezione 14
Comunicazione
Sistemi Operativi (9 CFU), CdL Informatica, A. A. 2014/2015
Dipartimento di Scienze Fisiche, Informatiche e Matematiche
Università di Modena e Reggio Emilia
http://weblab.ing.unimo.it/people/andreolini/didattica/sistemi-operativi
1
Quote of the day
(Meditate, gente, meditate...)
“The single biggest problem in
communication is the illusion that it
has taken place. ”
George Bernard Shaw (1856-1950)
Scrittore, drammaturgo
Premio Nobel per la letteratura nel 1925
2
INTRODUZIONE
3
Problema: comunicazione fra applicazioni
(Applicazioni diverse eseguite tramite programmi diversi)
Con la conoscenza attuale si è in grado di creare
applicazioni cooperanti, con un unico grande
vincolo: il programma che gestisce l'applicazione
deve essere multi-threaded.
Non è possibile programmare applicazioni che
usano diversi programmi pre-esistenti.
Grande limitazione!
→ Servono meccanismi di comunicazione fra
processi distinti (non solo thread).
4
Problema: comunicazione inter host
(Applicazioni distribuite su host diversi)
Un ulteriore limite è l'impossibilità attuale di far
comunicare processi su macchine distinte
connesse in rete (host).
→ I meccanismi di comunicazione devono poter
operare su host diversi.
In questo corso introduttivo non affronteremo il
problema della comunicazione inter host. Ci
limiteremo alla comunicazione intra host.
E poi ditemi che non vi voglio bene...
5
Inter Process Communication
(IPC: meccanismi per la comunicazione fra processi)
La cooperazione fra processi avviene tramite
diversi meccanismi che prendono il nome di Inter
Process Communication (IPC).
Obiettivo della IPC: permettere lo scambio di dati
fra processi distinti operanti (nel nostro caso)
localmente.
I processi che usano la IPC sono detti cooperanti.
6
Vantaggi della cooperazione
(Tanti e importanti)
Notifica di eventi.
Un'applicazione può notificare eventi (ad es., anomalie)
ad un'altra, oppure controllarla.
Accelerazione del calcolo (speedup).
Una tecnica comune per velocizzare i calcoli consiste
nello spezzare il problema in tanti piccoli sottoproblemi
eseguibili in parallelo.
I sottoproblemi possono essere eseguiti da processi
cooperanti in un sistema SMP.
7
Vantaggi della cooperazione
(Tanti e importanti)
Modularità.
La suddivisione di un problema in più
sottoproblemi è utile anche come strumento di
modularizzazione del software.
Riuso di codice, eliminazione delle ridondanze.
Ambiente operativo più ricco.
L'introduzione di processi cooperanti permette la
creazione di comandi complessi a partire da
comandi unitari semplici.
Pipe UNIX.
8
Modelli di IPC
(Scambio di messaggi, memoria condivisa)
Scambio di messaggi
(message passing).
Un
processo
cooperante
impacchetta i dati in messaggi che
saranno inviati ad un altro
processo cooperante.
Segnali.
Pipe.
Named pipe.
In questo corso introduttivo
vedremo solo questi meccanismi.
Processo A
M
Processo B
M
2
Kernel
1
M
9
Modelli di IPC
(Scambio di messaggi, memoria condivisa)
Memoria condivisa
(shared memory).
Uno dei processi cooperanti crea
un'area di memoria contigua visibile
agli altri.
I processi si agganciano all'area di
memoria condivisa e interagiscono
(scrivono, leggono) con essa come se
fosse allocata localmente.
POSIX shared memory.
Processo A
1
Memoria condivisa
2
Processo B
Kernel
10
SEGNALI
11
Definizione
(Che cosa sono i segnali)
Un segnale è una notifica asincrona inviata da un
task (o dal kernel) ad un altro task.
Notifica asincrona: non esiste sincronizzazione
alcuna fra i task coinvolti.
Il task mittente invia il segnale quando lo reputa
opportuno.
Il task destinatario riceve il segnale potenzialmente ad
un qualunque istante (quando il kernel lo consegna).
I segnali sono il meccanismo primordiale di
comunicazione in ambiente POSIX.
man 7 signal per tutti i (sordidi) dettagli.
12
Ciclo di vita di un segnale
(Tre fasi distinte)
Passo 1. Un evento provoca la generazione del
segnale da parte del kernel per conto di un
processo.
Passo 2. Il kernel accoda il segnale generato al
processo destinatario. Il segnale viene detto
pendente.
Passo 3. Non appena il processo viene
rischedulato, il segnale pendente gli viene
consegnato.
13
Origine dei segnali
(Duplice natura: asincrona o sincrona)
Asincrona: un evento del tutto indipendente
dall'esecuzione di un programma (e non ad esso
sincronizzato) provoca la generazione del segnale
e la sua successiva notifica.
L'utente interrompe un comando con CTRL-C.
L'utente sospende un comando con CTRL-Z.
L'utente ridimensiona una finestra di terminale.
...
14
Origine dei segnali
(Duplice natura: asincrona o sincrona)
Sincrona: un evento del tutto dipendente
dall'esecuzione di un programma (e con esso
sincronizzato) provoca la generazione del segnale
e la sua successiva notifica.
La CPU esegue un'istruzione malformata o illegale
(divisione per zero).
La CPU prova ad accedere ad una locazione di
memoria non assegnata al processo.
...
15
Meccanismi per l'invio di segnali
(Forniti dal SO alle applicazioni e agli utenti)
Il SO mette a disposizione diversi meccanismi per
la generazione e l'invio (raise) di segnali.
Shortcut da tastiera, icone ed applicazioni di gestione
dei processi per per l'utente principiante.
Comandi builtin ed esterni per l'utente avanzato.
Chiamate di sistema specifiche per il programmatore.
Funzioni di basso livello (kernel) per la consegna di
segnali in risposta ad anomalie nell'applicazione.
16
Modalità di ricezione dei segnali
(Forniti dal SO ai programmatori)
Il SO permette ai programmatori di specificare
(tramite opportune chiamate di sistema) la
reazione dell'applicazione alla ricezione di un
segnale. Ad una reazione corrisponde, in
generale, una ben specifica funzione, detta
gestore dei segnali (signal handler).
Ogni segnale ha una sua reazione di default, che
viene adottata nel caso in cui il programmatore
non specifichi altrimenti il comportamento da
intraprendere nei confronti del segnale ricevuto. 17
Reazioni alla consegna del segnale
(IGNORE: il kernel non consegna il segnale)
IGNORE.
Il processo imposta inizialmente una modalità di
“ignore” del segnale.
Il kernel non consegna al processo alcun segnale
ignorato.
Il processo non si accorge dei tentativi di consegna.
Al processo non è associato alcun gestore per quel
segnale.
18
Reazioni alla consegna del segnale
(TERMINATE: il processo termina; CORE DUMP: si salva la memoria in un file)
TERMINATE.
Il processo è terminato (killed)
Si parla di terminazione anomala (contrapposta alla
normale che avviene tramite exit()).
CORE DUMP.
Si genera una immagine della memoria virtuale del
processo, e la si salva in un file detto “core dump”.
Il processo viene successivamente terminato.
Il core dump può essere ispezionato in seguito con
l'ausilio di un debugger.
19
Reazioni alla consegna del segnale
(STOPPED: il processo è bloccato; CONTINUED: il processo è ripristinato)
STOPPED.
L'esecuzione del processo è temporaneamente
sospesa.
CONTINUED.
L'esecuzione del processo è ripristinata.
GENERIC HANDLER.
Il processo esegue una funzione specificata dal
programmatore.
20
Invio di segnali a processi
(Comando esterno /bin/kill)
Il comando esterno /bin/kill invia segnali a
processi.
Identifica i processi tramite PID o nome
(anche parziale).
Identifica i segnali tramite numero oppure tramite il
loro nome.
Proviamolo!
21
Esercizi (2 min.)
1. Si apra un nuovo terminale e si esegua il
comando top. Si usi il comando /bin/kill
sul processo top. Che cosa è successo?
22
Una svista molto comune
(Usare il builtin kill pensando di usare il comando esterno /bin/kill)
OCCHIO: la BASH fornisce il builtin kill,
versione ridotta di /bin/kill.
kill ha opzioni diverse da /bin/kill.
Documentarsi con man kill e poi eseguire kill è
da principianti (e sono stato anche buono).
Uno studente attento avrebbe dovuto:
digitare type -a kill e vedere quali comandi sono
disponibili.
digitare help kill e man kill per documentarsi
sulle differenze.
24
scegliere consapevolmente uno dei due comandi.
“Non avere paura!”
(“Io sono il tuo confessore! Non ti succede niente!”)
25
A che serve il builtin kill?
(Bella domanda, e ancora più bella la risposta!)
Il builtin kill è utilissimo in un frangente molto
particolare.
Il SO è soggetto ad una fork bomb e un terminale
eseguente BASH è aperto.
Se si riesce a scrivere il comando kill
PID_bomb BASH uccide la fork bomb.
/bin/kill invece non partirebbe neanche, dal
momento che la fork bomb ha esaurito la tabella
dei processi!
26
Quanti tipi di segnali esistono?
(Opzione -L del comando esterno /bin/kill)
L'opzione -L del comando esterno /bin/kill
fornisce una lista succinta dei segnali disponibili.
/bin/kill -L
L'elenco è particolarmente nutrito!
Alcune domande sorgono spontanee.
Che significato hanno tutte quelle sigle?
Cosa fanno quei segnali?
Che segnale è stato usato nell'esercizio precedente?
27
Classificazione dei segnali
(man 7 signal)
La pagina di manuale descrivente i segnali ne
spiega anche la semantica.
man 7 signal
Si scorre fino alla sezione “Standard Signals”.
Per ciascun segnale sono dettagliati:
una stringa identificativa (usata nei comandi).
un numero intero identificativo (usato nei comandi).
la reazione di default.
una spiegazione dell'effetto del segnale.
28
I segnali più comuni: TERM
(Segnale no. 15: terminazione “dolce”)
Il segnale numero 15, detto SIGTERM, notifica
ad un processo l'evento “terminazione
dell'applicazione”.
La sua azione di default è: terminare il processo.
Come genera un SIGTERM un utente casuale?
Schiaccia il pulsante  su una finestra.
Usa un gestore di processi (ad es. top, comando k).
Usa il comando esterno /bin/kill.
29
Esercizi (2 min.)
2. Si apra un nuovo terminale e si esegua il
comando top. Si invii il segnale SIGTERM al
processo top usando il comando esterno
/bin/kill.
30
Un dubbio amletico
(Il segnale di default usato da /bin/kill non sarà per caso TERM?)
A questo punto gli studenti
più attenti faranno una giusta
osservazione.
Il segnale di default usato
da /bin/kill è SIGTERM.
L'effetto su top è lo stesso...
È così?
Sì, è proprio così!
Lo verifichiamo?
(Malfidati :-)
32
Esercizi (2 min.)
3. Si apra un nuovo terminale e si esegua il
comando top. Si verifichi che il segnale inviato
a top tramite il comando seguente:
/bin/kill $(pgrep top)
è effettivamente SIGTERM.
33
I segnali più comuni: SIGKILL
(Segnale no. 9: terminazione “dura”)
Il segnale numero 9, detto SIGKILL, notifica ad
un
processo
l'evento
“terminazione
dell'applicazione”.
La sua azione di default è: terminare il processo.
Un momento: non è identico a SIGTERM?
Quasi. Cosa cambia?
SIGTERM può essere gestito con un gestore
impostato appositamente dal programmatore.
Chiude file aperti, dealloca la memoria, etc. etc. etc.
SIGKILL no. SIGKILL si subisce e basta.
35
Che si usa? SIGKILL o SIGTERM?
(Prima SIGTERM con le buone; poi SIGKILL con le cattive)
È preferibile inviare sempre un SIGTERM, in
modo tale da permettere ad una applicazione di
poter eseguire un eventuale gestore.
Se l'applicazione non risponde, si può terminarla
di forza con un SIGKILL.
Il sistema di inizializzazione dei servizi di
GNU/Linux adotta proprio questo approccio.
36
Uno screenshot
significativo
(Vale sempre più di √106 parole)
Guardate qui!
37
I segnali più comuni: SIGINT
(Segnale no. 2: interruzione da tastiera)
Il segnale numero 2, detto SIGINT, notifica ad
un processo l'evento “interruzione da tastiera”.
La sua azione di default è: terminare il processo.
Come genera un SIGINT un utente casuale?
L'utente preme la sequenza CTRL-C sul terminale (il
processo in esecuzione si interrompe).
Si usa il comando esterno /bin/kill (si simula la
pressione della sequenza CTRL-C).
38
Esercizi (1 min.)
4. Si apra un nuovo terminale e si esegua il
comando top. Si invii il segnale SIGINT al
processo top usando la tastiera.
39
Esercizi (1 min.)
5. Si apra un nuovo terminale e si esegua il
comando top. Si invii il segnale SIGINT al
processo top usando il comando esterno
/bin/kill.
41
I segnali più comuni: SIGSTOP
(Segnale no. 19: sospensione)
Il segnale numero 19, detto SIGSTOP, notifica ad
un processo l'evento “sospensione”.
La sua azione di default è: stoppare il processo.
Come genera un SIGSTOP un utente casuale?
L'utente preme la sequenza CTRL-S sul terminale (il
processo in esecuzione si blocca temporaneamente).
Si usa il comando esterno /bin/kill (si simula la
pressione della sequenza CTRL-S).
43
Esercizi (2 min.)
6. Si apra un nuovo terminale e si esegua il
comando ls -lR /. Si invii il segnale
SIGSTOP al processo ls usando la tastiera.
Cosa succede al processo?
44
I segnali più comuni: SIGCONT
(Segnale no. 18: ripristino)
Il segnale numero 18, detto SIGCONT, notifica ad
un processo l'evento “ripristino”.
La sua azione di default è: ripristinare il processo.
Come genera un SIGCONT un utente casuale?
L'utente preme la sequenza CTRL-Q sul terminale (il
processo in esecuzione si sblocca).
Si usa il comando esterno /bin/kill (si simula la
pressione della sequenza CTRL-Q).
46
Esercizi (1 min.)
7. Si invii il segnale SIGCONT al processo ls
usando la tastiera. Cosa succede al processo?
47
Perché esistono SIGSTOP e SIGCONT?
(Per chi se lo chiedesse)
I segnali SIGSTOP e SIGCONT
implementano
le
due
operazioni di controllo di
flusso software su terminale:
XOFF e XON.
Tali funzioni sono un retaggio
dei terminali fisici (DEC VT100).
49
Il comando pkill
(Introduce diversi criteri di identificazione dei processi)
/bin/kill seleziona i processi solamente in
base al PID o al nome.
Il
comando
esterno
/usr/bin/pkill
introduce diversi “filtri” di ricerca.
Appartenenza ad uno specifico utente o gruppo.
Scelta del processo più “recente” o più “anziano” (data
di creazione).
Uso di uno specifico terminale.
50
Alcune opzioni utili
(man pkill per tutti i dettagli)
pkill -x pattern: invio di TERM al processo
il cui nome coincide esattamente con pattern.
pkill -P ppid: invio di TERM al processo il
cui padre ha PID pari a ppid.
pkill -u andreoli: invio di TERM a tutti i
processi creati dall'utente andreoli.
51
Esercizi (2 min.)
8. Si esca dalla sessione grafica corrente usando il
comando pkill.
52
Reazioni non di default
(Le applicazioni usano gestori di segnale specifici)
Diverse applicazioni (anche di sistema)
impostano reazioni specifiche a segnali tramite
opportune funzioni.
In tali circostanze, l'invio del segnale ad una
applicazione non sortisce l'effetto normalmente
previsto.
La pagina di manuale dell'applicazione
documenta il comportamento corretto.
→ Morale: leggete sempre la pagina di manuale! 54
Un esempio
(L'applicazione bc reagisce a SIGINT stampando un messaggio ed uscendo)
L'applicazione bc è un interprete matematico a
precisione arbitraria. Lo si esegua con il comando:
bc
Si dia una operazione:
2 + 3
Si interrompa l'applicazione con CTRL-C. Come
si può vedere, bc esce dopo aver stampato un
messaggio.
In Debian, addirittura bc non esce!
55
→ Versioni di bc diverse, comportamento diverso...
Un altro esempio
(L'applicazione dd reagisce a SIGUSR1 stampando un indicatore di progresso)
L'applicazione dd permette di copiare file in
modo efficiente. Ad esempio, per generare zeri ed
ignorarli:
dd if=/dev/zero of=/dev/null
Si invii il segnale SIGUSR1 all l'applicazione.
pkill -SIGUSR1 $(pgrep -n dd)
Come si può vedere, dd stampa un indicatore di
progresso.
56
Esercizi (2 min.)
9. Si ripeta il comando di invio del segnale ogni
secondo.
Non manualmente, bensì tramite comandi di
shell!
57
Come gestire i segnali in C?
(It's a bit tricky...)
59
Invio di segnali
(Chiamata di sistema kill())
La chiamata di sistema kill() consente di
inviare un segnale ad un processo.
man 2 kill per sapere tutti i dettagli.
Parametri in ingresso.
Il PID del processo a cui inviare il segnale.
Il numero identificativo del segnale da inviare.
Valore di ritorno.
In caso di successo: 0.
In caso di errore: -1 (errno contiene il codice esatto).
Esempio d'uso: sorgente kill.c contenuto
60
nell'archivio 14-esempi.tar.bz2.
Un esempio concreto
(Il sorgente kill.c invia SIGTERM ad un PID letto da linea di comando)
Il sorgente kill.c contenuto nell'archivio 14esempi.tar.bz2 illustra l'invio di un segnale
specifico (SIGTERM) ad un PID passato come
argomento.
Si usa kill() con i seguenti argomenti:
pid: l'identificatore del segnale (interruzione).
SIGTERM: la reazione specifica (ignorare).
61
Esercizi (5 min.)
10. La libreria del C mette a disposizione la
funzione raise(), che invia un segnale allo
stesso processo invocante.
Si individui il prototipo di raise() leggendo la
pagina di manuale relativa.
Si scriva una implementazione di raise() per
mezzo della chiamata di sistema kill().
62
Impostazione della reazione
(Chiamata di sistema signal())
La chiamata di sistema signal() consente di
impostare una funzione di gestione per un
determinato segnale.
man 2 signal per sapere tutti i dettagli.
Parametri in ingresso.
Il numero identificativo del segnale.
Un puntatore alla funzione di gestione.
Valore di ritorno.
In caso di successo: un puntatore alla stessa funzione
di gestione.
64
In caso di errore: il valore SIG_ERR.
Caratteristiche del gestore
(È una funzione particolare)
Il gestore di segnale è una funzione che:
riceve in ingresso un intero.
non ritorna alcun valore in uscita.
Il tipo di dato opaco che rappresenta tale
funzione è sighandler_t.
typedef void (*sighandler_t) (int)
Il numero intero passato alla funzione di gestione
identifica il segnale catturato. La stessa funzione,
infatti, può essere impostata per gestire più
65
segnali.
Un esempio concreto
(Il sorgente ignore_signal.c imposta una reazione IGNORE per SIGINT)
Il sorgente ignore_signal.c nell'archivio
14-esempi.tar.bz2 illustra come ignorare
un segnale (nello specifico, SIGINT).
Si usa signal() con i seguenti parametri:
SIGINT: l'identificatore del segnale (interruzione).
SIG_IGN: la funzione specifica di reazione (ignorare).
66
Esercizi (2 min.)
11. Si provi a terminare il programma
ignore_signal inviando SIGINT in tutti i
modi possibili. Ci si riesce?
67
Un altro esempio concreto
(Il sorgente handle_signal.c imposta una funzione di reazione a SIGINT)
Il sorgente handle_signal.c nell'archivio
14-esempi.tar.bz2 illustra come impostare
una funzione specifica in reazione ad un segnale
(nello specifico, SIGINT).
Si usa signal() con i seguenti parametri:
SIGINT: l'identificatore del segnale (interruzione).
il puntatore alla funzione di gestione (che deve
rispettare il prototipo di tipo sighandler_t:
un int in ingresso, void in uscita).
69
Esercizi (2 min.)
12. Si provi a terminare il programma
handle_signal inviando SIGINT in tutti i
modi possibili. Ci si riesce?
70
SCAMBIO MESSAGGI: PIPE
72
Composizione di comandi
(Uno dei punti forti di UNIX)
I SO di tipo UNIX permettono di costruire
comandi complessi a partire da comandi più
semplici. La strategia usata è quella della catena
di assemblaggio.
Input
Comando
Comando
Ciascun comando:
...
Comando
Output
è specializzato in un compito ben definito.
riceve input dal comando precedente (o dall'utente).
produce output e lo invia al comando successivo (o al73
terminale).
STDIN, STDOUT, STDERR
(Tre canali di comunicazione a disposizione di ogni processo)
Ciascun processo ha a disposizione tre canali per
la comunicazione, ciascuno associato ad un
descrittore di file.
STDIN: canale di ingresso, usato per leggere l'input.
STDOUT: canale di uscita, usato per scrivere l'output.
STDERR: canale di errore, usato per scrivere messaggi
di errore.
I canali puntano di default al terminale.
STDIN
(fd 0)
Processo
STDOUT
(fd 1)
STDERR
(fd 2)
74
Pipe
(Un processo scrittore invia dati ad un processo lettore)
La pipe (tubazione) è un meccanismo di comunicazione
unidirezionale (half-duplex) e sequenziale fra un
processo scrittore e un processo lettore.
STDOUT scrittore → STDIN lettore.
Comunicazione stream: lo scrittore ed il lettore possono
scrivere e leggere, indipendentemente, messaggi di
lunghezza arbitraria.
→ Blocco in caso di scrittura su pipe “piena”.
→ Blocco in caso di lettura da pipe “vuota”.
Processo
scrittore
write()
Pipe
Processo
lettore
read()
75
Pipe in BASH
(Il metacarattere |)
In BASH, la funzionalità di pipe è introdotta dal
metacarattere |. Ad esempio:
ls | less
“Unisce” l'output di ls
con l'input di less.
Produce un elenco di file
e lo stampa in output.
Pagina l'elenco dei
file in ingresso.
76
Pipeline
(Il generico comando impartito alla BASH)
Un generico comando in BASH può essere visto
come una sequenza di comandi in pipe. Tale
comando prende il nome di pipeline.
Ad esempio:
ls -t | head -n 10 | less
77
Esercizi (5 min.)
13. Si spieghi il funzionamento della pipeline:
ls -t | head -n 10 | less
78
Esercizi (20 min.)
14. Si costruisca una pipeline che mostra in
maniera ordinata (dal più frequente al meno
frequente) i comandi della history di shell ed il
relativo numero di occorrenze. L'output deve
essere simile a quello del file history.txt
nell'archivio 14-esempi.tar.bz2.
Si faccia uso dei seguenti comandi (elencati in
ordine sparso): sort, less, column, history,
uniq, awk.
80
Una doverosa avvertenza
(La pipe fa passare solo STDOUT, non STDERR!)
La pipe fa passare al comando successivo solo lo
STDOUT del comando attuale; lo STDERR NON
viene passato.
Provare per credere:
ls file_inesistente | less -Mr
Premete CTRL-L per rinfrescare l'output del
terminale.
Sparisce il messaggio di errore di ls!
88
Come risolvere questo problema?
(Si fonde STDERR in STDOUT)
Nel comando precedente si può fondere STDERR
in STDOUT con l'operatore di redirezione >&.
ls file_inesistente 2>&1 | less -Mr
STDERR
STDOUT
Scrive sullo
stesso canale
di
Si immetta il comando e si noti la presenza del
messaggio di errore di ls.
89
Esercizi (5 min.)
15. Si individui l'errore nella seguente pipeline e
lo si corregga: strace ls | less -Mr.
90
Filtri UNIX
(Accettano input da STDIN, stampano output stdout)
Un comando UNIX di sistema funziona in due
modalità distinte.
Nella modalità standard, accetta come opzioni
e/o argomenti i nomi dei file su cui opera.
less -Mr file.txt
Nella modalità filtro UNIX non legge i nomi dei
file da argomento, bensì il relativo contenuto da
STDIN (e/o produce output su STDOUT).
ls | less -Mr
Notate l'assenza di argomenti
nel comando less.
92
Un esempio concreto
(Il comando grep)
Il comando UNIX grep effettua pattern matching
su dati.
Nella modalità standard, grep opera su file o
directory.
grep -nrHiE 'pattern' directory
Nella modalità filtro UNIX, grep effettua il pattern
matching sui dati letti da STDIN.
ls -a | grep .bash
93
Esercizi (5 min.)
16. Si spieghi il funzionamento del comando
seguente: grep ciao.
94
SCAMBIO MESSAGGI: NAMED PIPE
96
Named pipe
(Che cosa succede se scrittori e lettori non chiudono i descrittori non usati?)
La condivisione della pipe fra più lettori e scrittori
è scomoda.
Una volta dichiarata la propria natura (lettore o
scrittore) non si può tornare indietro.
La pipe può essere condivisa solo fra padre e figli → i
processi partecipanti devono essere noti in anticipo.
Per superare questi inconvenienti, lo standard
POSIX definisce un meccanismo simile: le named
pipe (dette anche FIFO).
97
Funzionamento
(Concettualmente analogo ad una pipe)
Una named pipe è quasi identica ad una pipe.
Comunicazione half-duplex bloccante fra processi
qualsiasi.
I dati in transito sono conservati in buffer dati del
kernel.
A differenza delle pipe, il file descriptor delle
named pipe punta ad un file speciale su disco.
Tecnicamente, il file speciale ha lunghezza zero ed ha
una propria struttura di metadati (inode).
Il file speciale è riconoscibile dal marcatore p
98
nell'output del comando ls -l.
Il comando mkfifo
(Crea named pipe)
Come si crea una named pipe? Si usa il comando
esterno mkfifo.
mkfifo nome_pipe.
Si osservi più da vicino il file appena creato.
ls -l nome_pipe
Il tipo di file è identificato, in effetti, come “p”.
La named pipe è, a tutti gli effetti, un file speciale
che non ha alcun contenuto su disco.
99
Uno streaming server dei poveri
(Con semplici strumenti da linea di comando)
Si provi a scrivere uno streaming server “dei
poveri” usando esclusivamente strumenti da linea
di comando.
Cosa serve?
Uno strumento per scaricare brani da Internet.
Uno strumento per riprodurre brani.
Una named pipe che riceve il contenuto del brano e
ne permette la lettura al riproduttore musicale.
100
I componenti dello streaming server
(wget + mkfifo + mplayer)
Client HTTP (per il download di brani):
wget (pacchetto software wget).
Strumento di comunicazione:
named pipe creata con il comando mkfifo.
Riproduttore multimediale “streaming”:
mplayer (pacchetto software mplayer).
101
“Composizione” del server
(Si crea una named pipe e ci si scarica il file multimediale tramite wget)
Si crei una named pipe, buffer intermedio fra
HTTP client e riproduttore multimediale.
mkfifo buffer
Si scarichi il filmato (o il brano audio) che si
intende ascoltare, riversandolo nella named pipe.
wget -O buffer
http://weblab.ing.unimo.it/people/andreolini/file-audio.ogg
102
Perché wget è bloccato?
(Si crea una named pipe e ci si scarica il file multimediale tramite wget)
Si tracci l'esecuzione di wget:
strace -p $(pgrep wget)
Si noti come wget non abbia ancora un
descrittore di file associato alla named pipe.
Il processo wget è bloccato nella open() del file
speciale buffer.
Finché non arriva un lettore, il kernel non fa
ripartire wget.
103
Perché wget è bloccato?
(Si crea una named pipe e ci si scarica il file multimediale tramite wget)
Si esegua il riproduttore multimediale.
Si usi l'opzione -cache 128, che precarica
128KB di dati prima di avviare la riproduzione.
Altrimenti mplayer potrebbe avere serie difficoltà a
riconoscere il tipo di filmato.
mplayer -cache 128 buffer
104
Esercizi (5 min.)
17. Si implementi un meccanismo per far vedere
l'output della propria sessione di terminale in
diretta su un altro terminale. È possibile usare il
comando script per registrare la sessione di
un terminale.
105