SC per Inter Process Communication. Pipe senza nome e con nome (FIFO)

Documenti analoghi
Comunicazione tra processi: pipe Le pipe sono un meccanismo UNIX di Inter Process Communication (IPC)

Sistemi Operativi Teledidattico

La Comunicazione tra Processi in Unix

Igino Corona

Chiamate di sistema per la Inter Process Communication (IPC) in POSIX. E.Mumolo, DEEI

Chiamate di sistema. Pipe Flussi di I/O

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Crea un nuovo processo. Al processo padre ritorna il PID del figlio. Al processo figlio ritorna 0

Sistemi Operativi. Marzo-Giugno 2011 matricole congrue 0 mod 3. Controllo dei processi - I

Lab. di Sistemi Operativi - Esercitazione n 9- -Thread-

Il processo figlio : utilizza lo stesso codice che sta eseguendo il padre ;

Laboratorio di Sistemi Operativi

I/O su Socket TCP: read()

System call per la gestione di processi

Laboratorio di Sistemi Operativi Marzo-Giugno 2008 matricole congrue 0 mod 3

Laboratorio di Sistemi Operativi

File I/O. M. R. Guarracino: File I/O 1

&& (nessun altro processo ha il file aperto) && (il fd e chiuso) Cancella il file;

Program m azione di Sistem a 5

SmallShell Piccolo processore comandi

Processi. Comunicazione tra processi Stefano Quer Dipartimento di Automatica e Informatica Politecnico di Torino

Digressione: man 2...

Directory. Le directory unix sono file.

Sistemi Operativi (M. Cesati)

Gestione dei processi

uid_t getuid(void); //real-user-id del chiamante getegid(void); //effective-user-id del chiamante gid_t getgid(void); //real-group-id del chiamante

La sincronizzazione è legata alla implementazione delle pipe: int pipe(int fd[2]);

Per operare su un file abbiamo bisogno di aprirlo, scriverlo, leggerlo, chiuderlo:

Digressione: man (2)...

Università di Roma Tor Vergata Corso di Laurea triennale in Informatica Sistemi operativi e reti A.A Pietro Frasca.

Esercitazione [8] Pipe e FIFO

PIPE. M. Guarracino - PIPE 1

Capitolo 5 -- Stevens

Sistemi Operativi Anno Accademico 2011/2012. Segnali: Interrupt software per la gestione di eventi asincroni

File binari e file di testo

I files in C. A cura del prof. Ghezzi

Laboratorio di Sistemi Operativi

System calls. permettono ai programmi utente di richiedere servizi al Sistema Operativo. servizi come scrittura di file, stampa su video, ecc.

Processi UNIX. I Processi nel SO UNIX. Gerarchie di processi UNIX. Modello di processo in UNIX

Corso di Sistemi Operativi Programmazione di Sistema e Concorrente

Argomenti della lezione. Messaggi. Formato di un messaggio. Corso di Sistemi Operativi Programmazione di Sistema e Concorrente

Processi Concetti di base. Esecuzione parallela e sequenziale Il concetto di processo Gestione dei processi

Chiamate di sistema per la Gestione dei processi in POSIX. E.Mumolo, DEEI

Laboratorio di Sistemi Operativi Marzo-Giugno 2008 matricole congrue 0 mod 3

GESTIONE DEI FILE IN C. Docente: Giorgio Giacinto AA 2008/2009

Il comando make. Per produrre un eseguibile da un programma C sono necessari tre passi compiuti dai seguenti moduli:

Introduzione al Linguaggio C

Interprocess communication: Pipe

Gestione dei file. Stefano Ferrari. Università degli Studi di Milano Programmazione. anno accademico

il tipo di parallelismo dipende dal grado di cooperazione

Corso di Programmazione Concorrente Processi. Valter Crescenzi

Pipe con nome. [Pagina intenzionalmente vuota] 1: Pipe con nome ( ) slide 1:1/22 (p.1)

Pipes e named pipes: 1. Nozioni preliminari 2. Pipes e named pipes (FIFO) in sistemi UNIX 3. Pipes e named pipes sistemi Windows

Processi in UNIX. Spazio di sistema (residente) Tabella dei. file APERTI OPEN FILE. Tabella dei codici

Esercizio sulla gestione di file in Unix

Sistemi operativi Modulo II I semafori 2 Select

LABORATORIO di Reti di Calcolatori

Gestione di files Motivazioni

Il File-System. I file in ambiente Linux Stefano Quer Dipartimento di Automatica e Informatica Politecnico di Torino

Programmazione di sistema in Linux: System Call per le IPC (InterProcessCommunication) E. Mumolo

Esercitazione di Lab. di Sistemi Operativi 1 a.a. 2011/2012

I SISTEMI OPERATIVI (1)

8. IL FILE SYSTEM. 1. I servizi per la gestione dei file

ACSO Programmazione di Sistema e Concorrente

I file Laboratorio di Linguaggi di Programmazione a.a. 2001/2002

Esame Laboratorio di Sistemi Operativi Cognome Nome Mat.

I Processi nel Sistema Operativo Unix. Gerarchie di processi Unix. Stati di un processo Unix. Stati di un processo Unix.

Il linguaggio C. Puntatori e dintorni

I Processi nel Sistema Operativo Unix

Corso di Sistemi Operativi A.A CHIAMATE DI SISTEMA PER IL CONTROLLO DEI PROCESSI. Fabio Buttussi

Processi - II. Franco Maria Nardini

Le strutture. Una struttura C è una collezione di variabili di uno o più tipi, raggruppate sotto un nome comune.

Controllo dei Processi 1

Sistemi Operativi. Sistemi I/O SISTEMI DI INPUT/OUTPUT. Hardware di I/O. Interfaccia di I/O per le applicazioni. Sottosistema per l I/O del kernel

Corso di Laboratorio di Sistemi Operativi

Controllo dei Processi. M. R. Guarracino - Primitive di Controllo dei Processi

Sistemi Operativi SISTEMI DI INPUT/OUTPUT. D. Talia - UNICAL. Sistemi Operativi 10.1

Esame Laboratorio di Sistemi Operativi Cognome Nome Mat.

I Processi nel SO UNIX

Corso di Sistemi Operativi Esercitazioni

Laboratorio di Sistemi Operativi primavera 2009

LIBRERIE STANDARD in C. LIBRERIE STANDARD in C

Esercitazione [5] Input/Output su Socket

Files, File I/O, File Sharing. Franco Maria Nardini

Corso di laurea in ingegneria informatica Esame di sistemi operativi 21 gennaio 2009 SOLUZIONI

Programmazione di sistema in Linux: gestione dei file. E. Mumolo

File e puntatori a file

Processore Danilo Dessì. Architettura degli Elaboratori.

Signalling (IPC) Signalling (segnalazione)

CORSO DI SISTEMI OPERATIVI A - ESERCITAZIONE 3. 1 strace : visualizzazione delle system call invocate da un processo

System Calls per la Gestione dei Processi

5. I device driver. Device driver - gestori delle periferiche. Struttura interna del sistema operativo Linux. Tipi di periferiche. Tipi di periferiche

Sincronizzazione e comunicazione tra processi in Unix. usati per trasferire ad un processo l indicazione che un determinato evento si è verificato.

Le librerie standard. ! La libreria standard del C è in realtà un insieme di librerie

Elementi di Architettura e Sistemi Operativi

ESERCIZI DI PROGRAMMAZIONE C IN AMBIENTE UNIX

C: panoramica. Violetta Lonati

Esercizi di Verifica Aprile 2005 Università disalerno

Comandi. Sistema Operativo

Introduzione. P4 termina prima di P3, P2 e P3 prima di P1 P1 P2 P3 P4 P1 P1 P2 P3 P4. Padre. P1,..., P4 sono processi. Figlio

Transcript:

SC per Inter Process Communication Pipe senza nome e con nome (FIFO) 1

Pipe Pipe : file speciali utilizzati per connettere due processi con un canale di comunicazione Possono essere utilizzati in modo unidirezionale da shell es: bash:~$ who sort more who pipe sort pipe more 2

Pipe (2) In generale : le pipe possono essere bidirezionali, connettere più processi fra loro etc queste interazioni più complesse non sono direttamente disponibili da shell ma devono essere programmate esplicitamente usando le SC relative alle pipe Le pipe sono state uno dei primi meccanismi di IPC in Unix e sono disponibili su tutti i sistemi 3

Pipe con nome e senza nome pipe senza nome (unnamed) file senza un nome visibile, che viene utilizzato per comunicazioni fra processi che condividono puntatori alla tabella dei file aperti (es. padre figlio, nonno nipote etc) pipe con nome (named o FIFO) file speciale (p) con nome visibile a tutti gli altri processi sulla stessa macchina 4

Creazione di pipe senza nome: pipe() #include <unistd.h> int pipe( int pfd[2] /*descrittori di file*/ ); /* (0) success (-1) error, sets errno */ crea una pipe, rappresentata da due descrittori di file: pfd[1] con cui si può scrivere dati sulla pipe e pfd[0] con cui si può leggere dalla pipe 5

Pipe senza nome: esempio int main (void){ int pfd[2]; /* descrittori */ /* creazione pipe */ if ( pipe(pfd) == -1 ) {/* errore */} /* adesso pfd[1] puo essere usato per la scrittura e pfd[0] per la lettura */ } 6

Pipe senza nome Una volta creata la pipe è possibile leggere e scrivere dati con read() e write() la capacità minima della pipe è definita dalla variabile Posix _POSIX_PIPE_BUF ma può essere maggiore vediamo come fare a vederne il valore le write() sono garantite essere atomiche solo se vengono scritti meno byte della capacità effettiva della pipe Alla creazione, il flag O_NONBLOCK non è settato, quindi sia lettura che scrittura possono bloccarsi. 7

Limiti di configurazione: *pathconf() #include <unistd.h> long fpathconf( int fd, /*descrittore di file*/ int name /*opzione di configurazione*/ ); long pathconf( char * path, int name ); /*path file*/ /*opzione di configurazione*/ /* (limite o -1) on success (-1) on error, sets errno */ 8

Limiti : *pathconf() (2) Come opera fpathconf(pfd,name) : forniscono il limite corrente per l opzione nome attenzione: può ritornare -1 sia se non c è limite all opzione, sia se si è verificato un errore al solito possiamo discriminare i due casi settando errno a 0 appena prima della chiamata vediamo come leggere la capacità minima Posix e stabilire la capacità reale! 9

Pipe senza nome: esempio int main (void){ int pfd[2]; long int v; /* creazione pipe */ } if ( pipe(pfd) == -1 ) {/* errore */} printf("posix = %ld e,_posix_pipe_buf); errno = 0; if ((v = fpathconf(pfd[0],_pc_pipe_buf))==-1){ else if (errno!= 0) {/* errore */} else printf( reale = illimitato\n ); } printf( reale = %ld\n,v); 10

Pipe senza nome : esempio (2) Compiliamo: bash:~$ gcc main.c -o pipetest Eseguiamo: bash:~$./pipetest POSIX = 512 e reale = 4096 bash:~$ 11

Uso di una pipe senza nome Si usano le SC che abbiamo già visto per gli altri file write, read, close hanno però una semantica diversa da quella sui file regular, la descriveremo in dettaglio stat permette di capire se un file è una pipe lseek non ha senso per le pipe più altre che non abbiamo ancora visto dup, dup2: le descriveremo dopo, sono fondamentali per implementare pipelining e ridirezione di shell 12

Uso di una pipe: write k = write(pfd,buf,n) i dati sono scritti nella pipe in ordine di arrivo se n è minore della capienza la write è atomica: non ci sono scritture parziali, la write si blocca finche non sono stati letti abbastanza dati dalla pipe per far posto ai dati nuovi (comportamento normale O_NONBLOCK non settato -- si può settare con fcntl) n è maggiore della capienza la write non è atomica, ci possono essere scritture parziali se O_NONBLOCK è settato la write scrive subito tutto oppure ritorna -1 (errno settato a EAGAIN) 13

Uso di una pipe: write (2) k = write(pfd,buf,n) se non esiste nessun lettore sulla pipe pfd (tutti i descrittori di lettura sono stati chiusi) una write su pfd provoca l invio di un segnale SIGPIPE al processo MOLTO PERICOLOSO! : la gestione di default di SIGPIPE è la terminazione del processo che lo riceve è necessario ridefinire la gestione ignorando SIGPIPE (vedremo come è possibile quando parliamo di segnali) se SIGPIPE è stato ignorato, una scrittura su una pipe senza lettori ritorna -1 errore EPIPE (equivale a EOF) 14

Uso di una pipe: read k=read(pfd,buf,n) i dati sono letti dalla pipe in ordine di arrivo i dati letti non possono essere rimessi nella pipe comportamento normale O_NONBLOCK non settato se la pipe è vuota e i descrittori di scrittura non sono ancora stati chiusi la read si blocca in attesa se i descrittori di scrittura sono tutti chiusi ritorna subito 0 (end_of_file) altrimenti legge al più n byte, se al momento dell invocazione la pipe contiene meno di n byte legge tutti i byte presenti e ritorna il numero dei byte letti k 15

Uso di una pipe: read (2) k=read(pfd,buf,n) se O_NONBLOCK è settato se la pipe è vuota la read ritorna subito -1 con errore settato a EAGAIN 16

Uso di una pipe: close k=close(pfd) libera il descrittore di file (come file regolari) quando l ultimo descrittore di scrittura è chiuso genera l end_of_file per i lettori facendo ritornare 0 ad eventuali read in attesa se viene effettuata una write su una pipe in cui tutti i descrittori di lettura sono stati chiusi il processo riceve un segnale fatale (SIGPIPE) 17

Usi di una pipe senza nome Solo per processi discendenti si passano i file descriptor attraverso la condivisione dei puntatori alla tabella dei file aperti Tipicamente per comunicazione unidirezionale uno scrittore ed un lettore più scrittori ed un lettore negli altri usi bisogna fare molta attenzione a possibili situazioni di deadlock Non esiste il concetto di messaggio byte non strutturati, i processi comunicanti devono stabilire il protocollo di scambio dati 18

Uso di una pipe senza nome (2) Sequenza tipica di utilizzo di una pipe senza nome: il padre crea la pipe il padre si duplica con una fork() i file descriptor del padre sono copiati nella tabella dei file descriptor del figlio il processo scrittore (padre o figlio) chiude pfd[0] mentre il processo lettore chiude pfd[1] i processi comunicano con read/write quando la comunicazione è finita ognuno chiude la propria estremità 19

Pipe senza nome: esempio /* msg lunghezza fissa N, manca gest. errori */ int main (void){ int pfd[2], pid, l; char msg[n]; if ( pipe(pfd) == -1 ) {/* errore */} if ( (pid=fork())== -1 ) {/* errore */} if ( pid ) { /* siamo nel padre */ close(pfd[1]); /* chiude scrittura */ l=read(pfd[0],msg,n); /* controlla esito read elabora il msg */ close(pfd[0]); /* chiude lettura */ } 20

Pipe senza nome: esempio (2) int main (void){ int pfd[2], pid, l; char msg[n]; else { /* siamo nel figlio */ close(pfd[0]); /* chiude lettura */ /* prepara il msg */ l = write(pfd[1],msg,n); /* controlla esito */ close(pfd[1]); /* chiude scrittura */ } return 0; } 21

Es: msg di lunghezza variabile Possibile protocollo: ogni messaggio logico è implementato da due messaggi fisici sul canale il primo messaggio (di lunghezza nota), specifica la lunghezza lung il secondo messaggio (di lunghezza lung) codifica il messaggio vero e proprio vediamo un frammento di possibile implementazione 22

Msg di lunghezza variabile (2) } else { /* siamo nel figlio */ int lung; /* per la lunghezza*/ close(pfd[0]); /* chiude lettura */ snprintf(msg,n, Da %d: Hi!!\n,getpid()); lung = strlen(msg) + 1; /* primo messaggio */ k = write(pfd[1], &lung, sizeof(int)); /* esito secondo messaggio */ k = write(pfd[1],msg,lung); /* esito */ close(pfd[1]); } /* NB: non funziona con più di 1 scrittore*/ 23

Msg di lunghezza variabile (3) /* manca totalmente gest errori ed EOF read */ if ( pid ) { /* siamo nel padre */ int l,lung; char* pmsg; close(pfd[1]); l=read(pfd[0],&lung,sizeof(int)); pmsg = malloc(lung); l=read(pfd[0],&pmsg,lung); printf( %s,pmsg); free(pmsg); close(pfd[0]); } /* NB: non funziona con più di 1 scrittore*/ 24

Pipelining e ridirezione più comandi possono essere combinati assieme dalla shell usando il pipelining il pipelining viene implementato attraverso le pipe la connessione fra stdout (1) dello stadio I e stdin (0) dello stadio I+1 viene implementata usando le pipe e sfruttando due chiamate di sistema per la duplicazione dei descrittori: dup e dup2 le stesse SC permettono di implementare anche la ridirezione 25

Duplicazione di fd: dup, dup2() #include <unistd.h> int dup( int fd /*descr di file da duplicare*/ ); /* (fd1) success (-1) error, sets errno */ duplica il descrittore fd e ritorna la posizione (fd1) della tabella dei descrittori in cui ha scritto la copia, fd1 è la prima posizione libera nella tabella dei descrittori 26

Situazione tabella descrittori Prima di invocare la dup(3) 0 1 2 3 Pos.Corrente 0 write/read I-nodek I-node tty Tabella dei descrittori di file (user area di P) Tabella dei file aperti Tabella degli i-node attivi 27

Situazione tabella descrittori (2) Dopo la invocazione di dup(3) terminata con successo da parte del processo P. Il valore ritornato è 4 0 1 2 3 4 Pos.Corrente 0 write/read I-nodek I-node tty Tabella dei descrittori di file (user area di P) Tabella dei file aperti Tabella degli i-node attivi 28

Duplicazione di fd: dup, dup2 (2) #include <unistd.h> int dup2( int fd, /*descr di file da duplicare*/ int fd2, /*fd da usare per la copia*/ ); /* (fd2) success (-1) error, sets errno */ duplica fd nella posizione specificata da fd2 se fd2 è in uso viene chiuso prima della copia la dup2 è atomica, se qualcosa va male fd2 non viene chuso se fd=fd2 la dup2 non fa niente 29

Situazione tabella descrittori Prima di invocare la dup2(3,1) 0 1 2 3 Pos.Corrente 0 write/read I-nodek I-node tty Tabella dei descrittori di file (user area di P) Tabella dei file aperti Tabella degli i-node attivi 30

Situazione tabella descrittori (2) Dopo la invocazione di dup2(3,1) terminata con successo da parte del processo P. Il valore ritornato è 1 0 1 2 3 Pos.Corrente 0 write/read I-nodek I-node tty Tabella dei descrittori di file (user area di P) Tabella dei file aperti Tabella degli i-node attivi 31

Es: redirezione con dup() e dup2() Es. ridirigere lo standard output su un file pippo int fd;... fd=open( pippo,o_wronly O_TRUNC O_CREAT,0666); /* duplica fd su stdout*/ if ( dup2(fd,1)== -1) {/* errore */ } else { close(fd); /* fd non serve piu */ printf( Questo viene scritto in pippo! ); }... 32

Ridirezione nella shell... Es. bash:$ ls -l > pippo Il processo shell si duplica con una fork()e si mette in attesa della terminazione del figlio Il figlio apre in scrittura il file pippo (creandolo o troncandolo) Il figlio duplica il descrittore di pippo con la dup2 sullo stdout (fd 1) e chiude il descrittore originario Il figlio invoca una exec di ls -l, la quale conserva i descrittori dei file, e quindi va a scrivere in pippo ogni volta che usa il file descriptor 1 33

Ridirezione nella shell (2) Es. (segue) bash:$ ls -l > pippo Quando il figlio termina il padre continua l esecuzione con i suoi descrittori invariati Con un meccanismo simile la shell implementa il pipelining, vediamo un esempio: 34

Es: pipelining con dup() e dup2() Es. una funzione che esegue who wc l void who_wc (void) { int pfd[2]; pid_t pid1,pid2; if (pipe(pfd)== -1) { /* creazione pipe */ } switch ( pid1=fork()) { case -1: {/* errore */ } case 0 : /* figlio1: eseguirà who */ if ( dup2(pfd[1],1)== -1) {/* errore */ } else { close(pfd[0]); close(pfd[1]); execlp( who, who, (char*) NULL); } }/* fine creazione figlio who */ 35

Es: pipelining con dup() e dup2() (2) /* creazione figlio2*/ switch ( pid2=fork()) { case -1: {/* errore */ } case 0 : /* figlio2: eseguira wc l */ if ( dup2(pfd[0],0)== -1) {/* errore */ } else { close(pfd[0]); close(pfd[1]); execlp( wc, wc, -l, (char*) NULL); }/* ancora il padre*/ close(pfd[0]); close(pfd[1]); waitpid(pid1,null,0); waitpid(pid2,null,0);} 36

Pipe con nome o FIFO #include <sys/types.h> #include <sys/stat.h> int mkfifo( const char * path, /*path fifo*/ mode_t perms, /*permission*/ ); /* (0) success (-1) error, sets errno */ crea una pipe con nome path con diritti perms, interpretati esattamente come in open (usa umask) il nome è visibile ai processi sulla stessa macchina e quindi anche processi scorrelati possono aprirla in lettura e scrittura e comunicare 37

Creazione di pipe con nome /* frammento che crea un nuovo pipe con nome umask 022*/ /* non fallisce se la pipe c è gia */ if ((mkfifo( serverreq,0664) == -1) && errno!=eexist) {/* gest errore*/} /* diritti di scrittura per il gruppo */ if (chmod( serverreq,0664) == -1) {/* gestione errore*/} /* uso pipe */ 38

Uso di una pipe con nome Prima di iniziare a scrivere/leggere la pipe deve essere aperta contemporaneamente da un lettore e da uno scrittore: Apertura da parte di un processo scrittore : usa le open() se nessun lettore ha ancora invocato la open() si blocca in attesa del primo lettore usando le opzioni O_NONBLOCK, O_NDELAY se non ci sono lettori la open termina subito con fallimento 39

Uso di una pipe con nome (2) Apertura da parte di un processo lettore : usa le open() se nessun scrittore ha ancora invocato la open() si blocca in attesa dello scrittore usando le opzioni O_NONBLOCK, O_NDELAY se non ci sono scrittori la open termina subito con successo 40

Uso di una pipe con nome (3) Tipico uso : più client e un server il server crea la pipe e la apre in lettura e scrittura perché non solo in lettura? Perché altrimenti alla chiusura dell ultimo processo client scrittore il server legge un end_of_file! Il server logicamente deve rimanere sempre attivo, e mantenere aperto un descrittore di scrittura anche nel server rende la read sempre bloccante anche se non ci sono client connessi i client aprono in scrittura la stessa pipe le risposte del server in genere sono fornite su pipe private dei client (una per ogni client) per evitare di essere terminato da una write il server deve ignorare SIGPIPE 41

Frammento di server /* creazione pipe server */ if ((mkfifo( serverreq,0664) == -1) && errno!=eexist) {/* gest errore*/} if (chmod( serverreq,0664) == -1) {/* gest errore*/} /* apertura in lettura e scrittura */ } if (pfd=open( serverreq,o_rdwr) == -1) {/* gest errore*/ } /* uso pipe: la read è bloccante anche senza client*/ while (true) { if ( (l=read(pfd,buf,n)) == -1) 42