Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
Scarica il documento per vederlo tutto.
vuoi
o PayPal
tutte le volte che vuoi
SOVRACCARICO DELLE RISORSE (NO OVERHEAD)
Come si crea un Thread ? Un processo viene SUDDIVISO in tante PARTI ( sotto-processi) . Ognuna di
queste parti ha un PROPRIO Program Counter.
Il CPU SCHEDULING avviene per i THREAD come se fossero dei PROCESSI interi.
OGNI THREAD ha un proprio STACK! Per i parametri e valori di ritorno
OGNI THREAD ha un’UNICA AREA DATI GLOBALE per tutti.
Quali sono i vantaggi dei Threads ?
1) MIGLIOR TEMPO DI RISPOSTA
2) NO OVERHEAD
3) Ottimizzazione dell’uso delle risorse ( La cpu non rimane mai inattiva)
4) EFFICIENZA IN MULTICORE Il Multi-threading implementato su processori multicore garantisce
ottime performances!
PROCESSO IN SINGLE THREAD ( chiamato anche PROCESSO IN MULTI-THREADING
HEAVY WEIGHT PROCESS) P a g . | 32
N.B. con il multi-threading abbiamo:
1) AREA DATI GLOBALE IN COMUNE ( SHARED
MEMORY)
2) PC (+ REGISTRI ) e STACK uno per ogni
THREAD!
Che cos’è l’Hyper-Threading? E’ una strategia HARDWARE implementata per la prima volta da INTEL ,
che prevede una REPLICAZIONE delle UNITA’ di ELABORAZIONE DATI (DATAPATH) per l’esecuzione
PARALLELA di OPERAZIONI in MULTI-THREADING
Esistono 2 tipi di THREAD:
1) Thread a livello UTENTE: è un thread che agisce senza l’intervento del S.O. ( per cui non si va mai
in Modalità Kernel). E’ veloce ma limitato! ( niente syscall al S.O. per interagire con I/O o HW ). Il
Processo ORIGINARIO contiene uno SCHEDULER INTERNO per SCHEDULARE i suoi THREADS.
2) Thread a livello KERNEL: dualmente al Thread a livello UTENTE , i Threads del Processo
ORIGINARIO sono schedulati dallo SCHEDULER del S.O. . Per cui c’è sempre l’intervento del S. O .
con il quale il Thread potrà interfacciarsi tramite SYSCALL
Un S.O. può avere una struttura a THREADS ? ASSOLUTAMENTE SI
I SISTEMI OPERATIVI POSSONO AVERE KERNEL MULTI-THREAD! ( ogni thread svolge una
macrofunzionalità nel sistema). Ogni SYSCALL farà riferimento ad un thread!
CAPITOLO 5 – SINCRONIZZAZIONE DEI PROCESSI
Due processi che comunicano possono usare 2 meccanismi ( come già detto) per comunicare:
1) Il Message Passing
2) SHARED MEMORY
Per processi che utilizzano la SHARED MEMORY necessariamente vi deve essere SINCRONIZZAZIONE!
SINCRONIZZAZIONE: IL PROBLEMA “PRODUTTORE-CONSUMATORE” ( o semplicemente “IL PROBLEMA DEL
BUFFER LIMITATO”)
ESISTONO due PROCESSI : uno sarà IL PRODUTTORE e produrrà INFORMAZIONI ; l’altro sarà il
CONSUMATORE e userà le informazioni del PRODUTTORE
I DUE PROCESSI hanno entrambi accesso ad una parte di MEMORIA CONDIVISA con un BUFFER su
questa memoria che è LIMITATA P a g . | 33
La situazione descritta viene gestita da un codice . Il codice contiene DUE PUNTATORI di tipo
INTERO ( IN E OUT) che tengono conto corrispettivamente della PROSSIMA POSIZIONE LIBERA e
della PROSSIMA POSIZIONE PIENA nel BUFFER.
- Se i due puntatori si sovrappongono significa che il BUFFER è VUOTO (IN = OUT) : tale
condizione è attesa dal CONSUMATORE affinché possa iniziare a prelevare informazione.
- Se i due puntatori sono diversi invece ( IN != OUT) significa che il BUFFER è PIENO : tale
condizione è attesa da PRODUTTORE che si ferma e attende che il CONSUMATORE CONSUMI
IL BUFFER ha un numero di elementi possibili pari a BUFFER_SIZE -1
Affinché possano essere usati gli elementi per un valore pari a BUFFER_SIZE bisognerà aggiungere
una variabile CONTATORE inizializzata a ZERO . IL CONTATORE VERRA’ INCREMENTATO ogni volta
che un ELEMENTO VIENE INSERITO NEL BUFFER e DECREMENTATO AD OGNI ESTRAZIONE.
CHE COS’E’ la SEZIONE CRITICA? è quella sezione di codice che deve essere eseguita in maniera
MUTUAMENTE ESCLUSIVA dai PROCESSI ( se un processo è nella sua SEZIONE CRITICA nessun altro
processo può accedervi). Questo dipende dal fatto che alcune volte (per motivi di sincronizzazione) può
essere necessario accedere a delle variabili in maniera ATOMICA.
Come si gestisce il PROBLEMA DELLA SEZIONE CRITICA? Bisogna progettare un PROTOCOLLO DI
COOPERAZIONE tra i PROCESSI. OGNI PROCESSO DEVE CHIEDERE IL PERMESSO DI ACCESSO ALLA SEZIONE
CRITICA MEDIANTE una “ENTRY SECTION”. Si esce dalla sezione CRITICA mediante una EXIT SECTION.
IL PROBLEMA VA RISOLTO garantendo:
1) Mutua esclusione se un processo è in esecuzione nella sua sezione critica nessun altro può
esservi se
2) PROGRESSO la SEZIONE CRITICA è vuota , necessariamente un processo che ne richiede
l’accesso dovrà prima o poi entrarvi
se
3) ATTESA LIMITATA un processo ha avuto accesso alla sua sezione critica, è necessario
porre un limite di accesso agli altri processi per le proprie sezioni critiche.
Che cos’è l’algoritmo di PETERSON ? è un ALGORITMO che permette di soddisfare MUTUA
ESCLUSIONE, PROGRESSO e ATTESA LIMITATA. Tutto ciò è possibile ammesso che si abbia a che fare con
soli 2 PROCESSI. Questi 2 processi condividono 2 VARIABILI:
1) Int TURNO indica il processo che è di turno per accedere alla propria sezione critica
2) Boolean FLAG[2] è un ARRAY di 2 elementi che indica se un processo è pronto per entrare nella
propria sezione critica o meno se FLAG[i] = TRUE è PRONTO!
Differenza KERNEL CON DIRITTO DI PRELAZIONE e KERNEL SENZA DIRITTO DI PRELAZIONE? più
processi in MODALITA’ UTENTE possono richiedere SERVIZI DEL S.O. tramite SYSCALL. Il Kernel deve
regolare l’accesso ai DATI CONDIVISI. P a g . | 34
CON DIRITTO DI PRELAZIONE un processo in kernel mode può essere interrotto da un altro
processo (ad esempio perché è scaduto il quanto di tempo).
SENZA DIRITTO DI PRELAZIONE un processo in kernel mode non può essere interrotto da un
altro processo.
Qualsiasi SOLUZIONE AL PROBLEMA della SEZIONE CRITICA richiede l’uso di un LOCK ( LUCCHETTO) Un
processo che accede alla sua sezione critica ottiene un LOCK che restituirà al termine.
Come si risolve il problema della sezione critica con sistemi MONOPROCESSORE ? BASTA INTERDIRE LE
INTERRUPTS
Molte architetture moderne usano delle istruzioni atomiche (implementate in HW) per gestire l’accesso
alle SEZIONI CRITICHE:
TestAndSet
CompareAndSwap
QUESTA SOLUZIONE NON GARANTISCE l’ATTESA LIMITATA ( a meno che non si vada a complicare l’HW e
gli algoritmi usati)
Che cos’è il LOCK MUTEX? è una strategia che permette di PROTEGGERE le aree CRITICHI prima
ACQUISENDO il LOCK e poi RILASCIANDOLO ( con le istruzioni acquire() , release())
Che cosa sono i SEMAFORI ? sono meccanismi per la sincronizzazione dei processi.
IL SEMAFORO è una variabile INTERA (inizializzata ad 1) su cui si può OPERARE solo ed esclusivamente
mediante due funzioni atomiche :
1) wait(semaforo)
2) signal(semaforo)
* int semaforo
N.B. wait() e signal() sono funzioni atomiche da applicare al semaforo.
Questa variabile intera , è una variabile CONDIVISA tra tutti i processi che devono essere SINCRONIZZATI
TRA LORO. Tali processi usano questa variabile per gestire la sincronizzazione.
Quanti tipi di semafori esistono? 2 tipi:
1) Semaforo Binario : l’intero assume valori 0 e 1
2) Semaforo Contatore: l’intero può assumere valori in un dominio non limitato
Come si usano i semafori per la RISOLUZIONE DEL PROBLEMA DELLA SEZIONE CRITICA? la variabile
semaforo funge da LOCK MUTEX( lucchetto)
è inizializzata ad 1 semaphore mutex = 1;
IL PROCESSO per la MUTUA ESCLUSIONE
IL PROCESSO PER LA SINCRONIZZAZIONE:
dove S1 e S2 sono generiche operazioni
Che cos’è il BUSY WAITING ? è l’ATTESA ATTIVA dei PROCESSI NON
Dato che l’implementazione dei SEGNALI deve necessariamente far in modo che i PROCESSI
eseguano mai wait() e signal() in uno stesso istante su un SEMAFORO, le due funzioni devono esse stesse
essere gestite in sezione critica! Questo implica che i PROCESSI SIANO IN ATTESA del SEMAFORO: BUSY
WAITING
IL BUSY WAITING è poco efficiente nei sistemi MULTIPROGRAMMATI in quanto spreca cicli di CPU inutili
P a g . | 35
Cosa si può fare per evitare il BUSY WAITING con i SEMAFORI ? il Semaforo è affiancato da una LISTA
DI ATTESA . Esistono a supporto due Syscall chiamate block() e wakeup()
block() mette il processo nella coda d’attesa
wakeup() rimuove il processo dalla coda d’attesa ( viene quindi spostato nella Ready Queue)
IL PROBLEMA DI QUESTA IMPLEMENTAZIONE è che si possono avere DEADLOCKS più processi
attendono in maniera indefinita un evento (attendono l’esecuzione di un’operazione di signal)
IL PROBLEMA DEL PRODUTTORE-CONSUMATORE IMPLEMENTATO CON I SEMAFORI:
Si usano 3 variabili SEMAPHORE CONDIVISE:
semaphore full, empty , mutex; //full è inizializzato a 0, empty è inizializzato a n, mutex a 1
n è il numero di posizioni del Buffer Limitato
mutex garantisce la mutua esclusione sull’accesso al buffer
empty e full corrispondono a IN e OUT ( vedi caso normale)
N.B. mutex è un SEMAFORO BINARIO , empty e full sono 2 semafori CONTATORI
IL FUNZIONAMENTO è IDENTICO AL CASO NORMALE
IL PROBLEMA DEI LETTORI-SCRITTORI è un problema legato alla SINCRONIZZAZIONE tra PROCESSI
Abbiamo processi che possono soltanto LEGGERE ( i LETTORI)
Abbiamo processi che possono soltanto SCRIVERE ( gli SCRITTORI)
Non ci sono PROBLEMI se più LETTORI LEGGONO CONTEMPORANEAMENTE! La lettura non causa
mai incoerenze.
Per la scrittura possono invece verificarsi incoerenze bisognerà accedere in MUTUA
ESCLUSIONE
L’accesso deve rispettare la proprietà : UN SOLO SCRITTORE oppure TANTI LETTORI
IMPLEMENTAZIONE CON I SEMAFORI:
- Si crea un semaforo di mutua esclusione chiamato “scrittura” inizializzato a 1
- Bisognerà far in modo che TANTI LETTORI possano accedere in modalità “LETTURA” se non
abbiamo uno SCRITTORE interagente si usa una variabile num_lettori inizializzata a 0 che
conta il numero dei LETTORI ATTIVI. Il primo lettore acquisirà la MUTUA ESCLUSIONE (
mentre gli altri entreranno direttamente in SEZIONE CRITICA). L’ultimo LETTORE rilascerà la
MUTUA ESCLUSIONE.
- num_lettori è una VARIABILE CONDIVISA tra tutti i LETTORI ( per cui bisognerà proteggerne
l’accesso garantendo la mutua esclusione) si usa un semaforo MUTEX (inizializzato a 1)
IL PROBLEMA DEI 5 FILOSOFI:
ci son