View
1.868
Download
0
Category
Preview:
Citation preview
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)
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
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)
4
Esecuzione interleaved
Gestoreprocessi
Memoriaprincipale
Processo A
Processo B
Processo C
ProgramCounter
5
Esecuzione interleaved
Gestoreprocessi
Memoriaprincipale
Processo A
Processo B
Processo C
ProgramCounter
Indirizzi PC
a + 0a + 2a + 6a + 10
Scade l'intervallodi tempo assegnatoal processo A
6
Esecuzione interleaved
Gestoreprocessi
Memoriaprincipale
Processo A
Processo B
Processo C
ProgramCounter
Indirizzi PC
g + 100g + 102g + 106g + 110g + 114
Il gestore dei processisceglie come prossimoprocesso da eseguireil processo B, e neprepara l'esecuzione
7
Esecuzione interleaved
Gestoreprocessi
Memoriaprincipale
Processo A
Processo B
Processo C
ProgramCounter
Indirizzi PC
b + 32b + 36b + 40
Il processo B siinterrompe perchédeve effettuare unaoperazione di I/O
8
Esecuzione interleaved
Gestoreprocessi
Memoriaprincipale
Processo A
Processo B
Processo C
ProgramCounter
Indirizzi PC
g + 100g + 102g + 106g + 110g + 114
Il gestore dei processisceglie come prossimoprocesso da eseguireil processo C, e neprepara l'esecuzione
9
Esecuzione interleaved
Gestoreprocessi
Memoriaprincipale
Processo A
Processo B
Processo C
ProgramCounter
Indirizzi PC
c + 248c + 356c + 360c + 364
Il processo C terminala sua esecuzione
10
Esecuzione interleaved
Gestoreprocessi
Memoriaprincipale
Processo A
Processo B
Processo C
ProgramCounter
Indirizzi PC
g + 100g + 102g + 106g + 110g + 114
Il gestore dei processisceglie come prossimoprocesso da eseguireil processo A, e neprepara l'esecuzione
11
Esecuzione interleaved
Gestoreprocessi
Memoriaprincipale
Processo A
Processo B
Processo C
ProgramCounter
Indirizzi PC
a + 14a + 18a + 22a + 56
Il processo A siblocca perché richiedeuna operazione di I/O
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
13
Rappresentazione di un processoModello a due stati
not running runningcreazione terminazione
blocking
dispatching
Diagramma di accodamento
coda processi pronti CPUdispatchingcreazione terminazione
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
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”
16
Modello a tre statiModello a tre stati
ready runningcreazione terminazione
scadenzaintervallo
tempo
dispatching
blocked
attesaevento
completamentoevento
Transizioniready => 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
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
18
Stati aggiuntiviStato aggiuntivo new
new readycreazione terminazioneadmit
Strutture datiper il processoallocate edinizializzate
Stato aggiuntivo exit
running exitterminazione
Rilascio strutturedati allocate per ilprocesso
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
20
Modello a cinque stati
new exit
ready running
blocked
ammesso
interruzione
dispatching
uscita
attesa I/Oattesa evento
completamento I/Overifica evento
21
Modello a cinque stati
Coda processi pronti
Diagramma di accodamento
CPU
I/O Coda I/O Richiesta I/O
quanto di tempoesaurito
generazioneprocesso figlio
attesainterruzione
processo figlioin esecuzione
occorrenzainterruzione
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
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
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
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)
26
Modello a cinque stati con swapping
new exit
ready running
blocked
ammesso
interruzione
dispatching
uscita
attesa I/Oattesa evento
completamento I/Overifica evento
blockedsuspended
readysuspended
Rimozione dallamemoria (swap out)
verifica evento
Ripristino inmemoria (swap in)
verifica evento
27
Modello a cinque stati con swapping
Coda processi pronti
Diagramma di accodamento(swapping)
CPU
I/O Coda I/O Richiesta I/O
Processi parzialmenteeseguiti e sottoposti
a swap
swap outswap in
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
29
Gestione processi:strutture di controllo
• Per gestire l'esecuzione dei processi, il SO mantiene informazioni sui processi stessi e sulle risorse utilizzate
Memoria
Dispositivi
File
Risorsedi sistema
Processi
Strutture datidi controllo
Tabella dimemoria
...
Tabella dimemoria
...Tabella dimemoria
Tabella deiprocessi
P1
Pn
Immagine P1
Immagine Pn
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)
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
32
Immagine di un processo
Stack segmentStack
programma
Indirizzi alti
Indirizzi bassi
Lo stack cresce verso il basso
“Buco” nello spaziodi indirizzamento
Heap(malloc) L'heap cresce verso alto
Data segments BSS
Data
CodiceeseguibileText segment
Variabili non inizializzate(vengono impostate a 0)
Variabili globali inizializzate
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
34
Process Control Block
puntatore
identificatore di processo (PID)
registri
contatore di programma
stato del processo
contatore di programma
elenco dei file aperti
...
Process Control Block
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
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
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
38
Code di scheduling
coda deiprocessi
pronti
Primo elemento
Ultimo elemento registri
...
PCB7
registri
...
PCB2
coda unità
CDROM
Primo elemento
Ultimo elemento
codaunitàdischi
Primo elemento
Ultimo elemento registri
...
PCB3
registri
...
PCB14
registri
...
PCB6
codaterminale
0
Primo elemento
Ultimo elemento registri
...
PCB3
39
Scheduler• Componente del SO che seleziona i processi
dalle code• Due tipi di scheduling:
– Job scheduling– CPU scheduling
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)
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)
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
processo2.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
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
44
Modalità esecuzione e context switchp
Kernel mode
User mode
Processo
syscall()
Meccanismo per ilcambio di modo
service_call()
Hardware
Chiamatabloccante
Scheduler
Processo
Invocazionescheduler
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
46
Context switchProcesso P
0Processo P
1Sistema operativo
Salva lo stato in PCB0
Ripristina lo stato da PCB1
Salva lo stato in PCB1
Ripristina lo stato da PCB1
47
Context switchProcesso P
0Processo P
1Sistema operativo
Salva lo stato in PCB0
Ripristina lo stato da PCB1
Salva lo stato in PCB1
Ripristina lo stato da PCB1
Interruzione o syscall bloccante
48
Context switchProcesso P
0Processo P
1Sistema operativo
Salva lo stato in PCB0
Ripristina lo stato da PCB1
Salva lo stato in PCB1
Ripristina lo stato da PCB1
Interruzione o syscall bloccante
49
Context switchProcesso P
0Processo P
1Sistema operativo
Salva lo stato in PCB0
Ripristina lo stato da PCB1
Salva lo stato in PCB1
Ripristina lo stato da PCB1
Interruzione o syscall bloccante
50
Context switchProcesso P
0Processo P
1Sistema operativo
Salva lo stato in PCB0
Ripristina lo stato da PCB1
Salva lo stato in PCB1
Ripristina lo stato da PCB1
Interruzione o syscall bloccante
Interruzione o syscall bloccante
51
Context switchProcesso P
0Processo P
1Sistema operativo
Salva lo stato in PCB0
Ripristina lo stato da PCB1
Salva lo stato in PCB1
Ripristina lo stato da PCB0\
Interruzione o syscall bloccante
Interruzione o syscall bloccante
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
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
54
Modello processi UNIX
preempted
Usermode
running
Kernelmode
running
exited zombie
Sleeping inmemory
SleepingSwapped out
ReadySwapped out
ready
new
55
Immagine di un processo
Testo
Dati
Stack utente
Memoria condivisa
Contesto utente
Program counter
Registro di stato del processore
Stack pointer
Registri generali
Contesto registri
Entry nella tabella dei processi
U area (area utente)
Tabella indirizzamento (memoria virtuale)
Stack del kernel mode
Contesto sistema
56
Entry della tabella dei processiStato del processoPuntatori alla U areaDimensioni del processoIdentificatori 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)
57
User Area (U area)Puntatore alla entry della tabella dei processiDimensioni del processoIdentificatori d’utente (effettivo)Array per i gestori di segnaliTerminaleCampo di erroreParametri di I/O (es. indirizzi dei buffer)Timer (monitoring in modalita’ utente)Valore di ritorno di system callsTabella dei descrittori di file
58
Modello di avvio processi UNIX
• Shell tipiche:– Bourne Again SHell– Bourne– C– Korn
Comandi di shell: nome-comando [ arg1, ..., arg
n ]
Kernel(PID=0)
init(PID=1) getty login shell
getty login shell
getty login shell
Legge/etc/inittab
Legge/etc/passwd
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
60
Albero di processi UNIX
kernel
swapperpage daemon init
utente 1 utente 2 utente 3
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
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
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
stack
heap
dati
testo
fork()
Processo figlio
stack
heap
dati
testo
Entrambi i processi ripartono dall'istruzione
successiva alla fork()
nel testo
64
Utilizzi del meccanismo di forking• Creazione di
comandi a catena (pipeline)
find . -name '*.c' -print | wc -l
• Gestione di servizi (request serving)– Web server– FTP server– “XYZ” server
shell
s
find
f
wc
w
fork() fork()pipe()
output
Serverprocess
S
fork() fork()
Childprocess
C
Childprocess
C
richieste
risposta risposta
exec() exec()
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)
66
Cattivi utilizzi del forking: fork bomb
bomb
b
bomb
b
bomb
b
...
bomb
b
bomb
b
bomb
b
...
bomb
b
bomb
b
bomb
b
...
...
... ... ... ...
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 copiawhile ( 1 ) {
x=malloc(1048576); /* 1MB */*x = 0; /* forza il Copy On Write */fork();
}
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
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
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
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
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)
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
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
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)
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
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)
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
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
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...
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()
82
Syscall kill()• Signature: int kill(pid_t pid, int sig)
– Descrizione: invia il segnale identificato da sig al processo identificato da pid
– Argomenti:♦ Il PID del processo destinatario del segnale♦ L'identificatore del segnale da inviare
– Valore di ritorno:♦ 0 -> tutto OK♦ -1: si è verificato un errore
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);
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:♦ Il puntatore alla precedente funzione handler♦ SIG_ERR in caso di errore
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
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
87
Scenario wait() tempestiva
padre
figlio
fork()
• Il processo padre crea un figlio con la fork()
• Entrambi i processi eseguono concorrentemente
Running
Tabellaprocessi
Running
PID
PID
88
Scenario wait() tempestiva
padre
• Il processo padre invoca la wait() prima la morte del figlio, tempestivamente
• Il processo padre viene bloccato in attesa che il figlio termini la sua esecuzione
Blocked
Tabellaprocessiwait()
Runningfiglio
89
Scenario wait() tempestiva
padre
figlio
• Ad un certo punto, il processo figlio termina la sua esecuzione
• 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
Running
Tabellaprocessi
ZombieX
90
Scenario wait() tempestiva
padre
• Il kernel imposta a pronto il processo padre, dal momento che l'evento atteso si è verificato
• 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
Running
Tabellaprocessi
RunningPID,
codiceuscita
wait()
91
Scenario wait() tardiva
padre
figlio
fork()
• Il processo padre crea un figlio con la fork()
• Entrambi i processi eseguono concorrentemente
Running
Tabellaprocessi
Running
PID
PID
92
Scenario wait() tardiva
padre
figlio
• Ad un certo punto, il processo figlio termina la sua esecuzione
• 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
Running
Tabellaprocessi
ZombieX
93
Scenario wait() tardiva
padre
• Il processo padre invoca la wait() dopo la morte del figlio, tardivamente
• 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
Running
Tabellaprocessi
PID,codiceuscita
wait()
ZombieX
94
Scenario wait() mai invocata
padre
figlio
fork()
• Il processo padre crea un figlio con la fork()
• Entrambi i processi eseguono concorrentemente
Running
Tabellaprocessi
Running
PID
PID
95
Scenario wait() mai invocata
padre
figlio
• Ad un certo punto, il processo figlio termina la sua esecuzione
• Il kernel invia un segnale SIGCHLD al padre (di solito ignorato)
• Il kernel imposta lo stato del figlio a Zombie
Running
Tabellaprocessi
ZombieX• Stato 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
96
Scenario wait() mai invocata
padre
• Finché il padre esegue, esisterà sempre un PCB del figlio in stato Zombie
• Quando il padre termina l'esecuzione, vengono ripuliti entrambi i PCB
Exiting
Tabellaprocessi
ZombieX
XX
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
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)
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:♦ il PID 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)
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)
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
102
Caricamento di immagini
Pagina 1
Spazio indirizzamentoprocesso (RAM)
Pagina 2
...
Pagina n Blocco1
Memoria secondaria (periferica)
Blocco2
Bloccon
103
Caricamento di immagini
Blocco 1
Spazio indirizzamentoprocesso (RAM)
Pagina 2
...
Pagina n Blocco1
Memoria secondaria (periferica)
Blocco2
Bloccon
CPU
Sostituzione di codice:le pagine vengonosostituite quando richiestedal processore.
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)
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[]);
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
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()
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
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)
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
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
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
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?
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!
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!
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
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
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...
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
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
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
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
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);
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
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?
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
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);
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
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 terminaleun 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
Job Control• Job Control: insieme di tutti i meccanismi
necessari per:– identificare– sospendere e riesumare– eseguire attaccati ad un terminale– eseguire staccati da un terminaleun 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)
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
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
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
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
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
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
137
Un modello a sessioni e gruppic
login
l
Login shellSessionleader
Session
p
BG PG BG PG FG PG
Terminaledi controllo
stdin
stdoutstderr
stdoutstderr
stdoutstderr
PGleader
PGleader
PGleader
138
Gestione dei gruppi e delle sessioni• Esecuzione di un process group in foreground
– Si lancia una pipeline normalmentels -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)
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)
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
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
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
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
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)
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
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
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)
Recommended