UniTO/anno2/YearI/MCAD/lesson12-14112017.md

109 lines
3.2 KiB
Markdown
Raw Normal View History

2018-11-22 13:09:11 +01:00
# 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