Sistemi Operativi (M-Z) - Processi, Thread & Communicazione fra Processi - Dipartimento di Matematica e ...
←
→
Trascrizione del contenuto della pagina
Se il tuo browser non visualizza correttamente la pagina, ti preghiamo di leggere il contenuto della pagina quaggiù
Sistemi Operativi (M-Z) Processi, Thread & Communicazione fra Processi C.d.L. in Informatica (laurea triennale) A.A. 2019-2020 Prof. Mario F. Pavone Dipartimento di Matematica e Informatica Università degli Studi di Catania mario.pavone@unict.it mpavone@dmi.unict.it
Processo l Definizione: una istanza di esecuzione di un programma. l Si associano ad esso: n spazio degli indirizzi: n codice eseguibile; n dati; n stack; n copia dei registri della CPU; n file aperti; n allarmi pendenti; n processi imparentati. l Tabella dei processi con un Process Control Block (PCB) per ogni processo.
Programma vs. Processo l Programma: entità passiva -> contiene la lista delle istruzioni memorizzate sul disco l Processo: entità attiva l Due processi associati allo stesso programma sono considerati distinti l uguale codice ma differenti dati; stack; etc. l Share Code: solo una copia si trova in memoria
Stato di un processo l 3 stati principali (+ 2 addizionali); l transizioni.
Creazione e terminazione dei processi l Creazione di un processo: n in fase di inizializzazione del sistema; n da parte di un altro processo (padre) o per un'azione dell'utente; n metodologie: n sdoppiamento del padre: fork e exec (UNIX); n nuovo processo per nuovo programma: CreateProcess (Win32). l Terminazione: n uscita normale (volontario): exit (UNIX), ExitProcess (Win32); n uscita su errore (volontario); n errore critico (involontario): alcuni sono gestibili, altri no; n terminato da un altro processo (involontario): kill (UNIX), TerminateProcess (Win32).
Gerarchia dei Processi l Un processo può crearne un’altro l processo padre e processo figlio l processo figlio può a sua volta crearne altri l UNIX: process group l processo speciale init l In Windows: NO l Tutti i processi sono uguali l handle: token per il processo padre
Tabella dei processi l SO mantiene una Tabella dei processi; l Process Control Block (PCB); l Scheduler (bottom fig.); l Gestione degli interrupt per il passaggio di processo (vettore di interrupt & procedura di servizio dell’interrupt): n salvataggio nello stack del PC e del PSW nello stack attuale; n caricamento dal vettore degli interrupt l'indirizzo della procedura associata; n salvataggio registri e impostazione di un nuovo stack; n esecuzione procedura di servizio per l'interrupt; n interrogazione dello scheduler per sapere con quale processo proseguire; n ripristino dal PCB dello stato di tale processo (registri, mappa memoria); n ripresa nel processo corrente.
Code e accodamento l Coda dei processi pronti e code dei dispositivi; n strutture collegate sui PCB; l Diagramma di accodamento:
Thread l Modello dei processi: entità indipendenti che raggruppano risorse e con un flusso di esecuzione; l può essere utile far condividere a più flussi di esecuzione lo stesso spazio di indirizzi: thread; l quando può essere utile? n esempi: web-browser, videoscrittura, web-server, …
Thread: an example WORD PROCESSOR Un thread si occupa di interagire con l’utente; un altro formatta il documento; un terzo fa il backup su HD
Thread: an example WEB SERVER PROCESS NOTA: il dispatcher è un ciclo infinito che acquisisce richieste di lavoro e le passa ad un worker thread
Thread 3 processi 3 thread
Thread l Un thread è caratterizzato da: n PC, registri, stack, stato; n condivide tutto il resto; n no protezione di memoria. l scheduling dei thread; l cambio di contesto più veloce; Sistemi Multithreading
Thread l Thread diversi nello stesso processo non sono indipendenti l Condivisione e No protezione di memoria l un thread può leggere, scrivere o cancellare lo stack di un altro thread l Stesso user -> Cooperano -> non entrano in conflitto l Thread apre file => è visibile ad ogni thread nel processo l Unità gestione delle risorse => Processo
Thread l Ogni Thread ha un proprio Stack: perchè? l Utilizzano procedure diverse l storia di esecuzione diversa
Stati di un Thread l Anche un thread può trovarsi in uno dei seguenti stati l Transizioni di stato => analogo a quello dei processi.
Operazioni sui Thread l Nei sistemi Multithreading i processi inizano con un singolo thread l operazioni tipiche sui thread: n thread_create: un thread ne crea un altro; n thread_exit: il thread chiamante termina; n thread_join: un thread si sincronizza con la fine di un altro thread; n thread_yield: il thread chiamante rilascia volontariamente la CPU n no clock interrupt
Programmazione multicore l I thread permettono una migliore scalabilità con core con hypertreading e soprattutto con sistemi multicore; l con un sistema single-core abbiamo una esecuzione interleaved; singola T T T T T T T T T ... CPU 1 2 3 4 1 2 3 4 1 tempo l su un sistema multi-core abbiamo parallelismo puro. core 0 T T T T ... 1 3 1 3 core 1 T T T T ... 2 4 2 4 tempo
Programmazione multicore l Progettare programmi che sfruttino le moderne architetture multicore non è banale; l principi base: n separazione dei task; n trovare aree per attività separate e simultanee n bilanciamento; n assicurarsi che eseguano lo stesso lavoro di uguale valore n suddivisione dei dati; n dividere i dati per essere eseguiti su core separati n dipendenze dei dati; n esecuzione delle attività sia sincronizzata n test e debugging
Thread a livello utente l Vantaggio: il kernel non ne è a conoscenza l utile se non c'è supporto da parte del kernel ai thread; l Sistema Run-Time: raccolta di procedure per thread l Tabella dei Thread l gestita dal sistema run-time NOTA: le procedure che salvano lo stato del thread e lo scheduler sono locali
Thread a livello utente l Pro: n thread switching veloce n il dispatching non richiede trap nel kernel; n scheduling personalizzato; l Contro: n Implementazione chiamate bloccanti n una chiamata genera un blocco? n select, & page-fault n possibilità di non rilascio della CPU n clock sistema run-time
Thread a livello kernel l No sistema run-time l no tabella dei thread nel processo l unica tabella dei thread del kernel; l Pro: n un thread su chiamata bloccante non intralcia gli altri; l Contro: n cambio di contesto più lento (richiede trap); n creazione e distruzione più costose (numero di thread kernel tipicamente limitato, possibile riciclo).
Modello ibrido l prende il meglio dei due l prevede un certo numero di thread del kernel; l ognuno di essi viene assegnato ad un certo numero di thread utente (eventualmente uno); l assegnazione decisa dal programmatore.
I thread nei nostri sistemi operativi l Quasi tutti i sistemi operativi supportano i thread a livello kernel; n Windows, Linux, Solaris, Mac OS X,... l Supporto ai thread utente attraverso apposite librerie: n green threads su Solaris; n GNU portable thread su UNIX; n fiber su Win32. l Librerie di accesso ai thread (a prescindere dal modello): n Pthreads di POSIX (Solaris, Linux, Mac OS X, anche Windows); n una specifica da implementare sui vari sistemi; n threads Win32; n thread in Java; n wrapper sulle API sottostanti.
Comunicazione fra processi l Spesso i processi hanno bisogno di cooperare l collegamento I/O tra processi l Comunicazione ben strutturata l InterProcess Communication (IPC) l Problematiche da considerare: 1) come scambiarsi i dati; 2) accavallamento delle operazioni su dati comuni; 3) coordinamento sequenziale tra le operazioni (o sincronizzazione). l Corse critiche (race conditions) l processi che lavorano su risorse condivise: chi viene prescelto per l’esecuzione?
Race Conditions l Spool di Stampa: demone di stampa & directory di spool Evitare che più processi accedino a dati condivisi contemporaneamente
Regioni Critiche l Mutua Esclusione: garantire che il processo B utilizzi le risorse condivise solo dopo che il processo A termini il suo completo utilizzo l Regione/Sezione Critica: parte di programma in cui si accede alla memoria condivisa
Sezioni critiche l Astrazione del problema: sezioni critiche e sezioni non critiche. l Quattro condizioni per avere una buona soluzione: 1. mutua esclusione nell'accesso alle rispettive sezioni critiche; 2. nessuna assunzione sulla velocità di esecuzione o sul numero di CPU; 3. nessun processo fuori dalla propria sezione critica può bloccare un altro processo; 4. nessun processo dovrebbe restare all'infinito in attesa di entrare nella propria sezione critica.
Sezioni critiche: an example
Come realizzare la mutua esclusione 1) Disabilitare gli interrupt. 2) Variabili di lock. 3) Alternanza stretta: int N=2 int turn function enter_region(int process) while (turn != process) do nothing function leave_region(int process) turn = 1 – process n può essere facilmente generalizzato al caso N; n fa busy waiting (si parla di spin lock); n implica rigidi turni tra le parti (viola condizione 3).
Soluzione di Peterson int N=2 int turn int interested[N] function enter_region(int process) other = 1 – process interested[process] = true turn = process while (interested[other] = true and turn = process) do nothing function leave_region(int process) interested[process] = false l ancora busy waiting; l può essere generalizzato al caso N; l può avere problemi sui moderni multi-processori a causa del riordino degli accessi alla memoria centrale.
Istruzioni TSL e XCHG l Molte architetture (soprattutto multi-processore) offrono specifiche istruzioni: n TSL (Test and Set Lock); n uso: TSL registro, lock n operazione atomica e blocca il bus di memoria; enter_region: leave_region: TSL REGISTER,LOCK MOVE LOCK,#0 CMP REGISTER,#0 RET JNE enter_region RET n XCHG (eXCHanGe); n disponibile in tutte le CPU Intel X86; l ancora busy waiting.
Sleep e wakeup l Tutte le soluzioni viste fino ad ora fanno spin lock; n problema dell'inversione di priorità. l Soluzione: dare la possibilità al processo di bloccarsi in modo passivo (rimozione dai processi pronti); n primitive: sleep e wakeup. l Problema del produttore-consumatore (buffer limitato – N): n variabile condivisa count inizialmente posta a 0; function producer() function consumer() while (true) do while (true) do item = produce_item() if (count = 0) sleep() if (count = N) sleep() item = remove_item() insert_item(item) count = count – 1 count = count + 1 if (count = N – 1) if (count = 1) wakeup(producer) wakeup(consumer) consume_item(item) n questa soluzione non funziona bene: usiamo un bit di attesa wakeup.
Puoi anche leggere