114 lines
5.4 KiB
Markdown
Executable file
114 lines
5.4 KiB
Markdown
Executable file
# Primitive Sincrone
|
|
|
|
* Send bloccante e receive bloccante
|
|
*(vedi slides)*
|
|
|
|
## Guardie di output
|
|
|
|
Una guardia solitamente era trattata come una *recv* bloccante (**guardia di input**), ma possono esistere anche guardie della forma:
|
|
```
|
|
(<espr. booleana>); <primitiva send>
|
|
```
|
|
Che e' definita come **guardia di output**.
|
|
**Mescolare guardie di input e guardie di output puo' creare situazioni di deadlock.** *(vedi slides per esempi)*
|
|
Questo e' dovuto principalmente alla scelta non deterministica tra piu' guardie valide. Per questo motivo si decide di non utilizzare le guardie di output, a parte in alcuni casi specifici.
|
|
|
|
## Processi servitori: gestione di pool di risorse equivalenti
|
|
|
|
**Caso sincrono**
|
|
*(slides per implementazione)*
|
|
|
|
## Processi servitori: gestione di una risorsa dedicata
|
|
|
|
*(vedi slides)*
|
|
|
|
## Simulazione di un semaforo
|
|
|
|
Le primitive sincrone hanno lo stesso potere di tutte le primitive viste precedentemente. *(vedi slides per implementazione semaforo)*
|
|
|
|
## Prod/Cons con buffer di lunghezza finita
|
|
|
|
*(slides per implementazione)*
|
|
|
|
Il processo buffer e' un server che gestisce inserimento ed estrazione dalla coda.
|
|
|
|
Vedi anche esempio con guardie di output, che utilizza primitive di send per mandare i dati al consumatore.
|
|
|
|
## Prod / Cons con N processi server
|
|
|
|
Il buffer di N dati e' realizzato da N processi dati, produttore e consumatore estrerni.
|
|
*(slides per implementazione)*
|
|
Questa soluzione e' semplice, ma presuppone hardware con **elevato parallelismo**.
|
|
|
|
## Specifica di strategie di priorita'
|
|
|
|
*(slides per implementazione)*
|
|
I processi aspettano per ottenere una risorsa, ma quando questa si libera viene svegliato il processo con **priorita' piu' alta**. Caso analogo con send asincrona. I clienti in attesa sono inseriti in ordine di priorita' in una coda, e si presuppone un'unica risorsa (non un pool). E' praticamente uguale al caso asincrono.
|
|
|
|
## Lettori / Scrittori
|
|
|
|
*(slides per implementazione)*
|
|
Soluzione identica al caso asincrono. In questa soluzione pero' **non e' necessario gestire le code**.
|
|
|
|
## Note sulle primitive sincrone
|
|
|
|
Difficilmente sono implementate a livello kernel, perche' e' possibile realizzarle con le asincrone.
|
|
|
|
# Chiamate di procedura remota e rendez-vous (esteso)
|
|
|
|
Chiamata di procedura remota e rendez-vous esteso sono due concetti simili:
|
|
* Chiamata di procedura remota e' relativa alle soluzioni **multithreading**
|
|
* Rendez-vous esteso e' relativo alle soluzioni single thread (single server con interrupt)
|
|
La loro funzione e' pero' la stessa:
|
|
|
|
* Il client effettua una richiesta sul server, richiedendo una procedura. Nel caso RPC, questa procedura viene eseguita su un processo (thread) separato. Nel caso del rendez-vous esteso, l'operazione richiesta e' specificata come una serie di istruzioni che possono comparire in un punto qualunque del server. Il server usa quindi un *accept* che interrompe l'esecuzione e passa all'esecuzione delle istruzioni. *(vedi slides per dettagli e implementazione)*
|
|
|
|
### Esempio RPC: servizio di sveglia
|
|
|
|
Insieme di N processi clienti possono richiedere di essere svegliati da un processo servitore, dopo un tempo da loro prefissato. *(slides per grafico)*
|
|
|
|
Il server utilizzera' quindi un clock, che opera su un processo separato, e una serie di N thread relativi ai singoli processi, che sono spawnati una volta che il clock raggiunge i tempi prefissati. I thread si occupano di svegliare i processi.
|
|
|
|
*(slides per implementazione)*
|
|
|
|
### Rendez-vous
|
|
|
|
Il servizio richiesto e' specificato come insieme di istruzioni che possono comparire in un punto qualunque del processo servitore:
|
|
|
|
```
|
|
accept<servizio> (in <param-ingresso>,
|
|
out <param-uscita>);
|
|
(S1, ... , SN) -> S0;
|
|
```
|
|
|
|
* Nota: S1, ... SN sono servizi da eseguire in rendez-vous, mentre S0 e' una procedura eseguita solo dal server, non in rendez-vous.
|
|
|
|
#### Accept
|
|
|
|
* Bloccante: se non sono presenti richieste, provoca la sospensione del server
|
|
* Se lo stesso servizio e' richiesto da piu' processi, si utilizza una coda FIFO
|
|
* Lo schema di comunicazione e' quindi **asimmetrico da molti a uno**.
|
|
|
|
*(slides per grafico di esecuzione)*
|
|
|
|
##### Selezione delle richieste in base ai parametri di ingresso
|
|
|
|
Con accept, la selezione della richiesta da servire **puo' dipendere anche dai parametri d'ingresso della richiesta stessa**. In questo caso la guardia logica che condiziona l'esecuzione dell'azione puo' essere espressa anche in termini dei parametri di ingresso.
|
|
Questo richiede una doppia interazione tra server e client, la prima per trasmettere i parametri, la seconda per la richiesta stessa.
|
|
*NB: il numero di parametri deve essere limitato*
|
|
|
|
#### Esempio: sveglia
|
|
|
|
In questo esempio con rendez-vous del processo sveglia ci sono 3 tipi di richieste: *(vedi slides)*
|
|
*(slides per implementazione)*
|
|
In questo esempio, il client manda due richieste: nella prima manda il tempo dopo cui vuole essere svegliato, nella seconda manda l'effettiva richiesta di sveglia. Il server riceve la prima richiesta e la memorizza. Quando riceve la seconda richiesta, riordina il vettore *tempo-di-sveglia* in cui ha inserito il tempo indicato, e sveglia il processo dopo il tempo ricevuto.
|
|
|
|
#### Esempio: r&w
|
|
|
|
I lettori fanno tutte le *call*, gli scrittori fanno tutti gli *accept*. *(vedi slides per implementazione)*
|
|
|
|
|
|
# Linguaggi CSP: Communication Sequential Process
|
|
|
|
Modello di interazione tra processi, che utilizzano una comunicazione sincrona (di solito sono sulla stessa board, vari processori). *(vedi slides)*
|
|
|