3.2 KiB
Executable file
Primitive di comunicazione asincrone
Comunicazione asimmetrica:
- send non bloccante
- receive non bloccante
I canali sono definiti mediante un costrutto port
.
(vedi lesson 11)
E' la primitiva di piu' basso livello, analogamente ai semafori, soprattutto se il kernel non e' in grado di fornire primitive a memoria condivisa.
Scambio di dati e modello client/server
Producer and Consumer
Data una port dati
:
- Il produttore esegue
send() to dati
- il consumatore esegue
p=receive() from dati
A differenza di produttore e consumatore nel caso di semafori e monitor, non c'e' controllo sulla dimensione del canale. Scambio di dati con buffer potenzialmente infinito, che pero' potrebbe essere riempito da applicazioni errate.
Singolo produttore, piu' consumatori
(vedi slides per grafico) Introduce la necessita' di un processo gestore:
- Il produttore manda i dati sulla porta al gestore
- I consumatori mandano un segnale pronto al gestore, che quindi invia i dati al consumatore attraverso un canale del processo consumatore.
(vedi slides per gestore 'smistatore')
Interfaccia produttore
produttore {
while true {
... produce dato d ...
send (d) to gestore.dati
}
}
Interfaccia consumatore
consumatore {
port T dati;
.
.
.
send (s) to gestore.pronto
p = receive (d) from dati
}
}
Piu' produttori, piu' consumatori
Caso con buffer limitato:
- I consumatori sono analoghi al caso precedente
- I processi produttori sono multipli, quindi devono segnalare allo smistatore che sono pronti a inviare dati. Il buffer limitato fa si che il gestore debba tenere un contatore per controllare che i produttori possano aggiungere dati al buffer.
Il contatore del gestore viene aumentato quando i dati sono inviati dal produttore, e diminuito quando ci sono consumatori che richiedono dati. I consumatori sono quindi autorizzati a ricevere dati solo se il contatore e' > 0
, mentre i produttori sono autorizzati a mandare dati solo se il contatore e' < N
(dove N e' la dimensione del buffer).
Questa e' un' applicazione delle guardie.
(vedi slides per gestore)
Interfaccia produttore
produttore {
port S OK_send;
while true {
... produce dato d ...
send (s) to gestore.pronto
receive (s) from OK_send
send (d) to gestore.dati
}
}
Problema delle strategie di priorita'
Suppongo un server che gestisca un pool di risorse, e client che fanno richieste per ottenere una risorsa e deve ottenerla quello che ha priorita' massima (gli altri si bloccano mentre sono in attesa).
(vedi slides per codice server / esempio di guardie )
Le priorita' non sono specificate: le uniche informazioni sono quelle relative alla priorita' dei processi (il primo in coda e' quello con priorita' massima, l'ultimo quello con priorita' minima). Le risorse sono equivalenti.
Interfaccia client
client {
port int risorsa
...
send (s) to server.richiesta
p = receive (r) from risorsa
... usa risorsa...
send (r) to server.rilascio
}
Il client ha un'interfaccia semplice perche' la priorita' e' tutta gestita dal server.
Esercizi
- l'esercizio 2 e' un crivello di Eratostene (genera tutti i primi filtrando i multipli)
- l'esercizio 3 e' un rifacimento dell'esercizio H2O