SlideShare une entreprise Scribd logo
1  sur  147
Télécharger pour lire hors ligne
Concetto di processo
• Processo: istanza di un programma in
  esecuzione
  – Codice del programma (sezione di testo)
  – Stato di avanzamento
     ♦ Contatore di programma
     ♦ Pila (variabili locali, indirizzi di ritorno)
  – Variabili locali (sezione dei dati)




                                                       1
Concetto di processo
• Programma e processo sono due entità
  distinte
  – Un programma è un'entità passiva
     ♦ File su disco (codice o eseguibile) immutato
     ♦ Non va in esecuzione da solo
  – Un processo è un'entità attiva
     ♦ Struttura dati contenente puntatori a
        – Codice
        – Dati
        – Stato del processo



                                                      2
Esecuzione di un processo
• Il gestore dei processi esegue, ad intervalli di
  tempo più o meno regolari, una sequenza di
  istruzioni pertinenenti al programma (trace)
• Un SO moderno, multiprogrammato, time-
  sharing      garantisce      una    esecuzione
  sequenziale e concorrente (interleaved) di più
  processi
• Compiti specifici del gestore dei processi:
  – Garantire l'esecuzione sicura di una traccia
  – Scegliere il prossimo processo di cui sarà
    eseguita una traccia (scheduling)
  – Gestire la commutazione periodica tra un
    processo ed un altro (context switch)
                                                     3
Esecuzione interleaved
 Memoria
principale

 Gestore
 processi
                  Program
                  Counter
Processo A



Processo B

Processo C



                                      4
Esecuzione interleaved
 Memoria                    Indirizzi PC
principale
                            a+0
                            a+2
 Gestore
 processi                   a+6
                  Program
                            a + 10
                  Counter
                            Scade l'intervallo
Processo A
                            di tempo assegnato
                            al processo A
Processo B

Processo C



                                                 5
Esecuzione interleaved
 Memoria                    Indirizzi PC
principale
                            g + 100
                            g + 102
 Gestore
 processi                   g + 106
                  Program
                            g + 110
                  Counter
                            g + 114
Processo A
                            Il gestore dei processi
                            sceglie come prossimo
                            processo da eseguire
Processo B
                            il processo B, e ne
                            prepara l'esecuzione
Processo C



                                                      6
Esecuzione interleaved
 Memoria                    Indirizzi PC
principale
                            b + 32
                            b + 36
 Gestore
 processi                   b + 40
                  Program
                  Counter
                            Il processo B si
                            interrompe perché
Processo A
                            deve effettuare una
                            operazione di I/O
Processo B

Processo C



                                                  7
Esecuzione interleaved
 Memoria                    Indirizzi PC
principale
                            g + 100
                            g + 102
 Gestore
 processi                   g + 106
                  Program
                            g + 110
                  Counter
                            g + 114
Processo A
                            Il gestore dei processi
                            sceglie come prossimo
                            processo da eseguire
Processo B
                            il processo C, e ne
                            prepara l'esecuzione
Processo C



                                                      8
Esecuzione interleaved
 Memoria                    Indirizzi PC
principale
                            c + 248
                            c + 356
 Gestore
 processi                   c + 360
                  Program
                            c + 364
                  Counter
                            Il processo C termina
Processo A
                            la sua esecuzione

Processo B

Processo C



                                                    9
Esecuzione interleaved
 Memoria                    Indirizzi PC
principale
                            g + 100
                            g + 102
 Gestore
 processi                   g + 106
                  Program
                            g + 110
                  Counter
                            g + 114
Processo A
                            Il gestore dei processi
                            sceglie come prossimo
                            processo da eseguire
Processo B
                            il processo A, e ne
                            prepara l'esecuzione
Processo C



                                                      10
Esecuzione interleaved
 Memoria                    Indirizzi PC
principale
                            a + 14
                            a + 18
 Gestore
 processi                   a + 22
                  Program
                            a + 56
                  Counter
                            Il processo A si
Processo A
                            blocca perché richiede
                            una operazione di I/O
Processo B

Processo C



                                                     11
Rappresentazione di un processo
• L'esecuzione di tipo interleaved deve essere
  modellata all'interno del gestore dei processi
• Sembrerebbe naturale introdurre un modello
  del tipo DFA (Deterministic Finite Automata,
  automa deterministico a stati finiti)
• Quanti stati utilizzo per il mio modello?
• Proviamo con il caso più semplice:
  – Due stati: running, not running
  – I processi non in esecuzione sono “accodati” di
    fronte al processore, in attesa di ricevere tempo
    di calcolo
  – Tramite oppoerunte transizioni, un processo è
    in grado di cambiare stato
                                                        12
Rappresentazione di un processo
Modello a due stati
                            blocking
creazione                                              terminazione
             not running                  running

                           dispatching



Diagramma di accodamento
creazione                          dispatching         terminazione
                                                 CPU
            coda processi pronti




                                                                      13
Incompletezza del modello a 2 stati
• Il modello a due stati è incompleto
• Tutti i processi che non eseguono sono
  equiparati a processi in qualche modo
  “bloccati”
• In realtà, le cause del blocco possono essere
  estremamente diverse:
  – scadenza dell'intervallo di tempo di calcolo
    assegnato
  – comando di una operazione di I/O
  – arrivo di una interruzione
• Per discriminare le diverse cause di blocco, è
  necessario considerare un modello con
  almeno tre stati
                                                   14
Modello a tre stati
• L'automa che descrive il ciclo di vita di un
  processo è composto da tre stati:
  – running: la CPU sta eseguendo una traccia del
    processo
  – blocked: la CPU ha comandato una istruzione
    che richiede il verificarsi di un evento (di solito,
    I/O) per conto del processo, che deve fermarsi
    ed attendere la risposta
  – ready: la CPU non sta eseguendo una traccia
    del processo (quale che sia il motivo), tuttavia il
    processo è nelle condizioni di essere
    ripristinato
• Differenziazione esplicita degli stati di
  “bloccato” e “pronto”                                    15
Modello a tre stati
Modello a tre stati
                        scadenza
                        intervallo
creazione                                        terminazione
              ready                  running
                          tempo
                       dispatching
   completamento                        attesa
      evento                            evento
                         blocked

Transizioni
   ready => running:   assegnazione CPU al processo
   running => ready:   il processo ha utilizzato il max.
                       tempo per esecuzione traccia
   running => blocked: attesa completamento evento
   blocked => ready:   l'evento atteso si verifica              16
Stati aggiuntivi
• Il modello a tre stati è in grado di catturare le
  diverse      dinamiche        di    interruzione
  dell'esecuzione di una traccia
• Vengono aggiunti alcuni stati aggiuntivi per la
  gestione pulita dei meccanismi di creazione e
  di terminazione del processo
• Due ulteriori stati:
  – new: il sistema alloca ed inizializza le strutture
    dati per la gestione dell'esecuzione del
    processo
  – exit: il sistema rilascia le strutture dati ed
    alcune risorse allocate dal processo

                                                         17
Stati aggiuntivi
Stato aggiuntivo new

creazione                  admit                      terminazione
             new                           ready

                        Strutture dati
                        per il processo
                        allocate ed
                        inizializzate

Stato aggiuntivo exit

                      terminazione
            running                            exit

                        Rilascio strutture
                        dati allocate per il
                        processo
                                                                     18
Modello a cinque stati
• Ad ogni processo è associato uno stato
• Durante l'esecuzione, un processo è soggetto
  a cambiamenti di stato
• Stati:
  – new: il processo è stato appena creato
  – running: una unità di elaborazione esegue le
    istruzioni del relativo programma
  – blocked: il processo è in attesa del verificarsi di
    un qualche evento
  – ready: il processo attende di essere assegnato
    ad una unità di elaborazione
  – exit: il processo ha terminato la sua esecuzione
                                                          19
Modello a cinque stati
             ammesso                       uscita
    new                                                exit

                            interruzione


                    ready               running


completamento I/O                             attesa I/O
                             dispatching
verifica evento                               attesa evento
                              blocked




                                                              20
Modello a cinque stati
Diagramma di accodamento
                                       CPU
   Coda processi pronti



   I/O          Coda I/O      Richiesta I/O


                             quanto di tempo
                                esaurito


           processo figlio    generazione
           in esecuzione     processo figlio


                                 attesa
             occorrenza
                              interruzione
            interruzione
                                               21
Cause di creazione di un processo
• Attivazione di un batch job
  – Comando inviato tramite shell
• Login interattivo
  – Accesso al sistema da parte di un utente
• Gestione di un servizio
  – Un processo soddisfa una richiesta di servizio
  – Il processo invocante non si interrompe
  – Processi server
• Spawning
  – Un processo soddisfa una richiesta di servizio
  – Il processo invocante si interrompe
  – Processi di login
                                                     22
Cause di terminazione di un processo
• Completamento della traccia di istruzioni
  – Può essere comunicato esplicitamente
• Indisponibilità di memoria
  – Il processo richiede troppa memoria
• Violazioni di limite
  – Accesso a locazioni di memoria proibite
• Errore di protezione
  – Accesso ad una risorsa protetta o inesistente
• Terminazione su richiesta
  – Operata dal sistema o da un altro processo
• Errore aritmetico
  – Divisione per zero, overflow
                                                    23
Il grado di multiprogrammazione
• Il processore è, solitamente, molto più veloce dei
  sistemi di I/O
  – La maggior parte dei processi residenti in memoria
    è nello stato blocked, in attesa di completamento di
    una richiesta di I/O
  – Rischio di sottoutilizzo del processore
• Come si può prevenire questo problema?
  – Si cerca di mantenere il maggior numero di processi
    possibile negli stati running/ready
  – Grado di multiprogrammazione: numero di processi
    eseguibili (running + ready)
  – Obiettivo: mantenere il più alto possibile il grado di
    multiprogrammazione

                                                             24
Swapping
• Per superare il limite imposto dal vincolo di
  memoria fisica disponibile, si introduce il
  concetto di swapping nel modello
• Due stati aggiuntivi:
  – Blocked-Suspended: il processo è bloccato (in
    attesa di un evento) e la memoria che occupa è
    stata liberata con un trasferimento dati su disco
    (swap out)
  – Ready-Suspended: il processo non è bloccato
    (nessun evento, oppure attesa terminata) e
    torna ad occupare memoria centrale con un
    trasferimento dati da disco (swap in)

                                                        25
Modello a cinque stati con swapping
               ammesso                        uscita
   new                                                       exit

                             interruzione
Ripristino in
memoria (swap in)

                     ready                  running

  completamento I/O
                                                  attesa I/O
                              dispatching
  verifica evento
                                                  attesa evento
   verifica evento
                                blocked
                                              Rimozione dalla
        ready                                 memoria (swap out)
      suspended                   blocked
                                 suspended
          verifica evento
                                                                    26
Modello a cinque stati con swapping
Diagramma di accodamento
(swapping)

                Processi parzialmente
     swap in                             swap out
                 eseguiti e sottoposti
                       a swap


                                           CPU
   Coda processi pronti



   I/O          Coda I/O          Richiesta I/O




                                                    27
Cause di sospensione di un processo
• Swapping
  – Liberazione porzioni di memoria da parte del SO
  – Obiettivo: aumento grado multiprogrammazione
• Richiesta
  – Da parte di un utente interattivo
  – Da parte di un altro processo (coordinamento
    attività)
• Temporizzazione
  – Gestione attività periodiche (monitoraggio)
• Recupero
  – Ripristino da situazioni erronee/incoerenti

                                                      28
Gestione processi:
              strutture di controllo
• Per gestire l'esecuzione dei processi, il SO
  mantiene informazioni sui processi stessi e
  sulle risorse utilizzate               Immagine P            1
 Risorse          Strutture dati
di sistema         di controllo
                                        Tabella di
 Memoria                   Tabella di   memoria
                           memoria
Dispositivi ...
                                        Tabella di
   File                                    ...
                                        memoria
                                                     Immagine Pn
                  Tabella dei
 Processi
                   processi
                      P1


                      Pn                                           29
Tabelle di memoria
• Contengono informazioni su:
  – Allocazione memoria principale ai processi
  – Allocazione memoria secondaria ai processi
  – Modalità di protezione dei singoli segmenti di
    memoria (read-only, read-write, execute)
  – Informazioni necessarie a gestire la memoria
    virtuale (nei sistemi in cui essa è supportata)
• Esempi:
  – Pagine di memoria accessaibili al processo
  – File aperti (e relativi descrittori)



                                                      30
Immagine di un processo
• L'immagine di un processo rappresenta
  l'insieme di informazioni necessarie per poter
  coordinare l'esecuzione di più processi
  – Codice macchina del programma di cui il
    processo risulta essere una istanza,
    memorizzati in aree leggibili ed eseguibili
  – Dati utilizzati dal programma, memorizzati in
    aree di memoria leggibili e scrivibili
  – Stack, utilizzato per gestire le chiamate di
    funzione
  – Process Control Block (PCB), una collezione di
    attributi necessari al SO per controllare
    l'esecuzione del processo stesso
                                                     31
Immagine di un processo
                                  Indirizzi alti
                      Stack
Stack segment      programma
                                  Lo stack cresce verso il basso

                “Buco” nello spazio
                 di indirizzamento


                      Heap
                                  L'heap cresce verso alto
                     (malloc)

Data segments                     Variabili non inizializzate
                      BSS         (vengono impostate a 0)

                                  Variabili globali inizializzate
                      Data
                                  Indirizzi bassi
                    Codice
Text segment       eseguibile
                                                                    32
Process Control Block
• Il SO associa a ciascun processo un
  descrittore di processo (Process Control
  Block)
  – Identificatori: del processo, di altri processi
    relazionati
  – Stato del processo: running, ready, blocked,...
  – Privilegi: per accesso a servizi e risorse
  – Registri: salvataggio registri della CPU (registri
    interni, program counter, stack pointer)
  – Informazioni di scheduling: tutto ciò che il
    sistema necessita di sapere per arbitrare la
    assegnazione del processore ai processi in
    stato ready (CPU scheduling)
  – informazioni di stato: evento atteso                 33
Process Control Block
Process Control Block
        puntatore                     stato del processo
             identificatore di processo (PID)
                contatore di programma

                           registri

                contatore di programma
                    elenco dei file aperti


                              ...


                                                           34
Scheduling dei processi
• Obiettivo della multiprogrammazione:
  – massimizzare l'utilizzo della CPU tramite
    l'esecuzione contemporanea di più processi
  – contemporaneo è da intendersi nel senso di
    avanzamento alternato, non nel senso di
    esecuzione contemporanea sulla stessa CPU
• Obiettivo del time sharing:
  – Commutare l'uso della CPU fra processi così
    velocemente da facilitare l'interattività con gli
    utenti




                                                        35
Scheduling dei processi
• In un sistema con m CPU, al più m processi
  possono essere in esecuzione alla volta
  – Che succede se ho più di m processi in
    memoria?
• L'esecuzione dei processi deve essere
  schedulata sulle risorse di elaborazione a
  disposizione
  – Chi decide quale processo deve essere
    ripristinato in esecuzione su quale CPU?
• Scheduler



                                               36
Code di scheduling
• Per coordinare il passaggio di stato fra
  processi, il SO fa uso massiccio di code di
  scheduling
• Code utilizzate:
  – Coda dei processi
     ♦ contiene tutti i processi del sistema
  – Coda dei processi pronti (ready queue)
     ♦ contiene tutti i processi in stato di pronto
  – Coda di dispositivo
     ♦ contiene tutti i processi in attesa per l'uso del
       dispositivo
     ♦ una coda distinta per dispositivo

                                                           37
Code di scheduling
                             PCB7          PCB2
coda dei   Primo elemento
processi
           Ultimo elemento   registri      registri
 pronti
                                ...            ...
 coda      Primo elemento
 unità
           Ultimo elemento
CDROM
                             PCB3          PCB14      PCB6
coda       Primo elemento
unità
           Ultimo elemento   registri      registri   registri
dischi
                                ...            ...       ...


  coda                                  PCB3
          Primo elemento
terminale
          Ultimo elemento    registri
    0
                                ...                              38
Scheduler
• Componente del SO che seleziona i processi
  dalle code
• Due tipi di scheduling:
  – Job scheduling
  – CPU scheduling




                                               39
Job scheduling
• Utilizzato nei sistemi batch
• L'insieme dei job da eseguire viene riversato
  su disco (spooling)
• Lo scheduler dei job sceglie il prossimo job da
  mandare in esecuzione
• Obiettivo: mantenere costante il numero di job
  in memoria (grado di multiprogrammazione)
• Invocato con frequenza bassa
• Bilancio fra processi I/O-bound e CPU-bound
• Job scheduling non è integrato nel kernel dei
  moderni sistemi UNIX
  – Implementazioni applicative (stampa, posta)
                                                    40
CPU scheduling
• Utilizzato nei sistemi time sharing
• Seleziona il prossimo processo dalla coda di
  pronto per l'esecuzione
• Obiettivi:
  – Massimizzare numero di processi eseguiti
    nell'unità di tempo (throughput)
  – Minimizzare la latenza di processo
  – Dare priorità ai processi più importanti
• Invocato con frequenza elevata (ogni 100
  msec)



                                                 41
Context switch
• Quando la CPU interrompe l'esecuzione di un
  processo per passare ad un altro:
  1.Occorre salvare lo stato attuale del vecchio
    processo
  2.Occorre ripristinare lo stato precedente del
    nuovo processo
• Le operazioni delineate in 1. e 2. prendono il
  nome di context switch
• Contesto di un processo: contenuto del
  descrittore di processo
  – Registri, stato, info gestione memoria
• Durata context switch: 1usec – 1msec
  – Dipende fortemente dalla architettura
                                                   42
Cambio modalità esecuzione
• I processi si alternano anche in diverse
  modalità di esecuzione, caratterizzate da livelli
  di privilegio diversi
  – User mode, Kernel mode
• User mode: esecuzione applicativi
• Kernel mode: esecuzione servizi del kernel
  – Accesso a privilegi di livello superiore
  – Possibilità di esecuzione di istruzioni non
    ammesse in user mode
  – Caratterizzato (riconoscibile) da un settaggio di
    un bit di stato del processore


                                                        43
Modalità esecuzione e context switch
   Processo                       Processo

     syscall()


            Meccanismo per il                   User mode
            cambio di modo                     Kernel mode

   service_call()                  Scheduler
                    Invocazione
                    scheduler
          Chiamata
          bloccante

                                                 Hardware




                                                             44
Modi di esecuzione e context switch
• Cause di context switch
  – Interruzione di clock (time sharing), viene
    attivato lo scheduler per cedere il controllo ad
    un altro processo
  – Interruzione di I/O, con possibile riattivazione di
    un processo a più alta priorità
  – Nei sistemi basati su memoria virtuale, prelievo
    di una pagina di memoria da swap (page fault)
• Cause di cambio modo di esecuzione
  – Attivazione di una Interrupt Service Routine
  – Context switch
  – Chiamata di sistema

                                                          45
Context switch
Processo P0       Sistema operativo         Processo P1


                Salva lo stato in PCB0


              Ripristina lo stato da PCB1



                Salva lo stato in PCB1


              Ripristina lo stato da PCB1


                                                          46
Context switch
Processo P0         Sistema operativo        Processo P1
    Interruzione o syscall bloccante

                 Salva lo stato in PCB0


               Ripristina lo stato da PCB1



                 Salva lo stato in PCB1


               Ripristina lo stato da PCB1


                                                           47
Context switch
Processo P0         Sistema operativo        Processo P1
    Interruzione o syscall bloccante

                 Salva lo stato in PCB0


               Ripristina lo stato da PCB1



                 Salva lo stato in PCB1


               Ripristina lo stato da PCB1


                                                           48
Context switch
Processo P0         Sistema operativo        Processo P1
    Interruzione o syscall bloccante

                 Salva lo stato in PCB0


               Ripristina lo stato da PCB1



                 Salva lo stato in PCB1


               Ripristina lo stato da PCB1


                                                           49
Context switch
Processo P0         Sistema operativo        Processo P1
    Interruzione o syscall bloccante

                 Salva lo stato in PCB0


               Ripristina lo stato da PCB1

          Interruzione o syscall bloccante

                 Salva lo stato in PCB1


               Ripristina lo stato da PCB1


                                                           50
Context switch
Processo P0         Sistema operativo         Processo P1
    Interruzione o syscall bloccante

                 Salva lo stato in PCB0


               Ripristina lo stato da PCB1

          Interruzione o syscall bloccante

                 Salva lo stato in PCB1


               Ripristina lo stato da PCB0


                                                            51
Modello processi UNIX
• Esecuzione dei processi in user mode (codice
  applicativo) e kernel mode (servizi)
  – Lo stato running deve essere suddiviso in due
    stati: user running e kernel running
• Lo scheduler implementa un meccanismo di
  prelazione per supportare la priorità
  – Un processo che ritorna da una chiamata di
    sistema (lasciando il kernel mode) può essere
    messo in stato ready e lasciare il passo ad un
    processo con più alta priorità
  – Nuovo stato preempted che modella la
    prelazione

                                                     52
Modello processi UNIX
• Modello gerarchico di processi: un processo
  padre genera processi figli
• PID: process identifier (identifica il processo)
• Processo padre coordinatore aspetta che i
  processi figli lavoratori terminino l'esecuzione
• Se al momento dell'uscita un processo figlio
  non ha un processo padre che aspetta il suo
  completamento, entra nello stato zombie
  – Processo figlio morto
  – Ha un PCB nella tabella dei processi, in modo
    tale che il processo padre possa leggere il suo
    stato di uscita
  – Distinzione stati exited e zombie
                                                      53
Modello processi UNIX

                   preempted
                                             new
  User
 mode
running

                                                Ready
                                   ready
                                              Swapped out
            Kernel
            mode
           running


                                                Sleeping
                               Sleeping in
                                               Swapped out
                                memory



exited    zombie

                                                             54
Immagine di un processo
Testo
Dati
                                   Contesto utente
Stack utente
Memoria condivisa
Program counter
Registro di stato del processore
                                   Contesto registri
Stack pointer
Registri generali
Entry nella tabella dei processi
U area (area utente)
                                   Contesto sistema
Tabella indirizzamento (memoria
virtuale)
Stack del kernel mode


                                                       55
Entry della tabella dei processi
Stato del processo
Puntatori alla U area
Dimensioni del processo
Identificatori d’utente (reale ed effettivo)
Identificatori di processi (pid, id del genitore)
Descrittore degli eventi (valido in stato sleeping)
Priorita’
Segnali (mandati al processi ma non ancora gestiti)
Timer (monitoring)
P_link (puntatore per la lista ready)
Stato della memoria (swap in/out)

                                                      56
User Area (U area)
Puntatore alla entry della tabella dei processi
Dimensioni del processo
Identificatori d’utente (effettivo)
Array per i gestori di segnali
Terminale
Campo di errore
Parametri di I/O (es. indirizzi dei buffer)
Timer (monitoring in modalita’ utente)
Valore di ritorno di system calls
Tabella dei descrittori di file

                                                  57
Modello di avvio processi UNIX
 Kernel           init
                          getty   login     shell
(PID=0)         (PID=1)


                          getty   login     shell
          Legge
          /etc/inittab

                          getty   login     shell
• Shell tipiche:
  – Bourne Again SHell
  – Bourne                  Legge
  –C                        /etc/passwd
  – Korn
Comandi di shell: nome-comando [ arg1, ..., argn ]
                                                     58
Creazione di un processo UNIX
• Durante la propria esecuzione, un processo
  può creare altri processi (fork)
  – Processo creante: processo padre
  – Processo creato: processo figlio
• Ciascun processo creato, a sua volta, può
  creare altri processi
• Organizzazione dei processi ad albero
• Un processo può ereditare dal padre:
  – Tutte le risorse
  – Un sottoinsieme delle risorse


                                               59
Albero di processi UNIX
                 kernel



page daemon     swapper     init



              utente 1    utente 2   utente 3




                                                60
Creazione di un processo UNIX
• Esecuzione del processo padre dopo aver
  creato un processo figlio:
  – Il processo padre continua l'esecuzione in
    maniera concorrente con i propri figli
  – Il processo padre attende che alcuni o tutti i
    suoi figli terminino l'esecuzione
• Esecuzione del processo figlio:
  – Dallo stesso punto in cui si era interrotto il
    padre prima di invocare la fork()
• Spazio di indirizzamento del processo figlio:
  – Il processo figlio è un duplicato del padre
  – Il processo figlio carica un programma

                                                     61
System call fork()
• In UNIX, ogni processo è caratterizzato da un
  numero identificatore univoco (PID)
• Un nuovo processo viene creato per mezzo
  della syscall fork()
• La syscall fork:
  – Duplica il descrittore del processo padre nel
    descrittore del processo figlio
  – Genera un nuovo PID
  – Inserisce il descrittore di processo del figlio
    nella coda di pronto
• Valore di ritorno della fork:
  – PID nel processo padre
  – 0 nel processo figlio
                                                      62
System call fork()
• Signature: pid_t fork(void)
  – Descrizione: crea un esatto duplicato del
    processo chiamante
  – Argomenti: nessuno
  – Valore di ritorno:
     ♦ Processo padre -> PID del figlio
     ♦ Processo figlio -> 0
     ♦ -1 in caso di errore
    Processo padre        Processo figlio
        stack                 stack
                                        Entrambi i processi
                 fork()                 ripartono dall'istruzione
                                        successiva alla fork()
        heap                   heap
        dati                   dati     nel testo
        testo                  testo
                                                                    63
Utilizzi del meccanismo di forking
• Creazione di                                              shell
  comandi a catena                                fork()               fork()
  (pipeline)                                               pipe()
                                      exec()                                    exec()
                                                   find                wc
  find . -name '*.c' -print | wc -l
                                                                                output


• Gestione di servizi                                       Server
                                      richieste
                                                           process
  (request serving)                               fork()               fork()
   – Web server                                 Child                 Child
                                               process               process
   – FTP server
   – “XYZ” server
                                               risposta              risposta




                                                                                         64
Cattivi utilizzi del forking: fork bomb
• Una fork bomb è un particolare tipo di
  processo che non fa altro che riprodurre
  processi figli, I quali a loro volta si riproducono
• Meccanismo rozzo ma efficace di negazione
  dei servizi (Denial of Service, DoS)
  – Può essere accidentale
  – Di solito, è intenzionale (malizioso)
• Una fork bomb fa esplicite assunzioni sul
  comportamento del SO:
  – Tabella dei processi di dimensioni limitate
    (viene saturata, non si può più eseguire niente)
  – Ciascun processo richiede risorse di calcolo (il
    sistema rallenta considerevolmente)
                                                        65
Cattivi utilizzi del forking: fork bomb
                                 bomb



                                 ...
                         bomb            bomb



                                 ...
                  bomb                          bomb



                  ...                           ...
     bomb                 bomb          bomb                 bomb


            ...                          ...
                           ...                         ...




                                                                    66
Scheletro di una fork bomb
• Il tipico scheletro di una fork bomb è un ciclo
  while che, per sempre, effettua una fork()
• Per peggiorare le cose, si può anche allocare
  della memoria
  – Memory leak: alloco memoria senza liberarla
  – Porta molto rapidamente il sistema in swap
  – Nei sistemi con Copy On Write, occorre scrivere
    nella memoria per creare le pagine copia
  while ( 1 ) {
    x=malloc(1048576); /* 1MB */
    *x = 0;     /* forza il Copy On Write */
    fork();
  }
                                                      67
Prevenzione delle fork bomb
• Soluzioni comuni:
  – Il SO imposta un limite al numero di processi
    generati da un utente (ulimit)
  – Uccisione di tutti i processi (tranne kill ed init)
    kill -9 -1
  – Modifiche al SO per impedire la diffusione del
    bombing




                                                          68
vfork()
• Variante veloce della fork(), pensata per I
  processi figli che caricano immediatamente
  altre immagini
  – Scenario ideale: shell (processo padre che
    forka processi figli eseguenti comandi)
• Il kernel non copia la tabella di memoria del
  padre nelle tabelle di memoria del figlio, ma le
  fa condividere finché il processo figlio:
  – non carica una immagine (exec())
  – non esce (_exit())
• Nel frattempo, il processo padre si blocca
• Non esiste semantica Copy-On-Write: il figlio
  può cambiare i valori delle variabili del padre
                                                     69
Gestione dei Process IDentifier
• Signature: pid_t getpid(void)
  – Descrizione: ritorna il PID del processo
    chiamante
  – Argomenti: nessuno
  – Valore di ritorno: il PID del processo chiamante
• Signature: pid_t getppid(void)
  – Descrizione: ritorna il PID del processo padre di
    quello chiamante
  – Argomenti: nessuno
  – Valore di ritorno: il PID del processo padre del
    processo chiamante


                                                        70
Identificazione di processi
• Come si possono trovare I PID dei processi in
  maniera estremamente rapida?
• Comando pgrep
  – pgrep “stringa”
  – Restituisce una lista di PID associati a processi
    il cui nome contiene “stringa”
  – pgrep init -> 1




                                                        71
Terminazione di un processo
• La syscall exit() viene utilizzata per terminare il
  programma con un codice di uscita
• Alcune risorse allocate dal processo vengono
  liberate dal SO
  – Gli stream aperti vengono svuotati (flush)
  – I file temporanei vengono rimossi
  – Viene chiamata la funzione di chiusura _exit()
• Se un processo genitore termina, tutti i suoi
  figli si chiamano orfani
  – Gli orfani diventano immediatamente figli del
    processo init (che ha PID=1)


                                                        72
Terminazione di un processo
• Variante: _exit()
• Il processo esce con un codice di uscita
• Non svuota gli stream aperti, non cancella i file
  temporanei
• Chiude i descrittori di file aperti
• Quando si usa la _exit()?
  – Processo figlio creato con vfork()
  – Processo figlio che non ha caricato una
    immagine con exec()
• Si impedisce che il figlio possa modificare le
  risorse usate dal padre

                                                      73
Terminazione di un processo
• Signature: void exit(int status)
  – Descrizione: termina l'esecuzione del processo
    e fornisce un codice di uscita al processo
    invocante
  – Argomenti: il codice di uscita
     ♦ EXIT_SUCCESS (0): tutto OK
     ♦ EXIT_FAILURE (1): errore
  – Valore di ritorno: nessuno
• Si possono usare anche altri codici di uscita >
  0 per discriminare diverse cause di errore



                                                     74
Segnali
• Meccanismo di notifica asincrona di eventi ad
  un processo
  – Asincrona: non legata ad eventi interni al kernel
• Meccanismo primitivo di Inter Process
  Communication (IPC)
• Un segnale è una interruzione software
  (eccezione), inviata ad un processo
  – Inviata tramite tastiera (CTRL-C da terminale)
  – Inviata tramite il comando kill
  – Inviata dal kernel (SIGSEGV)



                                                        75
Ciclo di vita di un segnale
• I segnali UNIX hanno un ciclo di vita preciso
• Step 1: un processo (o il kernel) genera un
  segnale (raise, send, generate)
• Step 2: il kernel conserva il segnale fino a
  quando non è in grado di consegnarlo
• Step 3: il kernel consegna il segnale al
  processo destinatario
• Step 4: il kernel esegue una azione legata al
  segnale




                                                  76
Azioni legate ad un segnale
• Quali sono le possibili azioni?
• Ignorare il segnale (ignore):
  – Non viene intrapresa alcuna azione
  – Due segnali (KILL, STOP) non possono essere
    ignorati
• Gestire il segnale (catch and handle):
  – Sospensione dell'esecuzione del processo
  – Salto ad una funzione (handler) definita nel
    codice del programma ed assegnata al segnale
  – Ripristino dell'esecuzione del processo
• Eseguire una azione di default (default action):
  – Il kernel esegue una azione preconfigurata (ad
    es., uccisione del processo)                     77
Identificatori di segnale
• I segnali sono identificati in maniera univoca
  da numeri interi positivi, a partire dal numero 1
• A ciascun numero è associato una costante
  simbolica avente prefisso SIG
• La definizione dell'intero insieme dei segnali è
  definita nel file include <bits/signum.h>
• Per vedere la lista, si può utilizzare il comando
  di gestione dei segnali kill:
  kill -l




                                                      78
Alcuni segnali comuni
• SIGKILL (9):
  – Termina istantaneamente il processo, senza
    possibilità di effettuare operazioni di cleanup
  – Non può essere gestito con un handler
• SIGTERM (15):
  – termina istantaneamente il processo, con
    possibilità di registrare un handler per
    effettuare operazioni di cleanup
• SIGINT (2):
  – Segnale di interruzione, inviato al processo
    collegato ad un terminale, in seguito a CTRL-C
  – Termina il processo
                                                      79
Alcuni segnali comuni
• SIGSEGV (11):
  – Il kernel termina istantaneamente il processo, in
    seguito ad un accesso invalido alla memoria
  – Non può essere gestito con un handler
• SIGCHLD (15):
  – Segnale inviato al processo padre quando un
    processo figlio termina l'esecuzione
• SIGUSR1 (10), SIGUSR2 (12):
   – Segnali configurabili tramite handler opportuni
   – Azione di default: terminano il processo
• E tanti, tanti altri...

                                                        80
Invio di segnali: il comando kill
• Il comando kill permette di inviare segnali ai
  processi
   – kill -”id segnale” “pid processo
   – kill -9 8732
   – Occorre avere I privilegi opportuni!
• Variante pkill: identifica in maniera simbolica i
  segnali ed i processi
   – pkill -KILL program
• E da programma?
   – Si utilizza la syscall kill()



                                                      81
Syscall kill()
• Signature: int kill(pid_t pid, int sig)
   – Descrizione: invia il segnale identificato da sig
     al processo identificato da pid
   – Argomenti:
      ♦ IlPID del processo destinatario del segnale
      ♦ L'identificatore del segnale da inviare

   – Valore di ritorno:
      ♦0  -> tutto OK
      ♦ -1: si è verificato un errore




                                                         82
Ricezione di segnali
• Si utilizza la syscall signal(), che permette di
  associare ad un segnale una ben specifica
  funzione handler
• Che prototipo deve avere la funzione handler?
  – void sig_handler(int signo)
• Il file include <signal.h> definisce il tipo di dato
  sighandler_t come puntatore ad una funzione
  che vuole un intero e non ritorna niente (void)
  – typedef void (*sighandler_t) (int);




                                                         83
Syscall signal()
• Signature: sighandler_t signal(int signo,
  sighandler_t handler)
  – Descrizione: sostituisce l'azione corrente del
    segnale con l'azione definita dalla funzione
    handler
  – Argomenti:
     ♦ L'identificatore
                      del segnale da gestire
     ♦ Un puntatore alla funzione handler
        – SIG_DFL: azione di default
        – SIG_IGN: ignorare il segnale
        – Puntatore ad una funzione effettiva
  – Valore di ritorno:
     ♦ Ilpuntatore alla precedente funzione handler
     ♦ SIG_ERR in caso di errore                      84
Handler di segnali: alcune note
• Quando il kernel consegna un segnale, il
  processo può eseguire una qualunque
  porzione di codice
  – L'handler non può sapere quale
• E' importante che l'handler non esegua codice
  “troppo complicato”
  – Tipicamente, imposta dei flag “volatile”, libera
    memoria, esce, non fa molto altro
• L'handler deve modificare variabili che il
  processo non tocca MAI
• I segnali possono essere rientranti
  – le syscall utilizzate all'interno dell'handler pure
  – man 7 signal                                          85
Sincronizzazione processo padre-figlio
• Il processo padre può decidere di aspettare il
  termine dell'esecuzione del processo figlio, per
  mezzo della syscall wait()
• La syscall wait rimuove il descrittore del
  processo padre dalla coda di pronto fino a che
  il processo figlio non termina l'esecuzione
• Quando il processo figlio termina l'esecuzione,
   ritorna un codice di uscita (exit status) al SO
  – =0: tutto OK (EXIT_SUCCESS)
  – =1: errore (EXIT_FAILURE)
• Il SO consegna il codice di uscita alla syscall
  wait
                                                     86
Scenario wait() tempestiva
• Il processo padre crea                              Tabella
                                     padre           processi
  un figlio con la fork()                     PID
                            fork()
                                                    Running
• Entrambi i processi                   PID
  eseguono                                          Running
                            figlio
  concorrentemente




                                                                87
Scenario wait() tempestiva
• Il processo padre                                Tabella
                                        wait()    processi
  invoca la wait() prima
                                padre
  la morte del figlio,                           Blocked
  tempestivamente                                Running
                           figlio
• Il processo padre
  viene bloccato in
  attesa che il figlio
  termini la sua
  esecuzione




                                                             88
Scenario wait() tempestiva
• Ad un certo punto, il                          Tabella
                                       padre    processi
  processo figlio
  termina la sua                               Running

                              X
  esecuzione                                   Zombie
                              figlio

• Il kernel imposta lo
  stato del figlio a
  Zombie
  – Processo figlio morto a
    tutti gli effetti
  – Il PCB è ancora
    presente nella tabella
    dei processi
  – PCB usato per fornire
    al padre il valore di
    uscita                                                 89
Scenario wait() tempestiva
• Il kernel imposta a                            Tabella
                                                processi
  pronto il processo                  wait()
                             padre
  padre, dal momento                           Running
                                      PID,
  che l'evento atteso si                       Running
                                     codice
  è verificato                       uscita
• Il kernel invia un
  segnale SIGCHLD al
  padre (di solito
  ignorato)
• Il processo padre
  ritorna ad eseguire
  dopo la wait()
• Viene letto il codice di
  uscita del figlio                                        90
Scenario wait() tardiva
• Il processo padre crea                              Tabella
                                     padre           processi
  un figlio con la fork()                     PID
                            fork()
                                                    Running
• Entrambi i processi                   PID
  eseguono                                          Running
                            figlio
  concorrentemente




                                                                91
Scenario wait() tardiva
• Ad un certo punto, il                          Tabella
                                       padre    processi
  processo figlio
  termina la sua                               Running

                              X
  esecuzione                                   Zombie
                              figlio

• Il kernel imposta lo
  stato del figlio a
  Zombie
  – Processo figlio morto a
    tutti gli effetti
  – Il PCB è ancora
    presente nella tabella
    dei processi
  – PCB usato per fornire
    al padre il valore di
    uscita                                                 92
Scenario wait() tardiva
• Il processo padre                           Tabella
                                   wait()    processi
  invoca la wait() dopo
                           padre
  la morte del figlio,                      Running
                                    PID,
                                               X
  tardivamente                              Zombie
                                   codice
                                   uscita
• Il kernel invia un
  segnale SIGCHLD al
  padre (di solito
  ignorato)
• Viene usato il PCB del
  figlio per comunicare
  lo stato di uscita al
  padre
• Viene eliminato il PCB
  del figlio                                            93
Scenario wait() mai invocata
• Il processo padre crea                              Tabella
                                     padre           processi
  un figlio con la fork()                     PID
                            fork()
                                                    Running
• Entrambi i processi                   PID
  eseguono                                          Running
                            figlio
  concorrentemente




                                                                94
Scenario wait() mai invocata
• Ad un certo punto, il                          Tabella
                                    padre       processi
  processo figlio
  termina la sua                               Running

                              X
  esecuzione                                   Zombie
                           figlio

• Il kernel invia un
  segnale SIGCHLD al
                        • Stato Zombie
  padre (di solito
                          – Processo figlio morto a
  ignorato)
                             tutti gli effetti
• Il kernel imposta lo    – Il PCB è ancora
  stato del figlio a         presente nella tabella
  Zombie                     dei processi
                              – PCB usato per fornire
                                al padre il valore di
                                uscita
                                                           95
Scenario wait() mai invocata
• Finché il padre                     Tabella


                           X
                                     processi
  esegue, esisterà
                           padre
                                      X
  sempre un PCB del                Exiting

                                      X
  figlio in stato Zombie           Zombie

• Quando il padre
  termina l'esecuzione,
  vengono ripuliti
  entrambi i PCB




                                                96
System call wait()
• Signature: pid_t wait(int *status)
  – Descrizione: sospende l'esecuzione del
    processo chiamante fino a quando uno dei suoi
    processi figli termina
  – Ingresso: puntatore ad un intero utilizzato per
    memorizzare lo “stato” del processo
  – Ritorno:
     ♦ Il PID del processo figlio terminato
     ♦ -1 in caso di errore




                                                      97
System call wait()
• Lo stato del processo può essere letto tramite
  delle macro opportune
  – WIFEXITED(status): restituisce 1 se il figlio è
    terminato normalmente (exit()), 0 altrimenti
  – WEXITSTATUS(status): restituisce il codice di
    uscita del processo figlio (gli 8 bit meno significativi
    di status: status & 255)
  – WIFSIGNALED(status): restituisce 1 se il figlio è
    stato terminato tramite un segnale, 0 altrimenti
  – WIFSTOPPED(status): restituisce 1 se il figlio è
    stato interrotto (SIGSTOP), 0 altrimenti
  – WIFCONTINUED(status): restituisce 1 se il figlio è
    stato ripristinato (SIGCONT), 0 altrimenti
  – ... e tante altre (man wait)
                                                               98
System call waitpid()
• Signature: pid_t waitpid(pid_t pid, int *status,
  int options)
  – Descrizione: sospende l'esecuzione del
    processo chiamante fino a quando uno dei suoi
    processi figli cambia stato
  – Ingresso:
     ♦ ilPID del processo (o dell'insieme di processi) da
       aspettare
     ♦ puntatore ad un intero utilizzato per memorizzare
       lo “stato” del processo
     ♦ maschera di bit contenente le opzioni di uso

  – Ritorno:
     ♦ Il PID del processo figlio terminato
     ♦ -1 in caso di errore (errno=ECHILD)                  99
System call waitpid()
• Il primo argomento pid può assumere i
  seguenti valori:
  – -1: aspetta un qualunque processo figlio
  – 0: aspetta un qualunque processo figlio con
    group ID pari a quello del processo chiamante
  – >0: aspetta un qualunque processo figlio con
    PID = pid
• Le opzioni sono le seguenti:
  – WNOHANG: ritorna immediatamente se nessun
    figlio è uscito (non aspetta)
      ♦ torna 0 se il padre ha figli, -1 altrimenti
  – WUNTRACED: considera come cambio di stato
    anche l'interruzione (SIGSTOP)
                                                      100
Caricamento di immagini
• UNIX mette a disposizione una famiglia di
  funzioni (exec()) per sostituire l'immagine di un
  processo padre con quella di un eseguibile
• La sostituzione è efficiente
  – Non si copia l'intero contenuto della memoria
    secondaria in memoria
  – Si associano blocchi di memoria principale a
    blocchi di memoria secondaria (memory
    mapping)
  – Si carica il blocco in memoria centrale solo
    quando viene utilizzato dal processore


                                                      101
Caricamento di immagini
Spazio indirizzamento   Memoria secondaria
  processo (RAM)           (periferica)

    Pagina 1

    Pagina 2

        ...

    Pagina n              Blocco
                             1      Blocco
                                       2

                           Blocco
                              n




                                             102
Caricamento di immagini
Spazio indirizzamento                   Memoria secondaria
  processo (RAM)                           (periferica)

    Blocco 1

    Pagina 2

         ...

    Pagina n                                 Blocco
                                                1     Blocco
                                                         2

                                             Blocco
               Sostituzione di codice:          n
               le pagine vengono
   CPU         sostituite quando richieste
               dal processore.


                                                               103
Syscall execl
• Signature: int execl(const char *path, const
  char *arg, ...)
   – Descrizione: carica l'immagine eseguibile del
     programma di nome path, passando i parametri
   – Argomenti:
      ♦ Un puntatore alla stringa contenente il
        percorso assoluto dell'eseguibile
      ♦ Una lista di stringhe (terminata con NULL),
        che saranno assegnate ad argv[0], argv[1], ...
   – Valore di ritorno:
      ♦ -1 in caso di errore
• execl() è una funzione variadica (ammette un
  numero variabile di argomenti)
                                                         104
Famiglia funzioni exec()
• int execlp(const char *file, const char *arg, ...);
• int execle(const char *file, const char *arg, ...,
  char * const envp[]);
• int execv(const char *file, const char *argv[]);
• int execvp(const char *file, const char *argv[]);
• int execle(const char *file, const char *arg[],
  char * const envp[]);




                                                        105
Esecuzione semplificata
• Esiste una procedura estremamente
  semplificata per l'esecuzione di processi
• Se si vuole eseguire un comando secco
  (tipicamente, un comando di shell), senza
  necessità di generare più figli, si può usare la
  chiamata system()
• Cosa fa system()?
• Padre:
  – fork() di un processo figlio
  – wait() per aspettare l'uscita del figlio
• Figlio:
  – execv() di una immagine
                                                     106
Funzione system()
• Signature: int system(const char *command)
  – Descrizione: crea un processo figlio ed esegue
    il comando “/bin/sh -c comando”, dove
    comando è la stringa puntata da command
  – Argomenti:
      ♦ Un puntatore alla stringa contenente il
        comando
      ♦ Valore di ritorno:
      ♦ Il codice di stato della wait()
      ♦ -1 in caso di errore

• Esercizio: implementare la system() usando le
  chiamate fork(), execv(), waitpid()
                                                     107
Una piccola avvertenza
• Durante l'esecuzione del comando tramite
  system, nel processo figlio
  – il segnale SIGCHLD è bloccato (sigprocmask)
  – i segnali SIGINT e SIGQUIT sono ignorati
• Se il programma è lanciato da terminale, un
  CTRL-C viene propagato a padre e figlio
  – Ma non sempre il programma è lanciato da
    terminale...
• Se la funzione system() è invocata all'interno di
  un ciclo, bisogna esplicitamente controllare lo
  stato di uscita del figlio


                                                      108
Utenti e gruppi: modello di protezione
• Il modello UNIX prevede l'attribuzione di
  processi e file ad utenti e gruppi di lavoro
• Utente:
  – Astrazione di una singola persona
  – Può lanciare processi e gestire file
  – Identificato da uno User Id (UID), numero intero
    non negativo
  – E' associato ad uno username e ad una
    password per la verifica delle credenziali
  – Database utenti memorizzato in /etc/passwd
  – Un utente (superutente, root) ha pieni poteri di
    accesso alle risorse del sistema (processi, file)
                                                        109
Utenti e gruppi: modello di protezione
• Il modello UNIX prevede l'attribuzione di
  processi e file ad utenti e gruppi di lavoro
• Gruppo (di lavoro):
  – Astrazione di un gruppo di persone che
    lavorano per uno stesso obiettivo
  – Ciascun utente può far parte di più gruppi, ma
    ne usa uno alla volta (gruppo primario)
  – Possono condividere accessi a file
  – Identificato da un Group Id (GID), numero intero
    non negativo
  – E' associato ad un groupname e ad una
    password per la verifica delle credenziali
  – Database utenti memorizzato in /etc/group
                                                       110
Utenti e gruppi: permessi dei file
• Come impatta il modello di protezione sui file?
• Semplice schema a permessi
• Tre distinte categorie di utenti:
  – User: UID dell'utente creatore di un file
  – Group: GID primario dell'utente al momento
    della creazione del file
  – Others: il resto del mondo
• Tre distinte categorie di azioni su file:
  – Read: è possibile leggere da file
  – Write: è possibile scrivere su file
  – eXecute: è possibile eseguire il file

                                                    111
Utenti e gruppi: permessi dei file
• A ciascun file è associata una maschera di bit
  contenente le azioni permesse (r,w,x) per
  ciascuna tipologia di utenti (u,g,o)
• La maschera di bit memorizza in maniera
  compatta chi può accedere come al file
• Diversi tipi di rappresentazione:
  – Stringa: rwxrwxr-x
  – Ottale: 775
  – Azione: ugo+rwx, o-w




                                                   112
Utenti e gruppi: diritti dei processi
• Come impatta il modello di protezione sui
  processi in esecuzione sulla macchina?
• In un sistema UNIX, i diritti di un processo
  coincidono molto spesso con i privilegi di
  accesso ai file
  – Filosofia UNIX: tutto ciò che si esegue è un
    processo, tutto ciò che si rappresenta è un file
• Gli UID e GID di un processo sono quelli
  utilizzati per il confronto con la maschera di bit
  dei file
• Ma come fa un processo ad essere associato
  ad un UID e ad un GID?

                                                       113
Utenti e gruppi: diritti dei processi
• Le cose, ovviamente, non sono così semplici
• Un processo UNIX si porta appresso quattro (!)
  UID e quattro GID diversi per regolare i diritti di
  acceso ai file da parte di un processo
  –   Filesystem User ID
  –   Real User ID
  –   Effective User ID
  –   Saved User ID
• La descrizione seguente vale non solo per gli
  UID, ma anche per i GID!


                                                        114
Utenti e gruppi: Filesystem User ID
• Il Filesystem User ID (UID) è lo UID associato al
  file su disco
• Dichiara solamente chi ha scritto
  originariamente il file su disco, nient'altro!
  – beh, dichiara anche I permessi di accesso...
  – ... ma nient'altro che riguardi l'esecuzione dei
    processi!




                                                       115
Utenti e gruppi: Real User ID
• Il Real User ID (UID) è lo UID dell'utente che ha
  eseguito il processo
• Il Real User ID può essere (e solitamente è)
  diverso dal Filesystem User ID
  – Filesystem: chi ha scritto il file su disco
  – Real: chi lo sta eseguendo ora
• Il Real User ID di un processo viene impostato
  a quello del suo padre
  – Shell: imposta il Real User ID a quello
    dell'utente che la sta eseguendo
  – Tutti i comandi (figli) eseguono con quell'UID
• Il superutente può impostare il Real User ID a
  qualunque valore, gli utenti normali no             116
Utenti e gruppi: Effective User ID
• L'Effective User ID (EUID) è lo UID effettivo con
  cui il processo sta eseguendo
• Tutti i controlli di accesso (a file) avvengono
  tramite l'EUID
• L'EUID viene ereditato dal processo padre
• Un momento: ma non c'era già il Real User ID?
• Sì, ed in effetti, solitamente, Real User ID ed
  Effective User ID coincidono
• E allora a che serve differenziare in Real User
  ID ed Effective User ID?
   – A fare cose paranormali con i poteri di un
     utente normale
                                                      117
Utenti e gruppi: Effective User ID
• Ciascun file ha, in realtà, svariati altri bit nella
  bitmask dei permessi
• Tali bit sono usati per specificare particolari
  proprietà di un file o di una directory
• Una proprietà particolare è il Set User ID (SUID)
  bit, impostabile alla stregua di un qualunque
  permesso
  – chmod +s nome_file, chmod 4xyz nome_file
• Quando viene avviato un eseguibile con SUID,
  il kernel imposta l'EUID del file al filesystem
  UID
  – Esecuzione con i diritti del creatore, non
    dell'utente! E se il creatore è root...
                                                         118
Utenti e gruppi: Effective User ID
• Gli utenti normali possono impostare il valore
  di EUID al Real UID oppure al Saved UID
  (introdotto a breve)
• Il superutente può impostare l'EUID al valore
  che desidera
• Come trovare gli eseguibili SUID?
  – find / -perm -4000 2>/dev/null
• Esempio: passwd




                                                   119
Utenti e gruppi: Saved User ID
• Il Saved User ID è una copia fedele
  dell'Effective User ID di un processo, effettuata
  nell'istante in cui questo effettua una exec()
• Utilizzato per tenere traccia del vecchio
  Effective User ID prima di eseguire una
  immagine (potenzialmente SUID)
• Il Saved User ID è inizialmente ereditato dal
  processo padre
• Utenti non privilegiati non possono modificare
  il Saved User ID
• Il superutente può impostare il Saved User ID
  ad un qualunque valore
                                                      120
Utenti e gruppi: setuid()
• Signature: int setuid(uid_t uid)
  Signature: int setgid(gid_t gid)
  – Descrizione:
     ♦ Se EUID=0 (root), imposta Real, Effective e
       Saved User Id a uid (qualunque)
     ♦ Se EUID>0 (non root), imposta Effective User
       Id ad uid (uid=Real oppure uid=Saved)
  – Argomenti:
     ♦ Il nuovo User ID (uid)
  – Valore di ritorno:
     ♦ 0: tutto OK
     ♦ -1 in caso di errore

                                                      121
Utenti e gruppi: seteuid()
• Signature: int seteuid(uid_t euid)
  Signature: int setegid(gid_t egid)
  – Descrizione:
     ♦ Se EUID=0 (root), imposta l'Effective User Id a
       euid (qualunque)
     ♦ Se EUID>0 (non root), imposta l'Effective
       User Id ad uid (uid=Real oppure uid=Saved)
         – Comportamento identico a setuid()
  – Argomenti:
     ♦ Il nuovo Effective User ID (euid)
  – Valore di ritorno:
     ♦ 0: tutto OK
     ♦ -1 in caso di errore
                                                         122
Utenti e gruppi: recupero UID
•   Famiglia di funzioni get...id()
•   Non danno mai un errore
•   uid_t getuid(void);
•   uid_t getgid(void);
•   uid_t geteuid(void);
•   uid_t getegid(void);




                                       123
Una piccola applicazione
• Il SO Debian definisce il gruppo games come il
  gruppo dei videogiocatori
   – Tutti gli eseguibili dei videogiochi vengono
     installati nella directory /usr/games
   – Permessi: rwx r-x r-x (755)
   – Utente: root
   – Primary group:
      ♦ root (nel caso in cui non si scrivano file)
      ♦ games, con setgid (nel caso in cui si scrivano
        file)
• In quest'ultimo caso, chiunque esegua un
  videogioco prende il gruppo effettivo games
   – L'user effettivo rimane sempre quello normale
                                                         124
Una piccola applicazione
• L'applicazione videogame scrive, come gruppo
  games:
  – Gli high score (platform, sparatutto)
  – L'output delle partite (giochi da tavolo)
• L'applicazione vorrebbe scrivere gli altri file
  col gruppo primario dell'utente che ha lanciato
  l'eseguibile:
  – Traccie di debug
• Come si ottiene questo?




                                                    125
Una piccola applicazione
• All'inizio del programma, vengono salvati i
  Real ed Effective UID e GID:
  ruid = getuid();
  euid = geteuid();
  rgid = getgid();
  egid = getegid();
• Successivamente, si reimpostano UID e GID in
  modo tale che l'utente possa scrivere file col
  proprio gruppo primario:
  setuid(ruid);
  setgid(rgid);
• Qui, rgid è il GID dell'utente normale; ora sto
  scrivendo I file come utente normale
                                                    126
Una piccola applicazione
• Prima di scrivere gli high score, imposto
  setuid(euid);
  setgid(egid);
• Ora, il GID è di nuovo quello effettivo (games):
  write_high_scores(&players);
• Successivamente, reimposto UID e GID a quelli
  “normali”
  setuid(ruid);
  setgid(rgid);




                                                     127
Job Control
• Task di una shell moderna:
  – Lettura comando da terminale
  – Creazione ed esecuzione dei relativi processi
• Spesso il comando immesso è complesso, e
  consta di più “comandi”
  (cd /src/dir && tar cf - . ) | ( cd /dst/dir && tar xf -)
• Servono meccanismi per operare su “gruppi”
  di processi:
  – Identificazione
  – Interruzione, terminazione
  – Sospensione, ripristino
• Modello di Job Control
                                                              128
Job Control
• Job Control: insieme di tutti i meccanismi
  necessari per:
  – identificare
  – sospendere e riesumare
  – eseguire attaccati ad un terminale
  – eseguire staccati da un terminale
  un insieme di processi
• Tale esigenza nasce dai vecchi terminali seriali
  – Avevano un solo “schermo”
  – Ci si poteva attaccare un solo comando per
    volta (foreground)
  – Gli altri comandi eseguivano staccati dal
    terminale (background)                           129
Job Control
• Job Control: insieme di tutti i meccanismi
  necessari per:
  – identificare
  – sospendere e riesumare
  – eseguire attaccati ad un terminale
  – eseguire staccati da un terminale
  un insieme di processi
• Tale esigenza nasce dai vecchi terminali seriali
  – Avevano un solo “schermo”
  – Ci si poteva attaccare un solo comando per
    volta (foreground)
  – Gli altri comandi eseguivano staccati dal
    terminale (background)                           130
Gruppi di processi
• I processi sono suddivisi in gruppi di processi
  (process group)
• Un gruppo di processi è un insieme di processi
  che possono essere segnalati tutti insieme
  – Segnali: Terminazione, interruzione, ripristino
  – Processi: i componenti di una pipeline
• Ciascun processo fa parte di un process group
• Ciascun process group:
  – ha un processo detto “process group leader”; è
    l'ultimo processo in una pipeline
  – è identificato da un process group ID (PGID),
    pari al PID del process group leader
  – esiste fino a quando ha almeno un elemento        131
Sessioni
• Quando un utente effettua un login, il processo
  login crea una nuova sessione
• Sessione: un insieme di process group
• All'inizio ho una solo process group di un solo
  processo (la shell di login)
• Tale processo prende il nome di session leader
• Il PID del processo session leader è usato
  come session ID (identifica la sessione)
• Ciascuna sessione ha associato un dispositivo
  terminale (fisico o virtuale) di controllo, che
  gestisce le operazioni di I/O da e verso la
  sessione
                                                    132
Foreground e Background PG
• I process group all'interno di una sessione
  sono suddivisi in due categorie:
  – Un foreground process group
  – Uno o più background process group
• Il foreground process group è l'unico gruppo
  di processi ad essere attaccato direttamente al
  terminale sia in ingresso che in uscita
  – Si può interagire con i processi in esecuzione
    tramite la tastiera
• I background process group sono attaccati al
  terminale solamente in uscita
  – Possono solo scrivere sul terminale, non
    possono ricevere dati da terminale
                                                     133
Terminali
• Diversi tipi di terminale:
  – Veri terminali fisici (VT100, VT102) attaccati via
    connessioni seriali (/dev/ttyS0)
  – Emulatore di terminale classico in testo, fornito
    dal kernel (/dev/tty1) e prenotato da getty
     ♦ Alt-F1 + getty->login->bash
  – Pseudo terminale in cui il kernel fornisce un
    minimo supporto (/dev/pts/0) ed un processo
    arbitrario si sostituisce all'emulatore di
    terminale classico
     ♦ ssh -t, xterm, gnome-terminal, kterm
     ♦ Automazione domanda-risposta con uno
       (pseudo) terminale: expect
         – Chatscript di login del modem                 134
Interazioni con il terminale
• In che modi si può interagire con il terminale,
  tramite la tastiera?
  – Terminazione dell'emulatore di terminale: viene
    inviato un segnale SIGQUIT a tutti i processi
    facenti parte del foreground process group
  – Disconnessione rete/seriale terminale fisico:
    viene inviato un segnale SIGHUP (Hangup) a
    tutti i processi facenti parte del foreground
    process group
     ♦ Window manager testuale screen: intercetta
       il segnale e conserva lo stato delle finestre
  – Interruzione pipeline (CTRL-C): viene inviato un
    segnale SIGINT a tutti i processi facenti parte
    del foreground process group
                                                       135
Interazioni con il terminale
• In che modi si può interagire con il terminale,
  tramite la tastiera?
  – Sospensione pipeline (CTRL-Z): viene inviato
    un segnale SIGTSTOP a tutti i processi facenti
    parte del foreground process group
  – Ripristino pipeline in foreground (%, fg): viene
    inviato un segnale SIGCONT a tutti i processi
    facenti parte del foreground process group
    sospeso




                                                       136
p
     Un modello a sessioni e gruppi
                        login

     Session
            Session                                        Terminale
             leader Login shell                           di controllo
                                                    stdout
                                                    stderr
                     BG PG PG      FG PG PG
    BG PG
                          leader        leader


                                     stdin       stdout
              PG                                 stderr
            leader
                                                 stdout
                                                 stderr              137
Gestione dei gruppi e delle sessioni
• Esecuzione di un process group in foreground
  – Si lancia una pipeline normalmente
  ls -lR / | grep passwd | less -Mr
• Esecuzione di un process group in
  background
  – Si termina una pipeline col simbolo &
  ls -lR / | grep passwd > output.txt 2>&1 &
  – Viene stampata una riga del tipo
    [1] 25647
  – 1: ID del job inviato
  – 25647: process group ID (PiD del processo
    leader del gruppo, ossia l'ultimo della pipeline,
    grep)
                                                        138
Gestione dei gruppi e delle sessioni
• Visione dello stato dei process group di una
  sessione: comando jobs
  – jobs -l: elenco completo dei process group, con
    process group ID relativi e stato di esecuzione
  – jobs -p: elenco dei process group ID
• Sospensione del process group in foreground:
  – CTRL-Z
• Ripristino in background di un process group
  sospeso:
  – bg %job_id (bg in per un process group unico)
• Ripristino in foreground di un process group
  sospeso:
  – fg %job_id (fg o % per un process group unico)    139
Creazione di una sessione
• Signature: pid_t setsid(void)
  – Descrizione:
     ♦ Crea una nuova sessione
     ♦ Crea un nuovo process group all'interno
       della sessione
     ♦ Imposta il processo chiamante a session e a
       group leader
     ♦ Utilizzato dalle shell e dai demoni
  – Argomenti: nessuno
  – Valore di ritorno:
     ♦ Il session ID della sessione, se tutto OK
     ♦ -1 in caso di errore
• Comando setsid                                     140
Ottenimento session ID
• Signature: pid_t getsid(pid_t pid)
  – Descrizione: ritorna il session ID della sessione
    in cui si trova il processo identificato da pid
  – Argomenti:
     ♦ Il pid del processo (0: processo chiamante)
  – Valore di ritorno:
     ♦ Il session ID della sessione, se tutto OK
     ♦ -1 in caso di errore




                                                        141
Impostazione di un process group ID
• Signature: int setpgid(pid_t pid, pid_t pgid)
  – Descrizione: imposta il process group ID del
    processo identificato da pid a pgid
     ♦ Pid deve riferirsi al processo invocante o ad un
       suo figlio che non ha invocato exec()
     ♦ Pid deve essere nella stessa sessione del
       processo invocante
     ♦ Pid non deve riferirsi ad un session leader

  – Argomenti:
     ♦ Il pid del processo considerato
     ♦ Il pgid considerato
  – Valore di ritorno:
     ♦ 0: tutto OK
     ♦ -1 in caso di errore                               142
Ottenimento session ID
• Signature: pid_t getpgid(pid_t pid)
  – Descrizione: ritorna il process group ID del
    processo identificato da pid
  – Argomenti:
     ♦ Il pid del processo (0: processo chiamante)
  – Valore di ritorno:
     ♦ Il processo group ID della sessione, se tutto
       OK
     ♦ -1 in caso di errore




                                                       143
Demoni UNIX
• Il demone (daemon) è un processo che:
  – esegue come figlio diretto di init
  – non è connesso ad alcun terminale
  – esegue in background
• Etimologia: Maxwell's demon (1867)
   http://en.wikipedia.org/wiki/Maxwell%27s_demon
• Scopi:
   – Gestione task di sistema
   – Processo server: ascolta richieste, genera figli
     che producono risposte
• Solitamente, un demone è avviato da root o da
  un utente dedicato (apache)
                                                        144
Passi di creazione di un demone
• Step 1: il processo invoca una fork()
  – Viene creato un nuovo processo figlio
  – Tale processo diventerà il demone
• Step 2: nel padre, si invoca la exit()
  – Il padre esce e rende orfano il figlio
  – Il figlio diventa figlio di init
  – Il figlio non è un process group leader
• Step 3: il processo figlio invoca setsid()
  – Il figlio diventa un session leader (non essendo
    un process group leader, può diventarlo)
  – Viene anche creato un process group di cui il
    processo figlio è leader
  – Il figlio non ha un terminale di controllo         145
Passi di creazione di un demone
• Step 4: il figlio invoca chdir(“/”)
  – Viene impostata la directory di lavoro a /
  – Altrimenti la directory ereditata dal padre
    potrebbe essere dovunque (dipende da dove è
    stato invocato il processo padre)
  – Tale directory non potrebbe essere più
    smontata, in quanto in uso (reference!) da parte
    del demone
  – Il demone tende a durare per tutto il ciclo di vita
    della macchina
  – O ammazzo il demone, o non smonto il
    filesystem contenente la directory da cui è stato
    invocato il demone
                                                          146
Passi di creazione di un demone
• Step 5: il figlio imposta la maschera dei
  permessi a 0 (opzionale)
• Step 6: il figlio chiude tutti i descrittori di file
   – Non servono
   – stdin, stdout, stderr non servono perché il
     demone non è connesso ad alcun terminale
   – Gli altri descrittori non servono perché il
     demone, solitamente, non fa I/O, bensì crea
     processi figli per la gestione di richieste
• Step 7: i descrittori stdin, stdout, stderr
  vengono redirezionati a /dev/null (o a qualche
  logfile)

                                                         147

Contenu connexe

Tendances

CPU Scheduling algorithms
CPU Scheduling algorithmsCPU Scheduling algorithms
CPU Scheduling algorithmsShanu Kumar
 
Introduction to Parallel Computing
Introduction to Parallel ComputingIntroduction to Parallel Computing
Introduction to Parallel ComputingRoshan Karunarathna
 
OS Functions and Services
OS Functions and ServicesOS Functions and Services
OS Functions and Servicessgpraju
 
Operating System Lecture Notes
Operating System Lecture NotesOperating System Lecture Notes
Operating System Lecture NotesFellowBuddy.com
 
Linux directory structure by jitu mistry
Linux directory structure by jitu mistryLinux directory structure by jitu mistry
Linux directory structure by jitu mistryJITU MISTRY
 
Unix.system.calls
Unix.system.callsUnix.system.calls
Unix.system.callsGRajendra
 
Process synchronization
Process synchronizationProcess synchronization
Process synchronizationAli Ahmad
 
Computer Networks - Layers in OSI Model
Computer Networks - Layers in OSI ModelComputer Networks - Layers in OSI Model
Computer Networks - Layers in OSI ModelShreyash Agarwal
 
Inter process communication using Linux System Calls
Inter process communication using Linux System CallsInter process communication using Linux System Calls
Inter process communication using Linux System Callsjyoti9vssut
 
Deadlock detection
Deadlock detectionDeadlock detection
Deadlock detectionNadia Nahar
 
470سؤال حقيقى فى الحاسب الآلى للجميع (1)
470سؤال حقيقى فى الحاسب الآلى للجميع (1)470سؤال حقيقى فى الحاسب الآلى للجميع (1)
470سؤال حقيقى فى الحاسب الآلى للجميع (1)Mohammad Alsaba
 
Chapter 13 - I/O Systems
Chapter 13 - I/O SystemsChapter 13 - I/O Systems
Chapter 13 - I/O SystemsWayne Jones Jnr
 
المركزية و اللامركزية في الإدارة التربوية في فلسطين
المركزية و اللامركزية في الإدارة التربوية في فلسطين المركزية و اللامركزية في الإدارة التربوية في فلسطين
المركزية و اللامركزية في الإدارة التربوية في فلسطين Jamaity
 
OS Components and Structure
OS Components and StructureOS Components and Structure
OS Components and Structuresathish sak
 
Operating System 3
Operating System 3Operating System 3
Operating System 3tech2click
 
Lecture 1 distriubted computing
Lecture 1 distriubted computingLecture 1 distriubted computing
Lecture 1 distriubted computingARTHURDANIEL12
 

Tendances (20)

CPU Scheduling algorithms
CPU Scheduling algorithmsCPU Scheduling algorithms
CPU Scheduling algorithms
 
Introduction to Parallel Computing
Introduction to Parallel ComputingIntroduction to Parallel Computing
Introduction to Parallel Computing
 
OS Functions and Services
OS Functions and ServicesOS Functions and Services
OS Functions and Services
 
Operating System Lecture Notes
Operating System Lecture NotesOperating System Lecture Notes
Operating System Lecture Notes
 
Linux directory structure by jitu mistry
Linux directory structure by jitu mistryLinux directory structure by jitu mistry
Linux directory structure by jitu mistry
 
Unix.system.calls
Unix.system.callsUnix.system.calls
Unix.system.calls
 
ROM BIOS & POST
ROM BIOS & POSTROM BIOS & POST
ROM BIOS & POST
 
Process synchronization
Process synchronizationProcess synchronization
Process synchronization
 
Computer Networks - Layers in OSI Model
Computer Networks - Layers in OSI ModelComputer Networks - Layers in OSI Model
Computer Networks - Layers in OSI Model
 
Inter process communication using Linux System Calls
Inter process communication using Linux System CallsInter process communication using Linux System Calls
Inter process communication using Linux System Calls
 
Deadlock detection
Deadlock detectionDeadlock detection
Deadlock detection
 
470سؤال حقيقى فى الحاسب الآلى للجميع (1)
470سؤال حقيقى فى الحاسب الآلى للجميع (1)470سؤال حقيقى فى الحاسب الآلى للجميع (1)
470سؤال حقيقى فى الحاسب الآلى للجميع (1)
 
Unit 1 ppt
Unit 1 pptUnit 1 ppt
Unit 1 ppt
 
I/O System
I/O SystemI/O System
I/O System
 
Chapter 13 - I/O Systems
Chapter 13 - I/O SystemsChapter 13 - I/O Systems
Chapter 13 - I/O Systems
 
Introduction To Operating System
Introduction To Operating SystemIntroduction To Operating System
Introduction To Operating System
 
المركزية و اللامركزية في الإدارة التربوية في فلسطين
المركزية و اللامركزية في الإدارة التربوية في فلسطين المركزية و اللامركزية في الإدارة التربوية في فلسطين
المركزية و اللامركزية في الإدارة التربوية في فلسطين
 
OS Components and Structure
OS Components and StructureOS Components and Structure
OS Components and Structure
 
Operating System 3
Operating System 3Operating System 3
Operating System 3
 
Lecture 1 distriubted computing
Lecture 1 distriubted computingLecture 1 distriubted computing
Lecture 1 distriubted computing
 

En vedette

Sistemi Operativi: Struttura avanzata - Lezione 05
Sistemi Operativi: Struttura avanzata - Lezione 05Sistemi Operativi: Struttura avanzata - Lezione 05
Sistemi Operativi: Struttura avanzata - Lezione 05Majong DevJfu
 
9 - Architetture Software - SOA Cloud
9 - Architetture Software - SOA Cloud9 - Architetture Software - SOA Cloud
9 - Architetture Software - SOA CloudMajong DevJfu
 
Linguaggi Formali e Compilazione: Frontend
Linguaggi Formali e Compilazione: FrontendLinguaggi Formali e Compilazione: Frontend
Linguaggi Formali e Compilazione: FrontendMajong DevJfu
 
Architettura dei Calcolatori Subroutines80x86
Architettura dei Calcolatori Subroutines80x86Architettura dei Calcolatori Subroutines80x86
Architettura dei Calcolatori Subroutines80x86Majong DevJfu
 
Sistemi Operativi: Meccanismi - Lezione 03
Sistemi Operativi: Meccanismi - Lezione 03Sistemi Operativi: Meccanismi - Lezione 03
Sistemi Operativi: Meccanismi - Lezione 03Majong DevJfu
 
Traffic Shaping Su Linux
Traffic Shaping Su LinuxTraffic Shaping Su Linux
Traffic Shaping Su LinuxMajong DevJfu
 
Sistemi Operativi: Struttura - Lezione 04
Sistemi Operativi: Struttura - Lezione 04Sistemi Operativi: Struttura - Lezione 04
Sistemi Operativi: Struttura - Lezione 04Majong DevJfu
 
esercizio sigda n 11
esercizio sigda n 11esercizio sigda n 11
esercizio sigda n 11Majong DevJfu
 
5 Trasporto Affidabile Teoria
5 Trasporto Affidabile Teoria5 Trasporto Affidabile Teoria
5 Trasporto Affidabile TeoriaMajong DevJfu
 
4 Livello Ip Parte1 Color
4 Livello Ip Parte1 Color4 Livello Ip Parte1 Color
4 Livello Ip Parte1 ColorMajong DevJfu
 
2 sistemi informativi d azienda
2 sistemi informativi d azienda2 sistemi informativi d azienda
2 sistemi informativi d aziendaMajong DevJfu
 
Calcolo Numerico - 2 - Numeri Di Macchina
Calcolo Numerico - 2 - Numeri Di MacchinaCalcolo Numerico - 2 - Numeri Di Macchina
Calcolo Numerico - 2 - Numeri Di MacchinaMajong DevJfu
 

En vedette (20)

Sistemi Operativi: Struttura avanzata - Lezione 05
Sistemi Operativi: Struttura avanzata - Lezione 05Sistemi Operativi: Struttura avanzata - Lezione 05
Sistemi Operativi: Struttura avanzata - Lezione 05
 
9 - Architetture Software - SOA Cloud
9 - Architetture Software - SOA Cloud9 - Architetture Software - SOA Cloud
9 - Architetture Software - SOA Cloud
 
Lean six sigma
Lean six sigmaLean six sigma
Lean six sigma
 
process creation OS
process creation OSprocess creation OS
process creation OS
 
Linguaggi Formali e Compilazione: Frontend
Linguaggi Formali e Compilazione: FrontendLinguaggi Formali e Compilazione: Frontend
Linguaggi Formali e Compilazione: Frontend
 
8 Www2009 Parte1
8 Www2009 Parte18 Www2009 Parte1
8 Www2009 Parte1
 
3 H2 N Parte3
3 H2 N Parte33 H2 N Parte3
3 H2 N Parte3
 
Architettura dei Calcolatori Subroutines80x86
Architettura dei Calcolatori Subroutines80x86Architettura dei Calcolatori Subroutines80x86
Architettura dei Calcolatori Subroutines80x86
 
Sistemi Operativi: Meccanismi - Lezione 03
Sistemi Operativi: Meccanismi - Lezione 03Sistemi Operativi: Meccanismi - Lezione 03
Sistemi Operativi: Meccanismi - Lezione 03
 
Traffic Shaping Su Linux
Traffic Shaping Su LinuxTraffic Shaping Su Linux
Traffic Shaping Su Linux
 
Sistemi Operativi: Struttura - Lezione 04
Sistemi Operativi: Struttura - Lezione 04Sistemi Operativi: Struttura - Lezione 04
Sistemi Operativi: Struttura - Lezione 04
 
esercizio sigda n 11
esercizio sigda n 11esercizio sigda n 11
esercizio sigda n 11
 
5 Trasporto Affidabile Teoria
5 Trasporto Affidabile Teoria5 Trasporto Affidabile Teoria
5 Trasporto Affidabile Teoria
 
E6 Concorre
E6 ConcorreE6 Concorre
E6 Concorre
 
4 Livello Ip Parte1 Color
4 Livello Ip Parte1 Color4 Livello Ip Parte1 Color
4 Livello Ip Parte1 Color
 
2 sistemi informativi d azienda
2 sistemi informativi d azienda2 sistemi informativi d azienda
2 sistemi informativi d azienda
 
9 Ftp Telnet Email
9 Ftp Telnet Email9 Ftp Telnet Email
9 Ftp Telnet Email
 
6 Dns Parte2
6 Dns Parte26 Dns Parte2
6 Dns Parte2
 
esercizio sigda n 8
esercizio sigda n 8esercizio sigda n 8
esercizio sigda n 8
 
Calcolo Numerico - 2 - Numeri Di Macchina
Calcolo Numerico - 2 - Numeri Di MacchinaCalcolo Numerico - 2 - Numeri Di Macchina
Calcolo Numerico - 2 - Numeri Di Macchina
 

Plus de Majong DevJfu

8 - Architetture Software - Architecture centric processes
8 - Architetture Software - Architecture centric processes8 - Architetture Software - Architecture centric processes
8 - Architetture Software - Architecture centric processesMajong DevJfu
 
7 - Architetture Software - Software product line
7 - Architetture Software - Software product line7 - Architetture Software - Software product line
7 - Architetture Software - Software product lineMajong DevJfu
 
6 - Architetture Software - Model transformation
6 - Architetture Software - Model transformation6 - Architetture Software - Model transformation
6 - Architetture Software - Model transformationMajong DevJfu
 
5 - Architetture Software - Metamodelling and the Model Driven Architecture
5 - Architetture Software - Metamodelling and the Model Driven Architecture5 - Architetture Software - Metamodelling and the Model Driven Architecture
5 - Architetture Software - Metamodelling and the Model Driven ArchitectureMajong DevJfu
 
4 - Architetture Software - Architecture Portfolio
4 - Architetture Software - Architecture Portfolio4 - Architetture Software - Architecture Portfolio
4 - Architetture Software - Architecture PortfolioMajong DevJfu
 
3 - Architetture Software - Architectural styles
3 - Architetture Software - Architectural styles3 - Architetture Software - Architectural styles
3 - Architetture Software - Architectural stylesMajong DevJfu
 
2 - Architetture Software - Software architecture
2 - Architetture Software - Software architecture2 - Architetture Software - Software architecture
2 - Architetture Software - Software architectureMajong DevJfu
 
1 - Architetture Software - Software as a product
1 - Architetture Software - Software as a product1 - Architetture Software - Software as a product
1 - Architetture Software - Software as a productMajong DevJfu
 
10 - Architetture Software - More architectural styles
10 - Architetture Software - More architectural styles10 - Architetture Software - More architectural styles
10 - Architetture Software - More architectural stylesMajong DevJfu
 
25 architectural adaptation
25 architectural adaptation25 architectural adaptation
25 architectural adaptationMajong DevJfu
 

Plus de Majong DevJfu (20)

8 - Architetture Software - Architecture centric processes
8 - Architetture Software - Architecture centric processes8 - Architetture Software - Architecture centric processes
8 - Architetture Software - Architecture centric processes
 
7 - Architetture Software - Software product line
7 - Architetture Software - Software product line7 - Architetture Software - Software product line
7 - Architetture Software - Software product line
 
6 - Architetture Software - Model transformation
6 - Architetture Software - Model transformation6 - Architetture Software - Model transformation
6 - Architetture Software - Model transformation
 
5 - Architetture Software - Metamodelling and the Model Driven Architecture
5 - Architetture Software - Metamodelling and the Model Driven Architecture5 - Architetture Software - Metamodelling and the Model Driven Architecture
5 - Architetture Software - Metamodelling and the Model Driven Architecture
 
4 - Architetture Software - Architecture Portfolio
4 - Architetture Software - Architecture Portfolio4 - Architetture Software - Architecture Portfolio
4 - Architetture Software - Architecture Portfolio
 
3 - Architetture Software - Architectural styles
3 - Architetture Software - Architectural styles3 - Architetture Software - Architectural styles
3 - Architetture Software - Architectural styles
 
2 - Architetture Software - Software architecture
2 - Architetture Software - Software architecture2 - Architetture Software - Software architecture
2 - Architetture Software - Software architecture
 
1 - Architetture Software - Software as a product
1 - Architetture Software - Software as a product1 - Architetture Software - Software as a product
1 - Architetture Software - Software as a product
 
10 - Architetture Software - More architectural styles
10 - Architetture Software - More architectural styles10 - Architetture Software - More architectural styles
10 - Architetture Software - More architectural styles
 
Uml3
Uml3Uml3
Uml3
 
Uml2
Uml2Uml2
Uml2
 
6
66
6
 
5
55
5
 
4 (uml basic)
4 (uml basic)4 (uml basic)
4 (uml basic)
 
3
33
3
 
2
22
2
 
1
11
1
 
Tmd template-sand
Tmd template-sandTmd template-sand
Tmd template-sand
 
26 standards
26 standards26 standards
26 standards
 
25 architectural adaptation
25 architectural adaptation25 architectural adaptation
25 architectural adaptation
 

Sistemi Operativi: Processi - Lezione 07

  • 1. Concetto di processo • Processo: istanza di un programma in esecuzione – Codice del programma (sezione di testo) – Stato di avanzamento ♦ Contatore di programma ♦ Pila (variabili locali, indirizzi di ritorno) – Variabili locali (sezione dei dati) 1
  • 2. Concetto di processo • Programma e processo sono due entità distinte – Un programma è un'entità passiva ♦ File su disco (codice o eseguibile) immutato ♦ Non va in esecuzione da solo – Un processo è un'entità attiva ♦ Struttura dati contenente puntatori a – Codice – Dati – Stato del processo 2
  • 3. Esecuzione di un processo • Il gestore dei processi esegue, ad intervalli di tempo più o meno regolari, una sequenza di istruzioni pertinenenti al programma (trace) • Un SO moderno, multiprogrammato, time- sharing garantisce una esecuzione sequenziale e concorrente (interleaved) di più processi • Compiti specifici del gestore dei processi: – Garantire l'esecuzione sicura di una traccia – Scegliere il prossimo processo di cui sarà eseguita una traccia (scheduling) – Gestire la commutazione periodica tra un processo ed un altro (context switch) 3
  • 4. Esecuzione interleaved Memoria principale Gestore processi Program Counter Processo A Processo B Processo C 4
  • 5. Esecuzione interleaved Memoria Indirizzi PC principale a+0 a+2 Gestore processi a+6 Program a + 10 Counter Scade l'intervallo Processo A di tempo assegnato al processo A Processo B Processo C 5
  • 6. Esecuzione interleaved Memoria Indirizzi PC principale g + 100 g + 102 Gestore processi g + 106 Program g + 110 Counter g + 114 Processo A Il gestore dei processi sceglie come prossimo processo da eseguire Processo B il processo B, e ne prepara l'esecuzione Processo C 6
  • 7. Esecuzione interleaved Memoria Indirizzi PC principale b + 32 b + 36 Gestore processi b + 40 Program Counter Il processo B si interrompe perché Processo A deve effettuare una operazione di I/O Processo B Processo C 7
  • 8. Esecuzione interleaved Memoria Indirizzi PC principale g + 100 g + 102 Gestore processi g + 106 Program g + 110 Counter g + 114 Processo A Il gestore dei processi sceglie come prossimo processo da eseguire Processo B il processo C, e ne prepara l'esecuzione Processo C 8
  • 9. Esecuzione interleaved Memoria Indirizzi PC principale c + 248 c + 356 Gestore processi c + 360 Program c + 364 Counter Il processo C termina Processo A la sua esecuzione Processo B Processo C 9
  • 10. Esecuzione interleaved Memoria Indirizzi PC principale g + 100 g + 102 Gestore processi g + 106 Program g + 110 Counter g + 114 Processo A Il gestore dei processi sceglie come prossimo processo da eseguire Processo B il processo A, e ne prepara l'esecuzione Processo C 10
  • 11. Esecuzione interleaved Memoria Indirizzi PC principale a + 14 a + 18 Gestore processi a + 22 Program a + 56 Counter Il processo A si Processo A blocca perché richiede una operazione di I/O Processo B Processo C 11
  • 12. Rappresentazione di un processo • L'esecuzione di tipo interleaved deve essere modellata all'interno del gestore dei processi • Sembrerebbe naturale introdurre un modello del tipo DFA (Deterministic Finite Automata, automa deterministico a stati finiti) • Quanti stati utilizzo per il mio modello? • Proviamo con il caso più semplice: – Due stati: running, not running – I processi non in esecuzione sono “accodati” di fronte al processore, in attesa di ricevere tempo di calcolo – Tramite oppoerunte transizioni, un processo è in grado di cambiare stato 12
  • 13. Rappresentazione di un processo Modello a due stati blocking creazione terminazione not running running dispatching Diagramma di accodamento creazione dispatching terminazione CPU coda processi pronti 13
  • 14. Incompletezza del modello a 2 stati • Il modello a due stati è incompleto • Tutti i processi che non eseguono sono equiparati a processi in qualche modo “bloccati” • In realtà, le cause del blocco possono essere estremamente diverse: – scadenza dell'intervallo di tempo di calcolo assegnato – comando di una operazione di I/O – arrivo di una interruzione • Per discriminare le diverse cause di blocco, è necessario considerare un modello con almeno tre stati 14
  • 15. Modello a tre stati • L'automa che descrive il ciclo di vita di un processo è composto da tre stati: – running: la CPU sta eseguendo una traccia del processo – blocked: la CPU ha comandato una istruzione che richiede il verificarsi di un evento (di solito, I/O) per conto del processo, che deve fermarsi ed attendere la risposta – ready: la CPU non sta eseguendo una traccia del processo (quale che sia il motivo), tuttavia il processo è nelle condizioni di essere ripristinato • Differenziazione esplicita degli stati di “bloccato” e “pronto” 15
  • 16. Modello a tre stati Modello a tre stati scadenza intervallo creazione terminazione ready running tempo dispatching completamento attesa evento evento blocked Transizioni ready => running: assegnazione CPU al processo running => ready: il processo ha utilizzato il max. tempo per esecuzione traccia running => blocked: attesa completamento evento blocked => ready: l'evento atteso si verifica 16
  • 17. Stati aggiuntivi • Il modello a tre stati è in grado di catturare le diverse dinamiche di interruzione dell'esecuzione di una traccia • Vengono aggiunti alcuni stati aggiuntivi per la gestione pulita dei meccanismi di creazione e di terminazione del processo • Due ulteriori stati: – new: il sistema alloca ed inizializza le strutture dati per la gestione dell'esecuzione del processo – exit: il sistema rilascia le strutture dati ed alcune risorse allocate dal processo 17
  • 18. Stati aggiuntivi Stato aggiuntivo new creazione admit terminazione new ready Strutture dati per il processo allocate ed inizializzate Stato aggiuntivo exit terminazione running exit Rilascio strutture dati allocate per il processo 18
  • 19. Modello a cinque stati • Ad ogni processo è associato uno stato • Durante l'esecuzione, un processo è soggetto a cambiamenti di stato • Stati: – new: il processo è stato appena creato – running: una unità di elaborazione esegue le istruzioni del relativo programma – blocked: il processo è in attesa del verificarsi di un qualche evento – ready: il processo attende di essere assegnato ad una unità di elaborazione – exit: il processo ha terminato la sua esecuzione 19
  • 20. Modello a cinque stati ammesso uscita new exit interruzione ready running completamento I/O attesa I/O dispatching verifica evento attesa evento blocked 20
  • 21. Modello a cinque stati Diagramma di accodamento CPU Coda processi pronti I/O Coda I/O Richiesta I/O quanto di tempo esaurito processo figlio generazione in esecuzione processo figlio attesa occorrenza interruzione interruzione 21
  • 22. Cause di creazione di un processo • Attivazione di un batch job – Comando inviato tramite shell • Login interattivo – Accesso al sistema da parte di un utente • Gestione di un servizio – Un processo soddisfa una richiesta di servizio – Il processo invocante non si interrompe – Processi server • Spawning – Un processo soddisfa una richiesta di servizio – Il processo invocante si interrompe – Processi di login 22
  • 23. Cause di terminazione di un processo • Completamento della traccia di istruzioni – Può essere comunicato esplicitamente • Indisponibilità di memoria – Il processo richiede troppa memoria • Violazioni di limite – Accesso a locazioni di memoria proibite • Errore di protezione – Accesso ad una risorsa protetta o inesistente • Terminazione su richiesta – Operata dal sistema o da un altro processo • Errore aritmetico – Divisione per zero, overflow 23
  • 24. Il grado di multiprogrammazione • Il processore è, solitamente, molto più veloce dei sistemi di I/O – La maggior parte dei processi residenti in memoria è nello stato blocked, in attesa di completamento di una richiesta di I/O – Rischio di sottoutilizzo del processore • Come si può prevenire questo problema? – Si cerca di mantenere il maggior numero di processi possibile negli stati running/ready – Grado di multiprogrammazione: numero di processi eseguibili (running + ready) – Obiettivo: mantenere il più alto possibile il grado di multiprogrammazione 24
  • 25. Swapping • Per superare il limite imposto dal vincolo di memoria fisica disponibile, si introduce il concetto di swapping nel modello • Due stati aggiuntivi: – Blocked-Suspended: il processo è bloccato (in attesa di un evento) e la memoria che occupa è stata liberata con un trasferimento dati su disco (swap out) – Ready-Suspended: il processo non è bloccato (nessun evento, oppure attesa terminata) e torna ad occupare memoria centrale con un trasferimento dati da disco (swap in) 25
  • 26. Modello a cinque stati con swapping ammesso uscita new exit interruzione Ripristino in memoria (swap in) ready running completamento I/O attesa I/O dispatching verifica evento attesa evento verifica evento blocked Rimozione dalla ready memoria (swap out) suspended blocked suspended verifica evento 26
  • 27. Modello a cinque stati con swapping Diagramma di accodamento (swapping) Processi parzialmente swap in swap out eseguiti e sottoposti a swap CPU Coda processi pronti I/O Coda I/O Richiesta I/O 27
  • 28. Cause di sospensione di un processo • Swapping – Liberazione porzioni di memoria da parte del SO – Obiettivo: aumento grado multiprogrammazione • Richiesta – Da parte di un utente interattivo – Da parte di un altro processo (coordinamento attività) • Temporizzazione – Gestione attività periodiche (monitoraggio) • Recupero – Ripristino da situazioni erronee/incoerenti 28
  • 29. Gestione processi: strutture di controllo • Per gestire l'esecuzione dei processi, il SO mantiene informazioni sui processi stessi e sulle risorse utilizzate Immagine P 1 Risorse Strutture dati di sistema di controllo Tabella di Memoria Tabella di memoria memoria Dispositivi ... Tabella di File ... memoria Immagine Pn Tabella dei Processi processi P1 Pn 29
  • 30. Tabelle di memoria • Contengono informazioni su: – Allocazione memoria principale ai processi – Allocazione memoria secondaria ai processi – Modalità di protezione dei singoli segmenti di memoria (read-only, read-write, execute) – Informazioni necessarie a gestire la memoria virtuale (nei sistemi in cui essa è supportata) • Esempi: – Pagine di memoria accessaibili al processo – File aperti (e relativi descrittori) 30
  • 31. Immagine di un processo • L'immagine di un processo rappresenta l'insieme di informazioni necessarie per poter coordinare l'esecuzione di più processi – Codice macchina del programma di cui il processo risulta essere una istanza, memorizzati in aree leggibili ed eseguibili – Dati utilizzati dal programma, memorizzati in aree di memoria leggibili e scrivibili – Stack, utilizzato per gestire le chiamate di funzione – Process Control Block (PCB), una collezione di attributi necessari al SO per controllare l'esecuzione del processo stesso 31
  • 32. Immagine di un processo Indirizzi alti Stack Stack segment programma Lo stack cresce verso il basso “Buco” nello spazio di indirizzamento Heap L'heap cresce verso alto (malloc) Data segments Variabili non inizializzate BSS (vengono impostate a 0) Variabili globali inizializzate Data Indirizzi bassi Codice Text segment eseguibile 32
  • 33. Process Control Block • Il SO associa a ciascun processo un descrittore di processo (Process Control Block) – Identificatori: del processo, di altri processi relazionati – Stato del processo: running, ready, blocked,... – Privilegi: per accesso a servizi e risorse – Registri: salvataggio registri della CPU (registri interni, program counter, stack pointer) – Informazioni di scheduling: tutto ciò che il sistema necessita di sapere per arbitrare la assegnazione del processore ai processi in stato ready (CPU scheduling) – informazioni di stato: evento atteso 33
  • 34. Process Control Block Process Control Block puntatore stato del processo identificatore di processo (PID) contatore di programma registri contatore di programma elenco dei file aperti ... 34
  • 35. Scheduling dei processi • Obiettivo della multiprogrammazione: – massimizzare l'utilizzo della CPU tramite l'esecuzione contemporanea di più processi – contemporaneo è da intendersi nel senso di avanzamento alternato, non nel senso di esecuzione contemporanea sulla stessa CPU • Obiettivo del time sharing: – Commutare l'uso della CPU fra processi così velocemente da facilitare l'interattività con gli utenti 35
  • 36. Scheduling dei processi • In un sistema con m CPU, al più m processi possono essere in esecuzione alla volta – Che succede se ho più di m processi in memoria? • L'esecuzione dei processi deve essere schedulata sulle risorse di elaborazione a disposizione – Chi decide quale processo deve essere ripristinato in esecuzione su quale CPU? • Scheduler 36
  • 37. Code di scheduling • Per coordinare il passaggio di stato fra processi, il SO fa uso massiccio di code di scheduling • Code utilizzate: – Coda dei processi ♦ contiene tutti i processi del sistema – Coda dei processi pronti (ready queue) ♦ contiene tutti i processi in stato di pronto – Coda di dispositivo ♦ contiene tutti i processi in attesa per l'uso del dispositivo ♦ una coda distinta per dispositivo 37
  • 38. Code di scheduling PCB7 PCB2 coda dei Primo elemento processi Ultimo elemento registri registri pronti ... ... coda Primo elemento unità Ultimo elemento CDROM PCB3 PCB14 PCB6 coda Primo elemento unità Ultimo elemento registri registri registri dischi ... ... ... coda PCB3 Primo elemento terminale Ultimo elemento registri 0 ... 38
  • 39. Scheduler • Componente del SO che seleziona i processi dalle code • Due tipi di scheduling: – Job scheduling – CPU scheduling 39
  • 40. Job scheduling • Utilizzato nei sistemi batch • L'insieme dei job da eseguire viene riversato su disco (spooling) • Lo scheduler dei job sceglie il prossimo job da mandare in esecuzione • Obiettivo: mantenere costante il numero di job in memoria (grado di multiprogrammazione) • Invocato con frequenza bassa • Bilancio fra processi I/O-bound e CPU-bound • Job scheduling non è integrato nel kernel dei moderni sistemi UNIX – Implementazioni applicative (stampa, posta) 40
  • 41. CPU scheduling • Utilizzato nei sistemi time sharing • Seleziona il prossimo processo dalla coda di pronto per l'esecuzione • Obiettivi: – Massimizzare numero di processi eseguiti nell'unità di tempo (throughput) – Minimizzare la latenza di processo – Dare priorità ai processi più importanti • Invocato con frequenza elevata (ogni 100 msec) 41
  • 42. Context switch • Quando la CPU interrompe l'esecuzione di un processo per passare ad un altro: 1.Occorre salvare lo stato attuale del vecchio processo 2.Occorre ripristinare lo stato precedente del nuovo processo • Le operazioni delineate in 1. e 2. prendono il nome di context switch • Contesto di un processo: contenuto del descrittore di processo – Registri, stato, info gestione memoria • Durata context switch: 1usec – 1msec – Dipende fortemente dalla architettura 42
  • 43. Cambio modalità esecuzione • I processi si alternano anche in diverse modalità di esecuzione, caratterizzate da livelli di privilegio diversi – User mode, Kernel mode • User mode: esecuzione applicativi • Kernel mode: esecuzione servizi del kernel – Accesso a privilegi di livello superiore – Possibilità di esecuzione di istruzioni non ammesse in user mode – Caratterizzato (riconoscibile) da un settaggio di un bit di stato del processore 43
  • 44. Modalità esecuzione e context switch Processo Processo syscall() Meccanismo per il User mode cambio di modo Kernel mode service_call() Scheduler Invocazione scheduler Chiamata bloccante Hardware 44
  • 45. Modi di esecuzione e context switch • Cause di context switch – Interruzione di clock (time sharing), viene attivato lo scheduler per cedere il controllo ad un altro processo – Interruzione di I/O, con possibile riattivazione di un processo a più alta priorità – Nei sistemi basati su memoria virtuale, prelievo di una pagina di memoria da swap (page fault) • Cause di cambio modo di esecuzione – Attivazione di una Interrupt Service Routine – Context switch – Chiamata di sistema 45
  • 46. Context switch Processo P0 Sistema operativo Processo P1 Salva lo stato in PCB0 Ripristina lo stato da PCB1 Salva lo stato in PCB1 Ripristina lo stato da PCB1 46
  • 47. Context switch Processo P0 Sistema operativo Processo P1 Interruzione o syscall bloccante Salva lo stato in PCB0 Ripristina lo stato da PCB1 Salva lo stato in PCB1 Ripristina lo stato da PCB1 47
  • 48. Context switch Processo P0 Sistema operativo Processo P1 Interruzione o syscall bloccante Salva lo stato in PCB0 Ripristina lo stato da PCB1 Salva lo stato in PCB1 Ripristina lo stato da PCB1 48
  • 49. Context switch Processo P0 Sistema operativo Processo P1 Interruzione o syscall bloccante Salva lo stato in PCB0 Ripristina lo stato da PCB1 Salva lo stato in PCB1 Ripristina lo stato da PCB1 49
  • 50. Context switch Processo P0 Sistema operativo Processo P1 Interruzione o syscall bloccante Salva lo stato in PCB0 Ripristina lo stato da PCB1 Interruzione o syscall bloccante Salva lo stato in PCB1 Ripristina lo stato da PCB1 50
  • 51. Context switch Processo P0 Sistema operativo Processo P1 Interruzione o syscall bloccante Salva lo stato in PCB0 Ripristina lo stato da PCB1 Interruzione o syscall bloccante Salva lo stato in PCB1 Ripristina lo stato da PCB0 51
  • 52. Modello processi UNIX • Esecuzione dei processi in user mode (codice applicativo) e kernel mode (servizi) – Lo stato running deve essere suddiviso in due stati: user running e kernel running • Lo scheduler implementa un meccanismo di prelazione per supportare la priorità – Un processo che ritorna da una chiamata di sistema (lasciando il kernel mode) può essere messo in stato ready e lasciare il passo ad un processo con più alta priorità – Nuovo stato preempted che modella la prelazione 52
  • 53. Modello processi UNIX • Modello gerarchico di processi: un processo padre genera processi figli • PID: process identifier (identifica il processo) • Processo padre coordinatore aspetta che i processi figli lavoratori terminino l'esecuzione • Se al momento dell'uscita un processo figlio non ha un processo padre che aspetta il suo completamento, entra nello stato zombie – Processo figlio morto – Ha un PCB nella tabella dei processi, in modo tale che il processo padre possa leggere il suo stato di uscita – Distinzione stati exited e zombie 53
  • 54. Modello processi UNIX preempted new User mode running Ready ready Swapped out Kernel mode running Sleeping Sleeping in Swapped out memory exited zombie 54
  • 55. Immagine di un processo Testo Dati Contesto utente Stack utente Memoria condivisa Program counter Registro di stato del processore Contesto registri Stack pointer Registri generali Entry nella tabella dei processi U area (area utente) Contesto sistema Tabella indirizzamento (memoria virtuale) Stack del kernel mode 55
  • 56. Entry della tabella dei processi Stato del processo Puntatori alla U area Dimensioni del processo Identificatori d’utente (reale ed effettivo) Identificatori di processi (pid, id del genitore) Descrittore degli eventi (valido in stato sleeping) Priorita’ Segnali (mandati al processi ma non ancora gestiti) Timer (monitoring) P_link (puntatore per la lista ready) Stato della memoria (swap in/out) 56
  • 57. User Area (U area) Puntatore alla entry della tabella dei processi Dimensioni del processo Identificatori d’utente (effettivo) Array per i gestori di segnali Terminale Campo di errore Parametri di I/O (es. indirizzi dei buffer) Timer (monitoring in modalita’ utente) Valore di ritorno di system calls Tabella dei descrittori di file 57
  • 58. Modello di avvio processi UNIX Kernel init getty login shell (PID=0) (PID=1) getty login shell Legge /etc/inittab getty login shell • Shell tipiche: – Bourne Again SHell – Bourne Legge –C /etc/passwd – Korn Comandi di shell: nome-comando [ arg1, ..., argn ] 58
  • 59. Creazione di un processo UNIX • Durante la propria esecuzione, un processo può creare altri processi (fork) – Processo creante: processo padre – Processo creato: processo figlio • Ciascun processo creato, a sua volta, può creare altri processi • Organizzazione dei processi ad albero • Un processo può ereditare dal padre: – Tutte le risorse – Un sottoinsieme delle risorse 59
  • 60. Albero di processi UNIX kernel page daemon swapper init utente 1 utente 2 utente 3 60
  • 61. Creazione di un processo UNIX • Esecuzione del processo padre dopo aver creato un processo figlio: – Il processo padre continua l'esecuzione in maniera concorrente con i propri figli – Il processo padre attende che alcuni o tutti i suoi figli terminino l'esecuzione • Esecuzione del processo figlio: – Dallo stesso punto in cui si era interrotto il padre prima di invocare la fork() • Spazio di indirizzamento del processo figlio: – Il processo figlio è un duplicato del padre – Il processo figlio carica un programma 61
  • 62. System call fork() • In UNIX, ogni processo è caratterizzato da un numero identificatore univoco (PID) • Un nuovo processo viene creato per mezzo della syscall fork() • La syscall fork: – Duplica il descrittore del processo padre nel descrittore del processo figlio – Genera un nuovo PID – Inserisce il descrittore di processo del figlio nella coda di pronto • Valore di ritorno della fork: – PID nel processo padre – 0 nel processo figlio 62
  • 63. System call fork() • Signature: pid_t fork(void) – Descrizione: crea un esatto duplicato del processo chiamante – Argomenti: nessuno – Valore di ritorno: ♦ Processo padre -> PID del figlio ♦ Processo figlio -> 0 ♦ -1 in caso di errore Processo padre Processo figlio stack stack Entrambi i processi fork() ripartono dall'istruzione successiva alla fork() heap heap dati dati nel testo testo testo 63
  • 64. Utilizzi del meccanismo di forking • Creazione di shell comandi a catena fork() fork() (pipeline) pipe() exec() exec() find wc find . -name '*.c' -print | wc -l output • Gestione di servizi Server richieste process (request serving) fork() fork() – Web server Child Child process process – FTP server – “XYZ” server risposta risposta 64
  • 65. Cattivi utilizzi del forking: fork bomb • Una fork bomb è un particolare tipo di processo che non fa altro che riprodurre processi figli, I quali a loro volta si riproducono • Meccanismo rozzo ma efficace di negazione dei servizi (Denial of Service, DoS) – Può essere accidentale – Di solito, è intenzionale (malizioso) • Una fork bomb fa esplicite assunzioni sul comportamento del SO: – Tabella dei processi di dimensioni limitate (viene saturata, non si può più eseguire niente) – Ciascun processo richiede risorse di calcolo (il sistema rallenta considerevolmente) 65
  • 66. Cattivi utilizzi del forking: fork bomb bomb ... bomb bomb ... bomb bomb ... ... bomb bomb bomb bomb ... ... ... ... 66
  • 67. Scheletro di una fork bomb • Il tipico scheletro di una fork bomb è un ciclo while che, per sempre, effettua una fork() • Per peggiorare le cose, si può anche allocare della memoria – Memory leak: alloco memoria senza liberarla – Porta molto rapidamente il sistema in swap – Nei sistemi con Copy On Write, occorre scrivere nella memoria per creare le pagine copia while ( 1 ) { x=malloc(1048576); /* 1MB */ *x = 0; /* forza il Copy On Write */ fork(); } 67
  • 68. Prevenzione delle fork bomb • Soluzioni comuni: – Il SO imposta un limite al numero di processi generati da un utente (ulimit) – Uccisione di tutti i processi (tranne kill ed init) kill -9 -1 – Modifiche al SO per impedire la diffusione del bombing 68
  • 69. vfork() • Variante veloce della fork(), pensata per I processi figli che caricano immediatamente altre immagini – Scenario ideale: shell (processo padre che forka processi figli eseguenti comandi) • Il kernel non copia la tabella di memoria del padre nelle tabelle di memoria del figlio, ma le fa condividere finché il processo figlio: – non carica una immagine (exec()) – non esce (_exit()) • Nel frattempo, il processo padre si blocca • Non esiste semantica Copy-On-Write: il figlio può cambiare i valori delle variabili del padre 69
  • 70. Gestione dei Process IDentifier • Signature: pid_t getpid(void) – Descrizione: ritorna il PID del processo chiamante – Argomenti: nessuno – Valore di ritorno: il PID del processo chiamante • Signature: pid_t getppid(void) – Descrizione: ritorna il PID del processo padre di quello chiamante – Argomenti: nessuno – Valore di ritorno: il PID del processo padre del processo chiamante 70
  • 71. Identificazione di processi • Come si possono trovare I PID dei processi in maniera estremamente rapida? • Comando pgrep – pgrep “stringa” – Restituisce una lista di PID associati a processi il cui nome contiene “stringa” – pgrep init -> 1 71
  • 72. Terminazione di un processo • La syscall exit() viene utilizzata per terminare il programma con un codice di uscita • Alcune risorse allocate dal processo vengono liberate dal SO – Gli stream aperti vengono svuotati (flush) – I file temporanei vengono rimossi – Viene chiamata la funzione di chiusura _exit() • Se un processo genitore termina, tutti i suoi figli si chiamano orfani – Gli orfani diventano immediatamente figli del processo init (che ha PID=1) 72
  • 73. Terminazione di un processo • Variante: _exit() • Il processo esce con un codice di uscita • Non svuota gli stream aperti, non cancella i file temporanei • Chiude i descrittori di file aperti • Quando si usa la _exit()? – Processo figlio creato con vfork() – Processo figlio che non ha caricato una immagine con exec() • Si impedisce che il figlio possa modificare le risorse usate dal padre 73
  • 74. Terminazione di un processo • Signature: void exit(int status) – Descrizione: termina l'esecuzione del processo e fornisce un codice di uscita al processo invocante – Argomenti: il codice di uscita ♦ EXIT_SUCCESS (0): tutto OK ♦ EXIT_FAILURE (1): errore – Valore di ritorno: nessuno • Si possono usare anche altri codici di uscita > 0 per discriminare diverse cause di errore 74
  • 75. Segnali • Meccanismo di notifica asincrona di eventi ad un processo – Asincrona: non legata ad eventi interni al kernel • Meccanismo primitivo di Inter Process Communication (IPC) • Un segnale è una interruzione software (eccezione), inviata ad un processo – Inviata tramite tastiera (CTRL-C da terminale) – Inviata tramite il comando kill – Inviata dal kernel (SIGSEGV) 75
  • 76. Ciclo di vita di un segnale • I segnali UNIX hanno un ciclo di vita preciso • Step 1: un processo (o il kernel) genera un segnale (raise, send, generate) • Step 2: il kernel conserva il segnale fino a quando non è in grado di consegnarlo • Step 3: il kernel consegna il segnale al processo destinatario • Step 4: il kernel esegue una azione legata al segnale 76
  • 77. Azioni legate ad un segnale • Quali sono le possibili azioni? • Ignorare il segnale (ignore): – Non viene intrapresa alcuna azione – Due segnali (KILL, STOP) non possono essere ignorati • Gestire il segnale (catch and handle): – Sospensione dell'esecuzione del processo – Salto ad una funzione (handler) definita nel codice del programma ed assegnata al segnale – Ripristino dell'esecuzione del processo • Eseguire una azione di default (default action): – Il kernel esegue una azione preconfigurata (ad es., uccisione del processo) 77
  • 78. Identificatori di segnale • I segnali sono identificati in maniera univoca da numeri interi positivi, a partire dal numero 1 • A ciascun numero è associato una costante simbolica avente prefisso SIG • La definizione dell'intero insieme dei segnali è definita nel file include <bits/signum.h> • Per vedere la lista, si può utilizzare il comando di gestione dei segnali kill: kill -l 78
  • 79. Alcuni segnali comuni • SIGKILL (9): – Termina istantaneamente il processo, senza possibilità di effettuare operazioni di cleanup – Non può essere gestito con un handler • SIGTERM (15): – termina istantaneamente il processo, con possibilità di registrare un handler per effettuare operazioni di cleanup • SIGINT (2): – Segnale di interruzione, inviato al processo collegato ad un terminale, in seguito a CTRL-C – Termina il processo 79
  • 80. Alcuni segnali comuni • SIGSEGV (11): – Il kernel termina istantaneamente il processo, in seguito ad un accesso invalido alla memoria – Non può essere gestito con un handler • SIGCHLD (15): – Segnale inviato al processo padre quando un processo figlio termina l'esecuzione • SIGUSR1 (10), SIGUSR2 (12): – Segnali configurabili tramite handler opportuni – Azione di default: terminano il processo • E tanti, tanti altri... 80
  • 81. Invio di segnali: il comando kill • Il comando kill permette di inviare segnali ai processi – kill -”id segnale” “pid processo – kill -9 8732 – Occorre avere I privilegi opportuni! • Variante pkill: identifica in maniera simbolica i segnali ed i processi – pkill -KILL program • E da programma? – Si utilizza la syscall kill() 81
  • 82. Syscall kill() • Signature: int kill(pid_t pid, int sig) – Descrizione: invia il segnale identificato da sig al processo identificato da pid – Argomenti: ♦ IlPID del processo destinatario del segnale ♦ L'identificatore del segnale da inviare – Valore di ritorno: ♦0 -> tutto OK ♦ -1: si è verificato un errore 82
  • 83. Ricezione di segnali • Si utilizza la syscall signal(), che permette di associare ad un segnale una ben specifica funzione handler • Che prototipo deve avere la funzione handler? – void sig_handler(int signo) • Il file include <signal.h> definisce il tipo di dato sighandler_t come puntatore ad una funzione che vuole un intero e non ritorna niente (void) – typedef void (*sighandler_t) (int); 83
  • 84. Syscall signal() • Signature: sighandler_t signal(int signo, sighandler_t handler) – Descrizione: sostituisce l'azione corrente del segnale con l'azione definita dalla funzione handler – Argomenti: ♦ L'identificatore del segnale da gestire ♦ Un puntatore alla funzione handler – SIG_DFL: azione di default – SIG_IGN: ignorare il segnale – Puntatore ad una funzione effettiva – Valore di ritorno: ♦ Ilpuntatore alla precedente funzione handler ♦ SIG_ERR in caso di errore 84
  • 85. Handler di segnali: alcune note • Quando il kernel consegna un segnale, il processo può eseguire una qualunque porzione di codice – L'handler non può sapere quale • E' importante che l'handler non esegua codice “troppo complicato” – Tipicamente, imposta dei flag “volatile”, libera memoria, esce, non fa molto altro • L'handler deve modificare variabili che il processo non tocca MAI • I segnali possono essere rientranti – le syscall utilizzate all'interno dell'handler pure – man 7 signal 85
  • 86. Sincronizzazione processo padre-figlio • Il processo padre può decidere di aspettare il termine dell'esecuzione del processo figlio, per mezzo della syscall wait() • La syscall wait rimuove il descrittore del processo padre dalla coda di pronto fino a che il processo figlio non termina l'esecuzione • Quando il processo figlio termina l'esecuzione, ritorna un codice di uscita (exit status) al SO – =0: tutto OK (EXIT_SUCCESS) – =1: errore (EXIT_FAILURE) • Il SO consegna il codice di uscita alla syscall wait 86
  • 87. Scenario wait() tempestiva • Il processo padre crea Tabella padre processi un figlio con la fork() PID fork() Running • Entrambi i processi PID eseguono Running figlio concorrentemente 87
  • 88. Scenario wait() tempestiva • Il processo padre Tabella wait() processi invoca la wait() prima padre la morte del figlio, Blocked tempestivamente Running figlio • Il processo padre viene bloccato in attesa che il figlio termini la sua esecuzione 88
  • 89. Scenario wait() tempestiva • Ad un certo punto, il Tabella padre processi processo figlio termina la sua Running X esecuzione Zombie figlio • Il kernel imposta lo stato del figlio a Zombie – Processo figlio morto a tutti gli effetti – Il PCB è ancora presente nella tabella dei processi – PCB usato per fornire al padre il valore di uscita 89
  • 90. Scenario wait() tempestiva • Il kernel imposta a Tabella processi pronto il processo wait() padre padre, dal momento Running PID, che l'evento atteso si Running codice è verificato uscita • Il kernel invia un segnale SIGCHLD al padre (di solito ignorato) • Il processo padre ritorna ad eseguire dopo la wait() • Viene letto il codice di uscita del figlio 90
  • 91. Scenario wait() tardiva • Il processo padre crea Tabella padre processi un figlio con la fork() PID fork() Running • Entrambi i processi PID eseguono Running figlio concorrentemente 91
  • 92. Scenario wait() tardiva • Ad un certo punto, il Tabella padre processi processo figlio termina la sua Running X esecuzione Zombie figlio • Il kernel imposta lo stato del figlio a Zombie – Processo figlio morto a tutti gli effetti – Il PCB è ancora presente nella tabella dei processi – PCB usato per fornire al padre il valore di uscita 92
  • 93. Scenario wait() tardiva • Il processo padre Tabella wait() processi invoca la wait() dopo padre la morte del figlio, Running PID, X tardivamente Zombie codice uscita • Il kernel invia un segnale SIGCHLD al padre (di solito ignorato) • Viene usato il PCB del figlio per comunicare lo stato di uscita al padre • Viene eliminato il PCB del figlio 93
  • 94. Scenario wait() mai invocata • Il processo padre crea Tabella padre processi un figlio con la fork() PID fork() Running • Entrambi i processi PID eseguono Running figlio concorrentemente 94
  • 95. Scenario wait() mai invocata • Ad un certo punto, il Tabella padre processi processo figlio termina la sua Running X esecuzione Zombie figlio • Il kernel invia un segnale SIGCHLD al • Stato Zombie padre (di solito – Processo figlio morto a ignorato) tutti gli effetti • Il kernel imposta lo – Il PCB è ancora stato del figlio a presente nella tabella Zombie dei processi – PCB usato per fornire al padre il valore di uscita 95
  • 96. Scenario wait() mai invocata • Finché il padre Tabella X processi esegue, esisterà padre X sempre un PCB del Exiting X figlio in stato Zombie Zombie • Quando il padre termina l'esecuzione, vengono ripuliti entrambi i PCB 96
  • 97. System call wait() • Signature: pid_t wait(int *status) – Descrizione: sospende l'esecuzione del processo chiamante fino a quando uno dei suoi processi figli termina – Ingresso: puntatore ad un intero utilizzato per memorizzare lo “stato” del processo – Ritorno: ♦ Il PID del processo figlio terminato ♦ -1 in caso di errore 97
  • 98. System call wait() • Lo stato del processo può essere letto tramite delle macro opportune – WIFEXITED(status): restituisce 1 se il figlio è terminato normalmente (exit()), 0 altrimenti – WEXITSTATUS(status): restituisce il codice di uscita del processo figlio (gli 8 bit meno significativi di status: status & 255) – WIFSIGNALED(status): restituisce 1 se il figlio è stato terminato tramite un segnale, 0 altrimenti – WIFSTOPPED(status): restituisce 1 se il figlio è stato interrotto (SIGSTOP), 0 altrimenti – WIFCONTINUED(status): restituisce 1 se il figlio è stato ripristinato (SIGCONT), 0 altrimenti – ... e tante altre (man wait) 98
  • 99. System call waitpid() • Signature: pid_t waitpid(pid_t pid, int *status, int options) – Descrizione: sospende l'esecuzione del processo chiamante fino a quando uno dei suoi processi figli cambia stato – Ingresso: ♦ ilPID del processo (o dell'insieme di processi) da aspettare ♦ puntatore ad un intero utilizzato per memorizzare lo “stato” del processo ♦ maschera di bit contenente le opzioni di uso – Ritorno: ♦ Il PID del processo figlio terminato ♦ -1 in caso di errore (errno=ECHILD) 99
  • 100. System call waitpid() • Il primo argomento pid può assumere i seguenti valori: – -1: aspetta un qualunque processo figlio – 0: aspetta un qualunque processo figlio con group ID pari a quello del processo chiamante – >0: aspetta un qualunque processo figlio con PID = pid • Le opzioni sono le seguenti: – WNOHANG: ritorna immediatamente se nessun figlio è uscito (non aspetta) ♦ torna 0 se il padre ha figli, -1 altrimenti – WUNTRACED: considera come cambio di stato anche l'interruzione (SIGSTOP) 100
  • 101. Caricamento di immagini • UNIX mette a disposizione una famiglia di funzioni (exec()) per sostituire l'immagine di un processo padre con quella di un eseguibile • La sostituzione è efficiente – Non si copia l'intero contenuto della memoria secondaria in memoria – Si associano blocchi di memoria principale a blocchi di memoria secondaria (memory mapping) – Si carica il blocco in memoria centrale solo quando viene utilizzato dal processore 101
  • 102. Caricamento di immagini Spazio indirizzamento Memoria secondaria processo (RAM) (periferica) Pagina 1 Pagina 2 ... Pagina n Blocco 1 Blocco 2 Blocco n 102
  • 103. Caricamento di immagini Spazio indirizzamento Memoria secondaria processo (RAM) (periferica) Blocco 1 Pagina 2 ... Pagina n Blocco 1 Blocco 2 Blocco Sostituzione di codice: n le pagine vengono CPU sostituite quando richieste dal processore. 103
  • 104. Syscall execl • Signature: int execl(const char *path, const char *arg, ...) – Descrizione: carica l'immagine eseguibile del programma di nome path, passando i parametri – Argomenti: ♦ Un puntatore alla stringa contenente il percorso assoluto dell'eseguibile ♦ Una lista di stringhe (terminata con NULL), che saranno assegnate ad argv[0], argv[1], ... – Valore di ritorno: ♦ -1 in caso di errore • execl() è una funzione variadica (ammette un numero variabile di argomenti) 104
  • 105. Famiglia funzioni exec() • int execlp(const char *file, const char *arg, ...); • int execle(const char *file, const char *arg, ..., char * const envp[]); • int execv(const char *file, const char *argv[]); • int execvp(const char *file, const char *argv[]); • int execle(const char *file, const char *arg[], char * const envp[]); 105
  • 106. Esecuzione semplificata • Esiste una procedura estremamente semplificata per l'esecuzione di processi • Se si vuole eseguire un comando secco (tipicamente, un comando di shell), senza necessità di generare più figli, si può usare la chiamata system() • Cosa fa system()? • Padre: – fork() di un processo figlio – wait() per aspettare l'uscita del figlio • Figlio: – execv() di una immagine 106
  • 107. Funzione system() • Signature: int system(const char *command) – Descrizione: crea un processo figlio ed esegue il comando “/bin/sh -c comando”, dove comando è la stringa puntata da command – Argomenti: ♦ Un puntatore alla stringa contenente il comando ♦ Valore di ritorno: ♦ Il codice di stato della wait() ♦ -1 in caso di errore • Esercizio: implementare la system() usando le chiamate fork(), execv(), waitpid() 107
  • 108. Una piccola avvertenza • Durante l'esecuzione del comando tramite system, nel processo figlio – il segnale SIGCHLD è bloccato (sigprocmask) – i segnali SIGINT e SIGQUIT sono ignorati • Se il programma è lanciato da terminale, un CTRL-C viene propagato a padre e figlio – Ma non sempre il programma è lanciato da terminale... • Se la funzione system() è invocata all'interno di un ciclo, bisogna esplicitamente controllare lo stato di uscita del figlio 108
  • 109. Utenti e gruppi: modello di protezione • Il modello UNIX prevede l'attribuzione di processi e file ad utenti e gruppi di lavoro • Utente: – Astrazione di una singola persona – Può lanciare processi e gestire file – Identificato da uno User Id (UID), numero intero non negativo – E' associato ad uno username e ad una password per la verifica delle credenziali – Database utenti memorizzato in /etc/passwd – Un utente (superutente, root) ha pieni poteri di accesso alle risorse del sistema (processi, file) 109
  • 110. Utenti e gruppi: modello di protezione • Il modello UNIX prevede l'attribuzione di processi e file ad utenti e gruppi di lavoro • Gruppo (di lavoro): – Astrazione di un gruppo di persone che lavorano per uno stesso obiettivo – Ciascun utente può far parte di più gruppi, ma ne usa uno alla volta (gruppo primario) – Possono condividere accessi a file – Identificato da un Group Id (GID), numero intero non negativo – E' associato ad un groupname e ad una password per la verifica delle credenziali – Database utenti memorizzato in /etc/group 110
  • 111. Utenti e gruppi: permessi dei file • Come impatta il modello di protezione sui file? • Semplice schema a permessi • Tre distinte categorie di utenti: – User: UID dell'utente creatore di un file – Group: GID primario dell'utente al momento della creazione del file – Others: il resto del mondo • Tre distinte categorie di azioni su file: – Read: è possibile leggere da file – Write: è possibile scrivere su file – eXecute: è possibile eseguire il file 111
  • 112. Utenti e gruppi: permessi dei file • A ciascun file è associata una maschera di bit contenente le azioni permesse (r,w,x) per ciascuna tipologia di utenti (u,g,o) • La maschera di bit memorizza in maniera compatta chi può accedere come al file • Diversi tipi di rappresentazione: – Stringa: rwxrwxr-x – Ottale: 775 – Azione: ugo+rwx, o-w 112
  • 113. Utenti e gruppi: diritti dei processi • Come impatta il modello di protezione sui processi in esecuzione sulla macchina? • In un sistema UNIX, i diritti di un processo coincidono molto spesso con i privilegi di accesso ai file – Filosofia UNIX: tutto ciò che si esegue è un processo, tutto ciò che si rappresenta è un file • Gli UID e GID di un processo sono quelli utilizzati per il confronto con la maschera di bit dei file • Ma come fa un processo ad essere associato ad un UID e ad un GID? 113
  • 114. Utenti e gruppi: diritti dei processi • Le cose, ovviamente, non sono così semplici • Un processo UNIX si porta appresso quattro (!) UID e quattro GID diversi per regolare i diritti di acceso ai file da parte di un processo – Filesystem User ID – Real User ID – Effective User ID – Saved User ID • La descrizione seguente vale non solo per gli UID, ma anche per i GID! 114
  • 115. Utenti e gruppi: Filesystem User ID • Il Filesystem User ID (UID) è lo UID associato al file su disco • Dichiara solamente chi ha scritto originariamente il file su disco, nient'altro! – beh, dichiara anche I permessi di accesso... – ... ma nient'altro che riguardi l'esecuzione dei processi! 115
  • 116. Utenti e gruppi: Real User ID • Il Real User ID (UID) è lo UID dell'utente che ha eseguito il processo • Il Real User ID può essere (e solitamente è) diverso dal Filesystem User ID – Filesystem: chi ha scritto il file su disco – Real: chi lo sta eseguendo ora • Il Real User ID di un processo viene impostato a quello del suo padre – Shell: imposta il Real User ID a quello dell'utente che la sta eseguendo – Tutti i comandi (figli) eseguono con quell'UID • Il superutente può impostare il Real User ID a qualunque valore, gli utenti normali no 116
  • 117. Utenti e gruppi: Effective User ID • L'Effective User ID (EUID) è lo UID effettivo con cui il processo sta eseguendo • Tutti i controlli di accesso (a file) avvengono tramite l'EUID • L'EUID viene ereditato dal processo padre • Un momento: ma non c'era già il Real User ID? • Sì, ed in effetti, solitamente, Real User ID ed Effective User ID coincidono • E allora a che serve differenziare in Real User ID ed Effective User ID? – A fare cose paranormali con i poteri di un utente normale 117
  • 118. Utenti e gruppi: Effective User ID • Ciascun file ha, in realtà, svariati altri bit nella bitmask dei permessi • Tali bit sono usati per specificare particolari proprietà di un file o di una directory • Una proprietà particolare è il Set User ID (SUID) bit, impostabile alla stregua di un qualunque permesso – chmod +s nome_file, chmod 4xyz nome_file • Quando viene avviato un eseguibile con SUID, il kernel imposta l'EUID del file al filesystem UID – Esecuzione con i diritti del creatore, non dell'utente! E se il creatore è root... 118
  • 119. Utenti e gruppi: Effective User ID • Gli utenti normali possono impostare il valore di EUID al Real UID oppure al Saved UID (introdotto a breve) • Il superutente può impostare l'EUID al valore che desidera • Come trovare gli eseguibili SUID? – find / -perm -4000 2>/dev/null • Esempio: passwd 119
  • 120. Utenti e gruppi: Saved User ID • Il Saved User ID è una copia fedele dell'Effective User ID di un processo, effettuata nell'istante in cui questo effettua una exec() • Utilizzato per tenere traccia del vecchio Effective User ID prima di eseguire una immagine (potenzialmente SUID) • Il Saved User ID è inizialmente ereditato dal processo padre • Utenti non privilegiati non possono modificare il Saved User ID • Il superutente può impostare il Saved User ID ad un qualunque valore 120
  • 121. Utenti e gruppi: setuid() • Signature: int setuid(uid_t uid) Signature: int setgid(gid_t gid) – Descrizione: ♦ Se EUID=0 (root), imposta Real, Effective e Saved User Id a uid (qualunque) ♦ Se EUID>0 (non root), imposta Effective User Id ad uid (uid=Real oppure uid=Saved) – Argomenti: ♦ Il nuovo User ID (uid) – Valore di ritorno: ♦ 0: tutto OK ♦ -1 in caso di errore 121
  • 122. Utenti e gruppi: seteuid() • Signature: int seteuid(uid_t euid) Signature: int setegid(gid_t egid) – Descrizione: ♦ Se EUID=0 (root), imposta l'Effective User Id a euid (qualunque) ♦ Se EUID>0 (non root), imposta l'Effective User Id ad uid (uid=Real oppure uid=Saved) – Comportamento identico a setuid() – Argomenti: ♦ Il nuovo Effective User ID (euid) – Valore di ritorno: ♦ 0: tutto OK ♦ -1 in caso di errore 122
  • 123. Utenti e gruppi: recupero UID • Famiglia di funzioni get...id() • Non danno mai un errore • uid_t getuid(void); • uid_t getgid(void); • uid_t geteuid(void); • uid_t getegid(void); 123
  • 124. Una piccola applicazione • Il SO Debian definisce il gruppo games come il gruppo dei videogiocatori – Tutti gli eseguibili dei videogiochi vengono installati nella directory /usr/games – Permessi: rwx r-x r-x (755) – Utente: root – Primary group: ♦ root (nel caso in cui non si scrivano file) ♦ games, con setgid (nel caso in cui si scrivano file) • In quest'ultimo caso, chiunque esegua un videogioco prende il gruppo effettivo games – L'user effettivo rimane sempre quello normale 124
  • 125. Una piccola applicazione • L'applicazione videogame scrive, come gruppo games: – Gli high score (platform, sparatutto) – L'output delle partite (giochi da tavolo) • L'applicazione vorrebbe scrivere gli altri file col gruppo primario dell'utente che ha lanciato l'eseguibile: – Traccie di debug • Come si ottiene questo? 125
  • 126. Una piccola applicazione • All'inizio del programma, vengono salvati i Real ed Effective UID e GID: ruid = getuid(); euid = geteuid(); rgid = getgid(); egid = getegid(); • Successivamente, si reimpostano UID e GID in modo tale che l'utente possa scrivere file col proprio gruppo primario: setuid(ruid); setgid(rgid); • Qui, rgid è il GID dell'utente normale; ora sto scrivendo I file come utente normale 126
  • 127. Una piccola applicazione • Prima di scrivere gli high score, imposto setuid(euid); setgid(egid); • Ora, il GID è di nuovo quello effettivo (games): write_high_scores(&players); • Successivamente, reimposto UID e GID a quelli “normali” setuid(ruid); setgid(rgid); 127
  • 128. Job Control • Task di una shell moderna: – Lettura comando da terminale – Creazione ed esecuzione dei relativi processi • Spesso il comando immesso è complesso, e consta di più “comandi” (cd /src/dir && tar cf - . ) | ( cd /dst/dir && tar xf -) • Servono meccanismi per operare su “gruppi” di processi: – Identificazione – Interruzione, terminazione – Sospensione, ripristino • Modello di Job Control 128
  • 129. Job Control • Job Control: insieme di tutti i meccanismi necessari per: – identificare – sospendere e riesumare – eseguire attaccati ad un terminale – eseguire staccati da un terminale un insieme di processi • Tale esigenza nasce dai vecchi terminali seriali – Avevano un solo “schermo” – Ci si poteva attaccare un solo comando per volta (foreground) – Gli altri comandi eseguivano staccati dal terminale (background) 129
  • 130. Job Control • Job Control: insieme di tutti i meccanismi necessari per: – identificare – sospendere e riesumare – eseguire attaccati ad un terminale – eseguire staccati da un terminale un insieme di processi • Tale esigenza nasce dai vecchi terminali seriali – Avevano un solo “schermo” – Ci si poteva attaccare un solo comando per volta (foreground) – Gli altri comandi eseguivano staccati dal terminale (background) 130
  • 131. Gruppi di processi • I processi sono suddivisi in gruppi di processi (process group) • Un gruppo di processi è un insieme di processi che possono essere segnalati tutti insieme – Segnali: Terminazione, interruzione, ripristino – Processi: i componenti di una pipeline • Ciascun processo fa parte di un process group • Ciascun process group: – ha un processo detto “process group leader”; è l'ultimo processo in una pipeline – è identificato da un process group ID (PGID), pari al PID del process group leader – esiste fino a quando ha almeno un elemento 131
  • 132. Sessioni • Quando un utente effettua un login, il processo login crea una nuova sessione • Sessione: un insieme di process group • All'inizio ho una solo process group di un solo processo (la shell di login) • Tale processo prende il nome di session leader • Il PID del processo session leader è usato come session ID (identifica la sessione) • Ciascuna sessione ha associato un dispositivo terminale (fisico o virtuale) di controllo, che gestisce le operazioni di I/O da e verso la sessione 132
  • 133. Foreground e Background PG • I process group all'interno di una sessione sono suddivisi in due categorie: – Un foreground process group – Uno o più background process group • Il foreground process group è l'unico gruppo di processi ad essere attaccato direttamente al terminale sia in ingresso che in uscita – Si può interagire con i processi in esecuzione tramite la tastiera • I background process group sono attaccati al terminale solamente in uscita – Possono solo scrivere sul terminale, non possono ricevere dati da terminale 133
  • 134. Terminali • Diversi tipi di terminale: – Veri terminali fisici (VT100, VT102) attaccati via connessioni seriali (/dev/ttyS0) – Emulatore di terminale classico in testo, fornito dal kernel (/dev/tty1) e prenotato da getty ♦ Alt-F1 + getty->login->bash – Pseudo terminale in cui il kernel fornisce un minimo supporto (/dev/pts/0) ed un processo arbitrario si sostituisce all'emulatore di terminale classico ♦ ssh -t, xterm, gnome-terminal, kterm ♦ Automazione domanda-risposta con uno (pseudo) terminale: expect – Chatscript di login del modem 134
  • 135. Interazioni con il terminale • In che modi si può interagire con il terminale, tramite la tastiera? – Terminazione dell'emulatore di terminale: viene inviato un segnale SIGQUIT a tutti i processi facenti parte del foreground process group – Disconnessione rete/seriale terminale fisico: viene inviato un segnale SIGHUP (Hangup) a tutti i processi facenti parte del foreground process group ♦ Window manager testuale screen: intercetta il segnale e conserva lo stato delle finestre – Interruzione pipeline (CTRL-C): viene inviato un segnale SIGINT a tutti i processi facenti parte del foreground process group 135
  • 136. Interazioni con il terminale • In che modi si può interagire con il terminale, tramite la tastiera? – Sospensione pipeline (CTRL-Z): viene inviato un segnale SIGTSTOP a tutti i processi facenti parte del foreground process group – Ripristino pipeline in foreground (%, fg): viene inviato un segnale SIGCONT a tutti i processi facenti parte del foreground process group sospeso 136
  • 137. p Un modello a sessioni e gruppi login Session Session Terminale leader Login shell di controllo stdout stderr BG PG PG FG PG PG BG PG leader leader stdin stdout PG stderr leader stdout stderr 137
  • 138. Gestione dei gruppi e delle sessioni • Esecuzione di un process group in foreground – Si lancia una pipeline normalmente ls -lR / | grep passwd | less -Mr • Esecuzione di un process group in background – Si termina una pipeline col simbolo & ls -lR / | grep passwd > output.txt 2>&1 & – Viene stampata una riga del tipo [1] 25647 – 1: ID del job inviato – 25647: process group ID (PiD del processo leader del gruppo, ossia l'ultimo della pipeline, grep) 138
  • 139. Gestione dei gruppi e delle sessioni • Visione dello stato dei process group di una sessione: comando jobs – jobs -l: elenco completo dei process group, con process group ID relativi e stato di esecuzione – jobs -p: elenco dei process group ID • Sospensione del process group in foreground: – CTRL-Z • Ripristino in background di un process group sospeso: – bg %job_id (bg in per un process group unico) • Ripristino in foreground di un process group sospeso: – fg %job_id (fg o % per un process group unico) 139
  • 140. Creazione di una sessione • Signature: pid_t setsid(void) – Descrizione: ♦ Crea una nuova sessione ♦ Crea un nuovo process group all'interno della sessione ♦ Imposta il processo chiamante a session e a group leader ♦ Utilizzato dalle shell e dai demoni – Argomenti: nessuno – Valore di ritorno: ♦ Il session ID della sessione, se tutto OK ♦ -1 in caso di errore • Comando setsid 140
  • 141. Ottenimento session ID • Signature: pid_t getsid(pid_t pid) – Descrizione: ritorna il session ID della sessione in cui si trova il processo identificato da pid – Argomenti: ♦ Il pid del processo (0: processo chiamante) – Valore di ritorno: ♦ Il session ID della sessione, se tutto OK ♦ -1 in caso di errore 141
  • 142. Impostazione di un process group ID • Signature: int setpgid(pid_t pid, pid_t pgid) – Descrizione: imposta il process group ID del processo identificato da pid a pgid ♦ Pid deve riferirsi al processo invocante o ad un suo figlio che non ha invocato exec() ♦ Pid deve essere nella stessa sessione del processo invocante ♦ Pid non deve riferirsi ad un session leader – Argomenti: ♦ Il pid del processo considerato ♦ Il pgid considerato – Valore di ritorno: ♦ 0: tutto OK ♦ -1 in caso di errore 142
  • 143. Ottenimento session ID • Signature: pid_t getpgid(pid_t pid) – Descrizione: ritorna il process group ID del processo identificato da pid – Argomenti: ♦ Il pid del processo (0: processo chiamante) – Valore di ritorno: ♦ Il processo group ID della sessione, se tutto OK ♦ -1 in caso di errore 143
  • 144. Demoni UNIX • Il demone (daemon) è un processo che: – esegue come figlio diretto di init – non è connesso ad alcun terminale – esegue in background • Etimologia: Maxwell's demon (1867) http://en.wikipedia.org/wiki/Maxwell%27s_demon • Scopi: – Gestione task di sistema – Processo server: ascolta richieste, genera figli che producono risposte • Solitamente, un demone è avviato da root o da un utente dedicato (apache) 144
  • 145. Passi di creazione di un demone • Step 1: il processo invoca una fork() – Viene creato un nuovo processo figlio – Tale processo diventerà il demone • Step 2: nel padre, si invoca la exit() – Il padre esce e rende orfano il figlio – Il figlio diventa figlio di init – Il figlio non è un process group leader • Step 3: il processo figlio invoca setsid() – Il figlio diventa un session leader (non essendo un process group leader, può diventarlo) – Viene anche creato un process group di cui il processo figlio è leader – Il figlio non ha un terminale di controllo 145
  • 146. Passi di creazione di un demone • Step 4: il figlio invoca chdir(“/”) – Viene impostata la directory di lavoro a / – Altrimenti la directory ereditata dal padre potrebbe essere dovunque (dipende da dove è stato invocato il processo padre) – Tale directory non potrebbe essere più smontata, in quanto in uso (reference!) da parte del demone – Il demone tende a durare per tutto il ciclo di vita della macchina – O ammazzo il demone, o non smonto il filesystem contenente la directory da cui è stato invocato il demone 146
  • 147. Passi di creazione di un demone • Step 5: il figlio imposta la maschera dei permessi a 0 (opzionale) • Step 6: il figlio chiude tutti i descrittori di file – Non servono – stdin, stdout, stderr non servono perché il demone non è connesso ad alcun terminale – Gli altri descrittori non servono perché il demone, solitamente, non fa I/O, bensì crea processi figli per la gestione di richieste • Step 7: i descrittori stdin, stdout, stderr vengono redirezionati a /dev/null (o a qualche logfile) 147