Sistemi Operativi (M-Z) - Processi, Thread & Communicazione fra Processi - Dipartimento di Matematica e ...

Pagina creata da Fabio Castagna
 
CONTINUA A LEGGERE
Sistemi Operativi (M-Z) - Processi, Thread & Communicazione fra Processi - Dipartimento di Matematica e ...
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