Sei sulla pagina 1di 6

SISTEMI OPERATIVI NUOVO ORDINAMENTO 16 febbraio 2012

Cognome: Matricola: Nome:

1. Ricordate che non potete usare calcolatrici o materiale didattico. 2. Ricordate che potete consegnare al massimo tre prove scritte per anno accademico.

ESERCIZI RELATIVI ALLA PARTE DI TEORIA DEL CORSO (15 punti)


ESERCIZIO 1 (5 punti) Processi (1.1) Utilizzando un adeguato numero di semafori (opportunamente inizializzati si supponga che controllino risorse condivise) e le primitive semaforiche P e V, scrivere lo pseudo-codice di due processi P1 e P2 che possono andare in deadlock e spiegare come, quando ci capita, le condizioni necessarie al deadlock trovano realizzazione nell'esempio riportato: Semafori e loro inizializzazione: semaforo S1 = 1; // entrambi i semafori sono di mutua esclusione, un processo solo per volta semaforo S2 = 1; // pu passare. Non modello le risorse gestite (non occorre). P1: P(S1) P(S2) <<codice>> V(S1) V(S2) P2: P(S2) P(S1) <<codice>> V(S1) V(S2)

Elenco delle condizioni e loro realizzazione nell'esempio precedente : L'esecuzione andr in deadlock quando P1 e P2 si alternano nell'esecuzione della loro prima istruzione.Condizioni e loro realizzazione: Mutua esclusione: S1 vale 1 quando la risorsa che controlla libera, 0 altrimenti (idem S2) Possesso e attesa: le istruzioni P(S1) e P(S2) in sequenza realizzano questa condizione. Nel caso che porta a deadlock, P1 ha superato P(S1) e detiene quindi la risorsa controllata da S1. bloccato su S2, in attesa della risorsa da esso controllata e in questo momento in possesso di P2 (l'inverso vale per P2) No prelazione: il sistema operativo non interviene per sbloccare processi fermi su un semaforo. Attesa circolare: nel caso del deadlock, P1 in attesa di una risorsa da P2 (tramite P(S2)) e P2 in attesa di una risorsa da P1 (tramite P(S1)). (1.2) Dare la definizione di stato sicuro e riportare un esempio di stato sicuro in cui compaiano tre classi di risorsa e due processi, dimostrando che sicuro: 1

Uno stato si dice sicuro quando: quando esiste un possibile ordinamento dei processi tale per cui le richieste di ciascun processo sono soddisfacibili utilizzando le risorse libere nello stato di partenza pi quelle liberate dai processi che, nell'ordinamento, lo precedono. Esempio e dimostrazione: Siano P1 e P2 i processi, R1, R2, R3 le classi di risorsa. Assegnate[P1] = {2, 0, 0}, Assegnate[P2] = {0, 1, 1}, Richieste[P1] = {0, 2, 0}, Richieste[P2] = {0, 1, 0} e infine libere = {0, 1, 0}.

P1 e P2 per eseguire hanno bisogno di istanze di R2. Mentre P2 ne richiede una sola (che in questo momento a disposizione), P1 ne richiede 2, che per al momento non sono disponibili (una detenuta da P2). Il sistema operativo pu scegliere di assegnare l'unica istanza di R2 libera a P1 oppure a P2. Nel primo caso si generer un deadlock (n P1 n P2 avranno sufficienti istanze di R2). Nel secondo caso P2 potr eseguire liberando le risorse che saranno poi usate da P1. Poich esiste un possibile ordinamento dei due processi (P2, P1) tale per cui le richieste del primo (P2) sono soddisfacibili con le risorse inizialmente libere, e quelle del successivo (P1) lo sono con le risorse liberate dal precedente pi quelle inizialmente libere, lo stato sicuro.

ESERCIZIO 2 (2 punti) Memoria Secondaria (2.1) Che cosa si intende per scheduling del disco? Lo scheduling del disco la politica di selezione della prossima richiesta di accesso (in lettura o scrittura) ad un blocco del disco che sar eseguita. (2.2) Spiegare qual il fine dello scheduling del disco. Il fine ridurre il tempo di seek, migliorando in media il tempo di reperimento del blocco richiesto. ESERCIZIO 3 (6 punti) RAM e Memoria Virtuale (3.1) Consideriamo un sistema in cui la RAM gestita tramite paginazione, che fa uso di un TLB. Calcolare il tempo medio di accesso a un indirizzo in RAM nel caso in cui il TLB miss sia del 2%, il tempo d'accesso diretto alla RAM sia 100 nanosec e il tempo di accesso al TLB sia 20 nanosec. TLB miss = 0.02; hit ratio = 0.98; t_RAM = 200 tma = 0.02 * 200 + 0.98 * 120 = 4 + 117.6 = 121.6 122 nanosec tempo medio di accesso = 223.6 (circa 224 nanosec) (3.2) Spiegare in che cosa consiste un page fault e cosa comporta la sua gestione: Un page fault : la richiesta, da parte di un processo, di accedere ad una sua pagina al momento non caricata in RAM. Gestire un page fault significa: 2

Mandare in stato waiting il processo in esecuzione, effettuare un context switch per mantenere attiva la CPU, individuare la pagina richiesta in memoria secondaria e richiederne il caricamento, trovare un frame di RAM libero (o liberarne uno), aggiornare (a caricamento effettuato) la tabella delle pagine del processo in questione, far passare il processo allo stato ready e, quando diventer running, rieseguire l'istruzione interrotta dal page fault.
(3.3) Spiegare scopo e funzionamente dell'algoritmo di seconda chance: l'algoritmo di seconda chance un algoritmo di sostituzione: individua in RAM una pagina vittima a seguito dell'occorrenza di un page fault. Le pagine di un processo sono organizzate in una coda circolare. Ciascuna ha associato un bit di riferimento. Ad ogni utilizzo di una pagina il suo bit di riferimento (inizialmente a 0) messo ad 1. Quando si genera un page fault, la coda circolare viene percorsa e per ogni pagina considerata: se il suo bit di riferimento vale 0, sar scelta come vittima (e la scansione termina); se vale 1, il bit di riferimento viene portato a 0 e l'algoritmo passa a considerare la pagina successiva. (3.3) Quando viene utilizzato il dirty bit? A quale scopo? Il dirty bit indica se una pagina stata modificata rispetto alla sua copia in memoria secondaria oppure no. Viene usato ogni qual volta venga effettuato lo swapping (a livello di processi o di singole pagine), per decidere se occorre ricopiare la pagina di RAM in memoria secondaria oppure se questa operazione (costosa in termini di tempo) pu essere evitata.

ESERCIZIO 4 (2 punti) File System (4.1) Spiegare i rischi/difetti di una gestione a lista concatenata dei blocchi che costituiscono i diversi file I rischi/difetti sono due: (1) l'accesso diretto non pu essere eseguito in maniera efficiente in quanto per reperire il blocco di interesse occorre percorrere la sequenza dei blocchi che lo precedono; (2) la corruzione di un blocco comporta la perdita del medesimo pi degli eventuali blocchi successivi che costituiscono il file.

ESERCIZI RELATIVI ALLA PARTE DI UNIX (6 punti) ESERCIZIO 1 (2 punti) (1.1) Per qale motivo due esecuzioni di shmat sulla stessa area di memoria condivisa possono restituire indirizzi d'accesso diversi se eseguite da processi diversi?

Perch tali indirizzi (logici) dipendono dallo spazio degli indirizzi di ciascun processo.
(1.2) Per quale motivo l'uso di shmget in un sistema paginato crea frammentazione interna?

Perch l'unit logica minima di RAM allocabile una pagina. Se il numero di byte richiesti minore della dimensione di una pagina o non un suo multiplo esatto la pagina allocata (o l'ultima allocata, se pi di una) sar riempita in maniera solo parziale.
3

ESERCIZIO 2 (2 punti)

Spiegare dettagliatamente cosa fanno e quale sar l'effetto dei seguenti comandi:
(2.1) ls -lt | grep rwx >> abcd ls -lt elenca i contenuti della directory di lavoro completi di tutti i metadati; grep seleziona le righe in cui compare la tripla rwx (permessi di lettura, scrittura, esecuzione per qualche tipo di utente); >> ridireziona lo standard output sul file abcd, che se non esiste sar creato altrimenti verranno aggiunti in coda i nuovi contenuti. (2.2) chmod u+s prog (supponendo che i diritti di accesso di prog siano: r w x r - x - - - ) chmod modifica i diritti di accesso a file/directory. I diritti di prog diventano: r w s r x - - In particulare viene attivato il bit SUID. ESERCIZIO 3 (2 punti) (3.1) Spiegare il funzionamento della system call semget:

si vedano le slide o man.


(3.2) Per quale motivo l'esecuzione del seguente brano di codice produrr verosimilmente un segmentation fault?: typedef struct { long tipo; int dato1; int dato2; } mtype; .... int ris; mtype *msg; int qid = msgget(1234, 0); ris = msgrcv(qid, &msg, sizeof(mtype), 2, 0); Spiegazione: la variabile che dovrebbe contenere il messaggio ricevuto non stata allocata ( solo stato definito un puntatore); la dichiarazione avrebbe dovuto essere mtype msg (senza l'asterisco). Poich lo spazio non sufficiente, la copiatura dei dati potrebbe causare un tentativo di accesso alla memoria riservata per altri processi, da cui il segmentation fault. ESERCIZI RELATIVI ALLA PARTE DI C (6 punti) ESERCIZIO 1 (4 punti totali) a) (1 punto) Definire un tipo strutturato contatto avente i seguenti campi: - nome (stringa) 4

- eta (intero) - media (reale) La dimensione massima della stringa non nota a priori. typedef struct { char * nome; int eta; float media; (double media;) }contatto; b) (1 punto) Scrivere l'istruzione che alloca dinamicamente un array, di nome rubrica, di N elementi il cui tipo base contatto. contatto * rubrica = (contatto*) malloc(sizeof(contatto)*N); c) (2 punti) Scrivere la funzione con prototipo int cerca (char * nome, contatto * rubrica);

che restituisce lindice del primo contatto in rubrica il cui campo nome uguale a nome passato come argomento. La funzione restituisce -1 nel caso in cui il nome cercato non presente nellarray. Assumere che larray sia completamente riempito e che N sia una costante globale. int cerca (char * nome, contatto * rubrica){

int i=0; while (i<N){ if (strcmp(cercato, rubrica[i].nome)==0) return i; i++; } return -1; } ESERCIZIO 2 (2 punti) Date le seguenti strutture: typedef struct nodo *lista; struct nodo { int val; lista next; }nodo; e la funzione con prototipo: nodo * inserimento_ordinato(nodo * head, int valore); che inserisce in modo ordinato valore nella lista head, individuare i 2 errori sintattici indicando la riga che contiene lerrore con una freccia e scrivere le istruzioni corrette al fondo. 5

Nodo * inserimento_ordinato(nodo * head, int valore){ if (!head || head->val > valore) { Nodo * tmp = (nodo) malloc(sizeof(nodo)); tmp->val = valore; tmp->next = head; head = tmp; } else { head->next = inserimento_ordinato(head->next, valore); } return *head; } Nodo * tmp = (nodo*) malloc(sizeof(nodo)); return head;