Sei sulla pagina 1di 6

Sistemi Operativi A - Anno accademico 2001-2002

Problemi risolti

Problema 1

In un sistema time-sharing con priorità sono presenti quattro processi P1 - P4, nel seguente stato:
P1, P3 pronti; P2 in esecuzione; P4 in attesa su operazione di I/O
I processi P1, P2 e P4 hanno priorità uguale, e più alta del processo P3. Descrivere come cambia lo
stato del sistema se, a partire da questa situazione, si verificano, nell'ordine, gli eventi seguenti:
a. trascorre un quanto di tempo
b. si completa l’operazione di I/O per P4
c. trascorre un quanto di tempo
d. il processo in esecuzione chiede una operazione di I/O
e. il processo in esecuzione termina

Soluzione

Lo stato di modifica come segue:


a. P2 va in stato di pronto davanti a P3 (P3 è meno prioritario), P1 va in esecuzione
b. P4 va in stato di pronto in coda tra P2 e P3
c. P1 va in pronto in coda tra P4 e P3, P2 va in esecuzione
d. P2 va in stato di attesa, P4 (primo processo pronto) va in esecuzione
e. P4 termina, P1 va in esecuzione, P3 rimane in stato di pronto, P2 è in attesa di I/O

Problema 2

In un sistema real-time (con priorità) sono presenti quattro processi P1 - P4, nel seguente stato:
P1 in esecuzione; P2, P3 pronti; P4 in attesa su operazione di I/O
I processi P1 e P4 hanno priorità uguale, e più alta della priorità dei processi P2 e P3. Descrivere come
cambia lo stato del sistema se, a partire da questa situazione, si verificano, nell'ordine, gli eventi
seguenti:
a. trascorre un quanto di tempo
b. Il processo in esecuzione termina
c. si completa l’operazione di I/O per il processo P4
d. il processo in esecuzione chiede una operazione di I/O
e. trascorre un quanto di tempo

Soluzione

Lo stato di modifica come segue:


a. P1 rimane in esecuzione, poiché gli altri due processi pronti sono meno prioritari. Lo scadere di un
quanto di tempo non ha effetto in un sistema real-time a meno che non comporti la modifica delle
priorità (priorità dinamiche)
b. P1 termina e va in esecuzione il processo P2, primo della coda dei processi pronti e della stessa
priorità di P3.
c. P4 va in stato di pronto ma poiché è più prioritario di P2 e P3 va immediatamente in esecuzione,
mentre il processo P2 va in stato di pronto in coda a P3.
d. P4 va in stato di attesa e l'esecuzione passa al processo P3
e. Essendo P2 alla stessa priorità di P3, l'esecuzione di P3 non viene interrotta. Usualmente però i
sistemi real-time introducono uno scheduling round-robin tra i processi alla stessa priorità per
evitare il monopolio della CPU da parte di un solo processo a scapito degli altri della stessa
priorità. Andrebbe quindi in esecuzione il processo P2 mentre P3 verrebbe portato nella coda dei
processi pronti, al livello di priorità che gli compete (in questo caso è l'unico processo pronto).

1
Problema 3

Cinque processi (da P1 a P5) chiedono l’esecuzione contemporaneamente. Il loro tempo stimato di
CPU burst è di 90, 50, 40, 30 e 70 millisecondi, e i processi sono alla stessa priorità. Per le politiche di
scheduling elencate di seguito, determinare il tempo di attesa per ciascun processo, e dire quale è la
soluzione che minimizza il tempo medio di attesa:
- First Come First Served
- Shortest Process Next
- Round Robin, con quanto di tempo di 15 mSec

Soluzione

Per le politiche FCFS e SPN il tempo di attesa di ogni processo è la somma dei tempi di esecuzione dei
processi che lo precedono.
FCFS: P1 = 0
P2 = 90 mS
P3 = 90 + 50 = 140 mS
P4 = 90 + 50 + 40 = 180 mS
P5 = 90 + 50 + 40 + 30 = 210mS
Tempo medio = (0+90+140+180+210) / 5 = 620 / 5 = 124 mS
SPN: L’ordine di esecuzione è P4, P3, P2, P5 e P1. Si hanno quindi i seguenti tempi di attesa:
P1 = 30 + 40 + 50 + 70 = 190 mS
P2 = 30 + 40 = 70 mS
P3 = 30 mS
P4 = 0
P5 = 30 + 40 + 50 = 120 mS
Tempo medio = (190+70+30+0+120 = 410) / 5 = 82 mS
RR: L’alternarsi nell’esecuzione è dato dal seguente diagramma:
15 15 15 15 15 15 15 15 15 15 15 15 10 15 15 5 15 15 10 15
P1
P2
P3
P4
P5
dal quale risultano i seguenti tempi di attesa, contando anche quelli tra due quanti di tempi di
esecuzione:
P1 = 190 mS, P2 = 175 mS, P3 = 150 mS, P4 = 105 mS, P5 = 195 mS.
Tempo medio = (190+175+150+105+195 = 815) / 5 = 163 mS
Il tempo medio di attesa è minimo (come previsto) con la politica Shortest Process Next.

Problema 4

Progettare un frammento di programma che utilizzi le funzioni fork , exec e wait del sistema Unix per
realizzare la seguente situazione:

Il programma prog1 deve mandare in esecuzione i programmi prog2 e prog3 creando per essi due
processi. I programmi prog2 e prog3 devono quindi evolvere indipendentemente, mentre prog1 deve
aspettare che entrambi i processi creati finiscano prima di proseguire con l’esecuzione. prog1 prosegue
poi chiamando la funzione f2 se è terminato prima prog2, o la funzione f3 se è terminato prima prog3.

2
Soluzione

i = fork(); /* duplica il processo */


if (i == 0) /* è il processo figlio? */
{ execl(“prog2”,...); /* sì, esegue prog2 */
... gestione errori
}
else /* no, il padre memorizza l’identificatore */
id2 = i; /* del processo che esegue prog2 */

i = fork(); /* come sopra per prog3 */


if (i == 0)
{ execl(“prog3”,...);
... gestione errori
}
fine1 = wait(&stato); /* attende la fine dei processi figli */
fine2 = wait(&stato); /* memorizzandone l’identificatore */
if (fine1 == id2) /* è finito prima prog2? */
f2(...); /* sì, esegue la funzione f2 */
else
f3(...); /* no, esegue la funzione f3 */

Problema 5

Progettare un frammento di programma che utilizzi le funzioni di gestione processi di Unix per
realizzare il seguente comportamento:

Il programma A manda in esecuzione concorrente due processi che eseguono rispettivamente i


programmi B e C, e ne attende la terminazione. I processi terminano rispettivamente con codici di
completamento cB e cC. Quindi A verifica che il processo che termina per primo abbia il codice di
completamento maggiore dell’altro, e in tal caso termina con codice di completamento 1, altrimenti
termina con codice di completamento 0.

Soluzione

if (fork() == 0) /* manda in esecuzione il programma B */


{ execl(“B”,...);
... gestione errori ...
}
if (fork() == 0) /* manda in esecuzione il programma C */
{ execl(“C”,...);
... gestione errori ...
}
wait(&stato1); /* aspetta la fine del primo e ne rileva lo stato di completamento
*/
wait(&stato2); /* idem con il secondo */
if (stato1 > stato2)
exit(1);
else
exit(0);

Problema 6

Un sistema a memoria paginata ha un tempo di accesso alla memoria primaria di 100 nanosecondi.
Per gestire un page fault occorrono mediamente 10 mS se è disponibile una pagina vuota in memoria
centrale, o se la pagina da sostituire non è modificata, e 24 mS se si deve sostituire una pagina
modificata. Se nel 50% dei casi la pagina da sostituire è modificata, qual’è la probabilità accettabile di
page fault per un tempo medio di accesso di 200 nanosecondi?

3
Soluzione

La formula generale è la seguente, dove tm è il tempo di accesso medio, p è la probabilità di page


fault, tc è il tempo di accesso a memoria centrale, e tf è il tempo di servizio di un page fault (in cui si
trascura il tempo di accesso a memoria centrale perché trascurabile rispetto all’accesso a disco):
tm = (1 - p) × tc + p × tf
Nel nostro caso, essendo la probabilità di sostituire una pagina modificata pari al 50% dei page fault, il
tempo medio di servizio di un page fault è 17 mS (media tra 10 mS e 24 mS). Essendo tm = 200 nS e
tc = 100 nS, si ha:

200 = (1 - p) × 100 + p × 17 × 10 6
arrotondando, p = 1 / 170.000, cioè un page fault ogni 170.000 accessi a memoria.

Problema 7

La memoria virtuale di un calcolatore è divisa in pagine di 512 byte. Dati i seguenti frammenti di
programma in linguaggio C:

int x[32][128]; int x[32][128];


int r, c; int r, c;
... ...
for (r = 0; r < 32; r++) for (c = 0; c < 128; c++)
for (c = 0; c < 128; c++) for (r = 0; r < 32; r++)
x[r][c] = 0; x[r][c] = 0;

(a) (b)

dire quanti page fault vengono generati nell’ipotesi che:


- per i dati vengano usati 8 page frame, inizialmente non allocati
- i dati di tipo int occupino ciascuno 4 byte
- la matrice sia memorizzata per righe in modo contiguo e compatto
- gli unici dati allocati in memoria paginata siano gli elementi della matrice
- si adotti una politica di sostituzione locale delle pagine LRU

Soluzione

Se ogni dato intero occupa 4 byte, ogni riga della matrice occupa 128 x 4 = 512 byte, cioè una
pagina.

Nel caso (a) la matrice viene azzerata per righe, quindi una volta caricata in memoria la pagina
corrispondente alla prima riga questa può essere azzerata senza ulteriori page fault. Quindi si carica in
memoria la pagina che contiene la seconda riga, e così via fino all'ottava riga. A questo punto tutte le
pagine fisiche a disposizione sono state occupate, e per azzerare la riga di indice 8 (cioè la nona) è
necessario riutilizzare una pagina già utilizzata. In base alla politica LRU si riutilizza la prima pagina
fisica allocata, che contiene la riga di indice 0, che è quella utilizzata meno recentemente. Si prosegue
quindi riutilizzando la seconda pagina, poi la terza, fino all'ottava in cui viene allocata la riga di indice
15. Proseguendo nello stesso modo, si genera un page fault per ogni riga e quindi in totale si hanno
32 page fault.

Nel caso (b) la matrice viene azzerata per colonne, ma l'allocazione è sempre per righe. Viene quindi
caricata la prima riga nella prima pagina, e viene azzerato l'elemento di indice [0][0]. Per azzerare
l'elemento di indice [0][1] è necessario caricare la seconda riga, che occupa la seconda pagina fisica, e
così via fino all'elemento di indice [0][7] che occupa l'ottava pagina. Per l'elemento di indice [0][8]è
necessario liberare una pagina fisica. Come prima, per la politica LRU viene liberata la prima pagina
allocata. Proseguendo in questo modo, risulta che per ogni elemento della matrice da azzerare deve
essere allocata una nuova pagina, per un totale di 32 x 128 = 4096 page fault.

4
Problema 8

E' dato il seguente frammento di programma, eseguito nel sistema operativo Unix

/* programma "A" */
id = 0;
if (fork() == 0)
id = fork();

if (id == 0)
execl("B",...);
else
execl("C",...);
...

descrivere l’evoluzione del sistema durante l’esecuzione, cioè descrivere quali processi vengono creati,
quali programmi eseguono e quale è il contenuto della memoria del sistema (aree codice e aree dati)
durante e al termine della esecuzione del frammento, nell’ipotesi che non si verifichino errori.

Soluzione

Chiamiamo per semplicità A il processo che segue il programma A, e A1, A2, etc., i processi creati a
seguito dell'esecuzione della funzione fork(). L'esecuzione della istruzione

if (fork() == 0)

causa la creazione di un processo figlio A1, a cui la fork restituisce il valore 0. Al processo A viene
restituito un valore > 0 che coincide con l'identificatore di processo del processo A1. Il processo figlio
A1 quindi vede soddisfatta la condizione ed esegue l'istruzione

id = fork();

che causa la creazione di un nuovo processo A2. Nel processo A1 la variabile id riceve un valore > 0,
mentre nel processo A2 la variabile id riceve il valore 0. Nel processo A la variabile id conserva il
valore 0 assegnato dall'istruzione

id = 0;

poiché il processo A non è entrato all'interno della struttura condizionale if. Si ha quindi la seguente
situazione:
- nel processo A id = 0,
- nel processo A1 id > 0,
- nel processo A2 id = 0.

I processi A e A2 proseguiranno quindi eseguendo il codice del programma B, mentre il processo A1


proseguirà eseguendo il codice del programma C.

Problema 9

Quattro processi P1-P4 richiedono quattro risorse R1-R4 di cui esistono nel sistema le quantità indicate
in figura (a). In un certo istante dell’esecuzione i quattro processi posseggono le risorse indicate in
figura (b), e le loro richieste successive sono indicate in figura (c). Si supponga che le risorse possano
essere allocate a una a una e che nessuna delle risorse venga rilasciata da un processo prima della
terminazione.
a) Può verificarsi un deadlock? Se no spiegare perché, se sì fare un esempio di situazione di
deadlock.
b) Se può verificarsi deadlock, esiste una strategia di allocazione delle risorse che lo evita? Se sì
illustrare come possono essere allocate le risorse

5
R1 R2 R3 R4
risorse esistenti 4 8 5 6

Fig. a

allocazione R1 R2 R3 R4 richieste R1 R2 R3 R4
P1 1 3 2 2 P1 1 0 0 2
P2 1 2 0 1 P2 0 3 1 0
P3 2 1 2 0 P3 0 2 0 2
P4 0 0 0 2 P4 0 2 1 0

Fig. b Fig. c

Soluzione

Le risorse che rimangono disponibili nella situazione descritta sono le seguenti: R1 = 0, R2 = 2, R3 =


1, R4 = 1. Può verificarsi un deadlock perché le risorse disponibili non sono sufficienti a garantire la
terminazione di tutti i processi. Un esempio di allocazione che porta a deadlock è la seguente:

1) P1 alloca una unità della risorsa R4, poi si ferma perché non può allocare le altre risorse (1 unità di
R1, 1 unità di R4). Le risorse disponibili diventano: R1 = 0, R2 = 2 , R3 = 1, R4 = 0.

2) P2 alloca 2 unità della risorsa R2 e una unità della risorsa R3, poi si ferma perché per terminare gli
occorre una ulteriore unità di R2. Non vi sono più risorse disponibili.

3) Nessuno dei processi può acquisire le ulteriori risorse necessarie, quindi il sistema è in deadlock.

Il deadlock può essere evitato allocando le risorse ai processi secondo l'algoritmo del banchiere. In
questo caso:

1) P4 alloca 2 unità della risorsa R2 e 1 unità della risorsa R3, quindi termina lasciando disponibili le
seguenti risorse: R1 = 0, R2 = 2, R3 = 1, R4 = 3.

2) P3 alloca 2 unità della risorsa R2 e 2 unità della risorsa R4, quindi termina lasciando disponibili le
seguenti risorse: R1 = 2, R2 = 3, R3 = 3, R4 = 3.

3) Con queste risorse disponibili sia P1, sia P2 possono completare la loro esecuzione, quindi il sistema
non entra in uno stato di deadlock.