59
© 2002 - Domenico Barretta © 2002 - Domenico Barretta Politecnico di Politecnico di Milano Milano Processi concorrenti in Unix Processi concorrenti in Unix Docente Docente Domenico Barretta Domenico Barretta Politecnico di Milano Politecnico di Milano [email protected] [email protected]

Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano [email protected]

Embed Size (px)

Citation preview

Page 1: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

© 2002 - Domenico Barretta© 2002 - Domenico Barretta

Politecnico di MilanoPolitecnico di Milano

Processi concorrenti in UnixProcessi concorrenti in Unix

DocenteDocente

Domenico BarrettaDomenico Barretta

Politecnico di MilanoPolitecnico di [email protected]@elet.polimi.it

Page 2: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 22 - -

ContenutoContenuto

Funzioni per la comunicazione fra processiMeccanismi utilizzati:

Scambio di messaggiPipesMemoria condivisa e semaforiSocket

Esempi di codice

Page 3: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 33 - -

Scambio di messaggiScambio di messaggi

Viene gestito tramite una coda a cui più processi possono accedereI processi che intendono utilizzare lo scambio di messaggi devono utilizzare la stessa codaCiascun processo può utilizzare una coda sia per inviare messaggi che per riceverneA ciascun messaggio è possibile associare un tipo di messaggioUtilizzabile per indirizzare un messaggio ad uno dei processi che accedono in lettura ad una coda condivisa

Page 4: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 44 - -

Scambio di messaggiScambio di messaggi

Le librerie da importare per l’utilizzo dello scambio di messaggi sono

sys/ipc.hsys/msg.h

Per poter utilizzare i messaggi è prima necessario inizializzare una coda con la funzione msgget()Una volta inizializzata la coda (da parte di tutti i processi che devono comunicare) è possibile:

Inviare un messaggio con la funzione msgsnd()Ricevere un messaggio con la funzione msgrcv()

Page 5: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 55 - -

msgget()msgget()

Sintassiint msgget(key_t key, int msgflg)

EffettoSe non è ancora stata creata una coda a partire dalla chiave specificata, viene creata la coda e ne viene restituito l’identificatoreAltrimenti viene restituito l’identificatore della coda creata in precedenza

Page 6: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 66 - -

msgget() - parametrimsgget() - parametri

Il primo parametro serve a fare in modo che tutti i processi che chiamano la msgget() con la stessa chiave (un valore numerico ottenibile con la funzione ftok()) facciano riferimento alla stessa coda; se viene specificato come IPC_PRIVATE la coda è utilizzabile solo dal processo che la creaIl secondo parametro è definito come l’or di seguenti parametri:

IPC_CREAT da specificare se la coda va creata qualora non esista giàIPC_EXCL da specificare insieme a IPC_CREAT se la funzione deve fallire qualora la coda esista giàI permessi di accesso (notazione ottale)

Page 7: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 77 - -

Struttura dei messaggiStruttura dei messaggi

I messaggi sono tipicamente strutturati come una struct costituita da due campi:

Un long che costituisce il tipo del messaggioUn array di caratteri che costituisce il contenuto del messaggio

Esempio (MSGSZ è la massima dimensione di un messaggio):typedef struct msgbuf {

long mtype;

char mtext[MSGSZ];

} message_buf

Page 8: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 88 - -

msgsnd()msgsnd()

Sintassiint msgsnd(int msqid, const void *msgp,

size_t msgsz, int msgflg);

EffettoInvia il messaggio alla coda specificata e restituisce il numero di byte spediti

ParametriL’identificatore della coda a cui inviare il messaggioUn puntatore al messaggioLa dimensione del messaggio0 o IPC_NOWAIT a seconda se il processo vada sospeso o meno in caso di coda piena

Page 9: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 99 - -

msgrcv()msgrcv()

Sintassiint msgsrv(int msqid, void *msgp,

size_t msgsz, long msgtyp, int msgflg);

EffettoRiceve il messaggio del tipo indicato e restituisce il numero di byte ricevuti

ParametriL’identificatore della codaUn puntatore all’area dove scrivere il messaggio ricevutoLa massima dimensione da ricevere

Page 10: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 1010 - -

msgrcv() - continuamsgrcv() - continua

Altri parametriIl tipo di parametro da ricevere

0 per ricevere il primo messaggio della codaUn numero positivo per ricevere il primo messaggio del tipo specificatoUn numero negativo per ricevere il primo messaggio con tipo maggiore del modulo del valore specificato

Un flag:IPC_NOWAIT se in assenza di messaggi si vuole che la funzione ritorni subitoMSG_NOERROR se si vogliono troncare messaggi più lunghi della dimensione specificataMSG_EXCEPT se si specifica il tipo di messaggio da non ricevere

Page 11: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 1111 - -

Messaggi – Esempio di codiceMessaggi – Esempio di codice

Si tratta di un semplice programma che:Crea un processo figlioInvia un messaggio al processo figlio

Il processo figlio riceve il messaggio e lo stampa a videoTratto dal sito http://www.cs.cf.ac.uk/Dave/C/CE.html

Page 12: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 1212 - -

Messaggi – Esempio di codiceMessaggi – Esempio di codice

#include <sys/types.h>#include <sys/ipc.h>#include <sys/msg.h>#include <stdio.h>#include <unistd.h>#include <string.h>

#define MSGSZ 128

/* * Declare the message structure. */

typedef struct msgbuf{

long mtype;char mtext[MSGSZ-sizeof(long)];

} message_buf;

main()

{

int temp;

int msqid;

int msgflg = IPC_CREAT | 0666;

key_t key;

message_buf sbuf;

message_buf rbuf;

size_t buf_length;

pid_t pid;

/*

* Get the message queue id for * the "name" 1234, which was

* created by the server.

*/

key = 1234;

Page 13: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 1313 - -

Messaggi – Esempio di codiceMessaggi – Esempio di codice

if ((pid=fork()) <0 ) { perror("Error in

fork");exit(1);

}

if (0 == pid) //figlio{

if ((msqid = msgget(key, 0666)) < 0)

{ perror("msgget"); exit(1); }

/** Receive an answer of message* type 1.

*/

temp=msgrcv(msqid, &rbuf, MSGSZ, 1, 0);

if (temp < 0)

{

perror("msgrcv");

exit(1);

}

rbuf.mtext[temp]=0;

/*

* Print the answer.

*/

printf("In ricezione ho avuto %s\n", rbuf.mtext);

} //Fine figlio

Page 14: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 1414 - -

Messaggi – Esempio di codiceMessaggi – Esempio di codice

else //padre {

(void) fprintf(stderr, "\nmsgget: Calling msgget(%#lx,%#o)\n",key, msgflg);

if ((msqid = msgget(key, msgflg )) < 0)

{ perror("msgget"); exit(1); } else (void)

fprintf(stderr,"msgget: msgget succeeded: msqid = %d\n", msqid);

/* * We'll send message

type 1 */ sbuf.mtype = 1; (void)

fprintf(stderr,"msgget: msgget succeeded: msqid = %d\n", msqid);

(void)

strcpy(sbuf.mtext, "Did you get this?");

(void)

fprintf(stderr,"msgget: msgget succeeded: msqid = %d\n", msqid);

Page 15: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 1515 - -

Messaggi – Esempio di codiceMessaggi – Esempio di codice

buf_length = strlen(sbuf.mtext) ;

/*

* Send a message.

*/

if (msgsnd(msqid, &sbuf, buf_length, IPC_NOWAIT) < 0)

{

printf ("%d, %d, %s, %d\n", msqid, sbuf.mtype, sbuf.mtext, buf_length);

perror("msgsnd");

exit(1);

}

else

printf("Message: \"%s\" Sent\n", sbuf.mtext);

wait();

}

exit(0);

}

Page 16: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 1616 - -

PipesPipes

Una pipe è una coda circolare gestita dal sistema operativoTipicamente esistono uno o più processi che scrivono sulla pipe e un processo che legge dalla pipeUna volta inizializzata una pipe, è possibile utilizzarla per scrivere e leggere bytesE’ un canale di comunicazione unidirezionale

Page 17: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 1717 - -

PipesPipes

Le librerie da importare sono:sys/types.hunistd.hstdio.h

Si definisce un vettore di due interi che corrispondono all’ingresso e all’uscita della codaSi inizializza la pipe tramite la funzione pipe()La scrittura avviene tramite la funzione write()La lettura avviene tramite la funzione read()La chiusura avviene tramite la funzione close()

Page 18: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 1818 - -

pipe()pipe()

Sintassiint pipe(int pipedes[2])

EffettoCrea una pipeI byte scritti in pipedes[1] possono essere letti da pipedes[0]Restituisce 0 in caso di successo, -1 altrimenti

ParametriUn vettore di 2 interi in cui memorizzare i descrittori della pipe

Page 19: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 1919 - -

read()read()

Sintassisize_t read(int fd, void *buf, size_t nbytes)

EffettoLegge dalla pipe e memorizza i dati letti in bufRestituisce il numero di bytes letti, oppure 0 se è stato raggiunto EOF oppure -1 in caso di errore

ParametriCome primo parametro si usa pipedes[0]Il secondo parametro è un puntatore all’area di memoria in cui scrivere quanto lettoIl numero di bytes che si intende leggere

Page 20: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 2020 - -

Altre funzioniAltre funzioni

size_t write(int fd, const void *buf, size_t nbytes)

Analoga alla readSi utilizza pipedes[1] come secondo parametro

int close(int fd)Se utilizzata con pipedes[0] chiude la lettura della pipeSe utilizzata con pipedes[1] chiude la scrittura della pipe

Page 21: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 2121 - -

Pipe - Esempio di codicePipe - Esempio di codice

#include <sys/types.h> #include <unistd.h> #include <stdio.h> #define MAX 25/* maximum number of letters

communicated */ int main (void) {

int fd[2];/* provide file descriptor pointer array for pipe */ /* within pipe: fd[0] will be input end fd[1] will be output end */

pid_t pid;

char line[MAX]; /* character array (string) for reading */

if (pipe (fd) < 0)

/* create pipe and check for an error */ {

perror(''pipe error''); exit (1);

}

if ((pid = fork()) < 0)/* apply fork and check for error */ {

perror (''error in fork''); exit (1);

}

Page 22: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 2222 - -

Pipe - Esempio di codicePipe - Esempio di codice

if (0 == pid)

{/* processing for child */ printf (''The child process

is active.``n'');

close (fd[1]);/* close output end,

leaving input open */ read(fd[0], line, MAX); printf (“The string

received is '%s'``n'', line); }

else {

/* processing for parent */ printf (''The parent

process is active.``n'');

close (fd[0]);/* close input end, leaving output open */ write (fd[1], ''Your parent

is calling'', 22);

/* print string and indicate byte length */

}wait() exit (0);

Page 23: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 2323 - -

Memoria condivisaMemoria condivisa

Ogni processo ha uno spazio di indirizzamento privatoIl sistema operativo non consente di accedere allo spazio di indirizzamento di un altro processoEsistono delle funzioni che permettono di definire dello spazio in memoria come condiviso da più processi

Page 24: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 2424 - -

Memoria condivisaMemoria condivisa

La funzione che permette di condividere un’area di memoria è la mmap() di cui non vediamo tutti i dettagliLibreria da includere: sys/mman.hUna volta condiviso un’area di memoria, è possibile leggere e scrivere al suo interno come per una qualsiasi altra area di memoriaL’utilizzo della memoria condivisa implica la necessità di gestire in maniera corretta l’accesso concorrente ad essa (mutua esclusione)

Page 25: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 2525 - -

mmap()mmap()

Sintassivoid *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off)

EffettoCondivide una zona di memoria

ParametriIl primo e l’ultimo parametro sono solitamente 0len è la dimensione dell’area di memoriaprot indica i criteri di protezione:

PROT_NONE i dati non sono accessibiliUn or di PROT_WRITE PROT_READ e/o PROT_EXEC per rendere possibile ciascuna delle tre operazioni

Page 26: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 2626 - -

mmap()mmap()

Altri parametriflags (principali valori)

MAP_SHARED per condividere i cambiamenti dovuti a scrittureMAP_PRIVATE le modifiche non si ripercuotono sugli altri processi

fildesUn descrittore di file, tipicamente si usa –1 per l’uso qui descritto della mmap

Page 27: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 2727 - -

SemaforiSemafori

I semafori sono una delle possibili soluzioni al problema dell’accesso a risorse condivise in mutua esclusioneUn semaforo è un contatore intero positivo a cui sono associate

Una coda dei processi sospesi sul semaforoTre operazioni

InizializzazionePost (nota anche come signal e come V)Wait (nota anche come P)

Page 28: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 2828 - -

SemaforiSemafori

Esistono diverse implementazioni dei semaforiNell’implementazione standard di Unix i semafori vengono raggruppati in vettoriLe principali funzioni per la gestione di vettori di semafori sono:

semget()Inizializza un vettore di semafori

semop()Agisce su un semaforo

semctl()Gestisce i semafori

Page 29: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 2929 - -

semget()semget()

Sintassiint semget(key_t key, int nsem, int semflg)

EffettoCrea un vettore di semafori e restituisce l’identificatore del vettore creato se ha successo, -1 altrimenti

Parametri (confrontare con la msgget())Una chiave numericaIl numero di semafori da creare nel vettoreI flag

Page 30: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 3030 - -

semop()semop()

Sintassiint semop (int semid, struct sembuf *sops, unsigned nsops)

EffettoEffettua le operazioni specificate sul vettore di semafori

Parametrisemid l’identificatore del vettore di semaforisops un vettore di strutture dati che definisce le operazioninsops il numero di operazioni specificate in sembuf

Page 31: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 3131 - -

struct sembufstruct sembuf

E’ la struttura dati che descrive un’operazione da svolgere su un semaforo tramite la semop()Se si vuole agire su un solo semaforo si crea un vettore composto da un solo elementoI campi della struttura sono:

sem_num: l’indice del semaforo su cui agire all’interno del vettoresem_op: il valore da sommare al semaforosem_flg: è possibile specificare come flag IPC_NOWAIT se non si desidera sospendere il processo sull’operazione sul semaforo

Page 32: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 3232 - -

semctl()semctl()

Sintassiint semctl (int semid, int semnum, int cmd, union semun arg)

ParametriL’identificatore del vettore di semaforiIl numero del semaforo su cui agireIl comando da eseguire (fra cui SETVAL per inizializzare e IPC_RMID per distruggere il vettore di semafori)Un parametro opzionale dipendente dal comando (per la SETVAL si può utilizzare un intero che corrisponde al valore iniziale del semaforo)

Page 33: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 3333 - -

SemaforiSemafori

La funzione per operare sui semafori (semop()) è scomoda da utilizzareUn’unica funzione implementa sia la wait che la postSolitamente si definiscono due funzioni più intuitive che effettuano la post e la waitAnalogamente per l’inizializzazione dei semaforiSi veda in proposito l’esempio di codice sulla memoria condivisa

Page 34: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 3434 - -

Memoria condivisa - esempioMemoria condivisa - esempio

/* A readers/writers program using a shared buffer and semaphores */

#include <sys/types.h>#include <unistd.h>#include <stdio.h>#include <sys/mman.h>#include <sys/sem.h>#define BUF_SIZE 5

/* logical size of buffer */ #define SHARED_MEM_SIZE

(BUF_SIZE+2)*sizeof(int) /* size of shared memory */

#define run_length 10 /* number of iterations in test run */

#define buf_used 0 /* semaphore array index to check buffer elts used */

#define buf_space 1 /* semaphore array index to check buffer elts empty */

int sem_init(void) {

/* procedure to create and initialize semaphores and return semaphore id,assuming two semaphores defined in the given array of semaphores */ int semid; /* create new semaphore set of 2 semaphores */ if ((semid = semget (IPC_PRIVATE, 2, IPC_CREAT | 0600)) < 0){

perror ("error in creating semaphore");/* 0600 = read/alter by user */

exit (1); }

Page 35: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 3535 - -

Memoria condivisa - esempioMemoria condivisa - esempio

/* initialization of semaphores */ /* BUF_SIZE free spaces in empty buffer */ if (semctl (semid, buf_space, SETVAL, BUF_SIZE) < 0){

perror ("error in initializing first semaphore");

exit (1); }/* 0 items in empty buffer */ if (semctl (semid, buf_used, SETVAL, 0) < 0){

perror ("error in initializing second semaphore");

exit (1); }return semid;

}

void sem_wait(int semid, int index) {

/* procedure to perform a P or wait operation on a semaphore of given index */struct sembuf sops[1]; /* only one semaphore operation to be executed */ sops[0].sem_num = index; sops[0].sem_op = -1; sops[0].sem_flg = 0;

if (semop(semid, sops, 1) == -1) {

perror("error in semaphore operation");

exit (1); }

}

Page 36: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 3636 - -

Memoria condivisa - esempioMemoria condivisa - esempio

void sem_post(int semid, int index) {

/* procedure to perform a V or signal operation on semaphore of given index */

struct sembuf sops[1]; sops[0].sem_num = index;sops[0].sem_op = 1; sops[0].sem_flg = 0;

if (semop(semid, sops, 1) == -1){

perror ("error in semaphore operation");

exit (1); }

}

int main (void) {

pid_t pid; /* variable to record process id of child *//* shared memory elements */ caddr_t shared_memory; /* shared memory base address */ int *in; /* pointer to logical 'in' address for writer */ int *out; /* pointer to logical 'out' address for reader */ int *buffer; /* logical base address for buffer */ /* semaphore elements */ int semid; /* identifier for a semaphore set */ /* local variables */ int i_child, j_child; /* index variables */ int value; /* value read by child */

Page 37: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 3737 - -

Memoria condivisa - esempioMemoria condivisa - esempio

/* set up shared memory segment */ shared_memory=mmap(0, SHARED_MEM_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_SHARED, -1, 0);if (shared_memory == (caddr_t) -1) {

perror ("error in mmap while allocating shared memory\n");

exit (1); }/* set up pointers to appropriate places in shared memory segment */ buffer = (int*) shared_memory; /* logical buffer starts at shared segment */ in = (int*) shared_memory + BUF_SIZE*sizeof(int); out = (int*) shared_memory + (BUF_SIZE+1)*sizeof(int); *in = *out = 0; /* initial starting points */

/* create and initialize semaphore */ semid = sem_init(); if (-1 == (pid = fork())) /* check for error in spawning child process */ {

perror ("error in fork");exit (1);

}if (0 == pid) { /* processing for child == reader */ printf ("The reader process begins.\n");

for (i_child = 0; i_child < run_length; i_child++) { sem_wait(semid, buf_used); /* wait semaphore for something used */ value = buffer[*out]; *out = (*out + 1) % BUF_SIZE;

Page 38: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 3838 - -

Memoria condivisa - esempioMemoria condivisa - esempio

printf ("Reader's report: item %2d == %2d\n", i_child, value); sem_post(semid, buf_space); /* signal semaphore for space available */ } printf ("Reader done.\n");}else { /* processing for parent == writer */ printf ("The writer process begins.\n"); for (j_child = 0; j_child < run_length; j_child++) { sem_wait(semid, buf_space); /* wait semaphore for space available */ buffer[*in] = j_child*j_child; /* put data in buffer */ *in = (*in + 1) % BUF_SIZE;

printf ("Writer's report: item %2d put in buffer\n", j_child); sem_post(semid, buf_used); /* signal semaphore for something used */ } wait (pid); printf ("Writer done.\n"); /* Remove the semaphore from the system */ if (semctl (semid, 0, IPC_RMID) < 0) { perror ("error in removing semaphore from the system"); exit (1); } printf ("Semaphore cleanup complete.\n");}exit (0);

}

Page 39: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 3939 - -

Semafori PosixSemafori Posix

Una interessante libreria di semafori è quella dello standard PosixComoda, ma non sempre implementataLa libreria da importare è la semaphore.hIl tipo di un semaforo è sem_tLe principali funzioni per l’utilizzo dei semafori sono:

sem_init()

sem_wait()

sem_post()

sem_trywait()

Page 40: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 4040 - -

Posix - sem_init()Posix - sem_init()

Sintassiint sem_init(sem_t *sem, int pshared, unsigned int value)

EffettoInizializza il semaforo sem con il valore iniziale value

Ritorna –1 in caso di errore

ParametriIl semaforo da creareSe pshared è 0 il semaforo non è condiviso, altrimenti è condivisoIl valore iniziale

Page 41: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 4141 - -

Posix - sem_wait()Posix - sem_wait()

Sintassiint sem_wait(sem_t *sem)

EffettoDecrementa il valore del semaforoSe il semaforo è a 0, il chiamante viene sospesoUtilizzando la sem_trywait() si ha lo stesso effetto senza sospensione del processoRestituisce 0 in caso di successo, -1 altrimenti

ParametriIl semaforo su cui agire

Page 42: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 4242 - -

Posix - sem_post()Posix - sem_post()

Sintassiint sem_post(sem_t *sem)

EffettoSe non ci sono processi sospesi sul semaforo, incrementa il valore del semaforoSe ci sono processi sospesi sul semaforo, ne viene risvegliato unoRestituisce 0 in caso di successo, -1 altrimenti

ParametriIl semaforo su cui agire

Page 43: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 4343 - -

SocketSocket

E’ possibile scrivere programmi in C che utilizzano la rete per comunicare

Es: implementazione del paradigma client-server

L’interfaccia Socket permette di utilizzare il canale di rete sottostanteE’ possibile utilizzare questa interfaccia con diversi protocolli di rete

Scelta più comune: TCP/IP

Esiste anche per Windows (winsocket)Possibilità di interfacciare programmi che girano su piattaforme diverse

Page 44: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 4444 - -

SocketSocket

Per comunicare tramite l’interfaccia socket è necessario stabilire una connessioneUna connessione fra un processo P e un processo Q è rappresentata da quattro parametri:

Indirizzo IP di PNumero di porta di PIndirizzo IP di QNumero di porta di Q

Un processo può avere contemporaneamente attive più connessioni

Es: un server per un certo numero di client

Page 45: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 4545 - -

Interfaccia (API) di socketInterfaccia (API) di socket

I file di libreria da includere per utilizzare i socket sono: sys/types.h, sys/socket.h, netinet/in.h

La struttura dati che descrive un socket è la seguente:

struct sockaddr_in {

short sin_family; //Solitamente AF_INETushort sin_port; //Numero di portastruct in_addr sin_addr; //Indirizzo IPchar sin_zero[8]; } //Inutile

Page 46: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 4646 - -

Creazione della connessioneCreazione della connessione

Per creare una connessione esistono due modi diversi:

Il server utilizza la funzione accept (bloccante) che effettua un’apertura passiva (si dichiara disponibile ad aprire una connessione)Il client utilizza la funzione connect che effettua un’apertura attiva (stabilisce effettivamente la connessione con il server)

Perché una connect abbia successo, il server che si intende contattare deve aver effettuato l’apertura passiva

Page 47: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 4747 - -

Socket – Lato clientSocket – Lato client

Il client esegue le seguenti operazioni:Definisce e inizializza una variabile di tipo struct sockaddr_in contenente le informazioni relative al server (indirizzo IP e porta)Crea un socket della connessioneEsegue la connect specificando il proprio socket

Page 48: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 4848 - -

Socket – Lato serverSocket – Lato server

Il serverPredispone una variabile struct sockaddr_in client_addr per memorizzare indirizzo IP e porta del clientPredispone una variabile struct sockaddr_in server_addr per memorizzare il proprio indirizzo IP e port (normalmente si specifica solo la porta)Crea un socket per accettare connessioniEffettua, tramite la funzione bind un binding fra il socket e server_addrEffettua la accept per stabilire la connessione

Page 49: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 4949 - -

socket()socket()

Sintassiint socket(int family, int type, int protocol

EffettoCrea un socket e ne restituisce il descrittore; restituisce -1 in caso di errore

ParametriFamiglia di protocolli (AF_INET per TCP/IP)Tipo di comunicazione:

SOCK_STREAM per flusso affidabile di dati SOCK_DGRAM per datagrammi UDP

Protocollo della famiglia (solitamente 0)

Page 50: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 5050 - -

connect()connect()

Sintassiint connect(int sd, struct sockaddr_in *server_addr, int ep_len)

EffettoEffettua l’apertura attiva della connessione

ParametriIl socket da utilizzareI dati relativi all’indirizzo e porta del serverLa lunghezza del parametro precedente (tipicamente sizeof(server_addr))

Page 51: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 5151 - -

bind()bind()

Sintassiint bind(int sd, struct sockaddr_in *server_addr, int ep_len)

EffettoAssocia un numero di porta TCP ad un socket. Restituisce 0 in caso di successo, -1 altrimenti

ParametriIl socket da utilizzareI dati relativi all’indirizzo e porta del serverLa lunghezza del parametro precedente (tipicamente sizeof(server_addr))

Page 52: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 5252 - -

listen()listen()

Sintassiint listen(int sd, int len)

EffettoCrea e dimensiona una coda di richieste di connessione pendenti associata al socket. Restituisce 0 in caso di successo, -1 altrimenti

ParametriIl socket per cui creare la codaLa lunghezza della coda

Page 53: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 5353 - -

accept()accept()

Sintassiint accept(int sd, struct sockaddr_in *client_addr, int ep_len)

EffettoAccetta una richiesta di collegamento in qualità di server e restituisce un socket

ParametriIl socket da utilizzare per la ricezione della richiestaI dati relativi all’indirizzo e porta del clientLa lunghezza del parametro precedente (tipicamente sizeof(client_addr))

Page 54: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 5454 - -

Trasferimento di datiTrasferimento di dati

Per trasferire dati si utilizzano le funzioni send() e recv()

int send(ind sd, char *message, int len, int flags)

int recv(ind sd, char *message, int len, int flags)

ParametriIl socket da utilizzareUna stringa contentente il messaggioLa lunghezza della stringaDei flag per specificare funzioni speciali (di solito 0)Restituiscono il numero di caratteri trasferiti

Page 55: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 5555 - -

Altre funzioni utiliAltre funzioni utili

unsigned int inet_addr(char *stringa)Converte l’indirizzo IP da stringa a formato di rete

char * inet_ntoa(unsigned int addr)Converte l’indirizzo IP da formato di rete a stringa

unsigned short int htons(unsigned short int port)

Converte il numero di porta da numero intero a formato di rete

unsigned short int ntohs(unsigned short int port)

Converte il numero di porta da formato di rete a numero intero

Page 56: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 5656 - -

Socket – esempio di clientSocket – esempio di client

#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 4000

void addr_initialize(struct sockaddr_in *indirizzo, int port, long IPaddr)

{ indirizzo->sin_family = AF_INET; indirizzo->sin_port = htons((u_short)

port); /* htons: host to network

conversion, short */ indirizzo->sin_addr.s_addr = IPaddr;}

void main(int argc, char* argv[]){ int sd; struct sockaddr_in server_addr; struct sockaddr_in mio_addr; int mio_addr_len=sizeof(mio_addr); int error, num, inviati; char dati[12]="abcdefghilm";

addr_initialize(&server_addr, PORT, inet_addr(argv[1]));

sd=socket(AF_INET,SOCK_STREAM,0); error=connect(sd,(struct sockaddr*)

&server_addr, sizeof(server_addr)); if (error==0) { printf("Ho eseguito la connessione\

n"); printf("\n inserire il numero di

caratteri da trasmettere: "); scanf("%d", &num);

Page 57: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 5757 - -

Socket – esempio di clientSocket – esempio di client

while (num > 0) { inviati=send(sd,dati,num,0); printf(" inserire il numero di

caratteri da trasmettere: "); scanf("%d", &num); } printf("\n Chiudo la connessione \

n"); close(sd); } else printf("%s","\nErrore di connect\

n\n"); close(sd);}

Page 58: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 5858 - -

Socket – esempio di serverSocket – esempio di server

#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <netinet/in.h>#define PORT 4000#define MAXCONN 5#define DIMBUF 6

void addr_initialize(struct sockaddr_in *indirizzo, int port, long IPaddr)

{ indirizzo->sin_family = AF_INET; indirizzo->sin_port = htons((u_short)

port); /* htons: host to network

conversion, short */ indirizzo->sin_addr.s_addr = IPaddr;}

void main(int argc, char * argv[]){ int sd,new_sd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int client_len=sizeof(client_addr); int ric=1, i; char buf[DIMBUF];

addr_initialize(&server_addr, PORT, INADDR_ANY);

sd=socket(AF_INET,SOCK_STREAM,0);

bind(sd,(struct sockaddr*) &server_addr,sizeof(server_addr));

listen(sd,MAXCONN);

Page 59: Politecnico di Milano © 2002 - Domenico Barretta Processi concorrenti in Unix Docente Domenico Barretta Politecnico di Milano barretta@elet.polimi.it

Processi concorrenti in UnixProcessi concorrenti in Unix © 2002 - Domenico Barretta© 2002 - Domenico Barretta- - 5959 - -

Socket – esempio di serverSocket – esempio di server

while (1) { printf("\nMi pongo in attesa di

richieste di connessione\n"); new_sd=accept(sd,(struct sockaddr*)

&client_addr, &client_len); printf("Ho accettato una connessione\

n"); ric=1; while (ric>0) { ric=recv(new_sd,buf,DIMBUF,0); printf("\nHo ricevuto %d caratteri:

",ric); for (i=0; i<ric;i++) printf("%c",

buf[i]); } close(new_sd); printf("chiudo la connessione\n"); } /* fine del ciclo perenne */ close(sd);}