Sei sulla pagina 1di 4

SOLUZIONI - SISTEMI OPERATIVI B, SCRITTO DEL 31/1/2013 NOME ______________________________ COGNOME ______________________________________ MATRICOLA __________ TEORIA (15 punti)

Quesito 1. (3 punti) Illustrare con un esempio il problema della sezione critica: Si consiedri un buffer condiviso da pi processi produttori e consumatori, gestito come una coda. Ogni produttore, quando inserisce un dato, deve aggiornare due variabili condivise: l'array che contiene gli elementi e la testa della coda. Si supponga che il buffer sia vuoto, che il produttore P1 abbia inserito l'elemento creato ma non ancora aggiornato testa. Se lo scheduler della CPU la cede a un altro produttore, questo sovrascriver il dato prodotto da P1. Quesito 2. (3 punti) Parlando di sincronizzazione di processi, cosa si intende per stato sicuro? Uno stato (di assegnazione delle risorse ai processi) sicuro quando da esso si diparte almeno una sequenza di esecuzione sicura, cio tale che le richieste dei processi vengono soddisfatte e non si genera deadlock. Quesito 3. (4 punti) Illustrare la traduzione di indirizzi logici in fisici nel caso in cui la memoria principale sia gestita tramite paginazione e la tabella delle pagine sia realizzata come tabella invertita. Si veda lo schema spiegato a lezione. Quesito 4. (5 punti) Si consideri un sistema che adotta un meccanismo di paginazione su richiesta (4.a) che cosa si intende per working set? Il working set di un processo un'approssimazione dell'insieme delle pagine attive del medesimo, calcolata sulla base delle ultime richieste di accesso alle pagine. Il working set si evolve nel tempo, dipende dalla localit di esecuzione corrente. (4.b) si calcoli il working set attuale supponendo che la sequenza di richieste avvenute sino a questo istante sia la seguente e che sia pari a 15: 11211333214242444334422254334334 working set = {2, 3, 4, 5} UNIX (6 punti) Quesito 5. (2 punti) Assumendo che T1e T2 siano file e my_app sia un file eseguibile, spiegare i seguenti comandi e il loro effetto: (5.1) wc < T1 > T2 wc (word count) mostra il numero di righe, parole e caratteri del suo input. In questo caso < (redirezione dellinput) fa in modo che il contenuto del file T1 sia linput al comando, mentre > (re direzione delloutput) fa in modo che loutput del comando sia salvato nel file T2. Se il file T2 non 1

esiste viene creato, se gi esiste viene sovrascritto.

(5.2) chmod 742

my_app

Modifica i permessi di accesso al file my_app: rwx, per lutente proprietario; r--, per gli utenti nel gruppo del proprietario; -w-, per tutti gli altri utenti. (5.3) ps | grep my_app > T1 ps lista i processi attivi (lanciati dallo stesso terminale da cui stato lanciato ps), loutput di ps viene rediretto, attraverso la pipe, nellinput del comando grep, questultimo comando seleziona solo le righe che contengono la stringa my_app. Il risultato diventa il contenuto del file T1. (5.4) cat T1 >> T2 cat manda a video il contenuto di uno o pi file, in questo caso del file T1. Loutput di cat per rediretto e riversato nel file T2. In particolare, >> significa append, quindi se il file T2 gi esiste, il contenuto di T1 viene appeso al fondo di T2. Se T2 non esiste, viene creato.

Quesito 6. (2 punti) Spiegare leffetto delle seguenti system call, specificando il significato delle opzioni usate e indicando eventuali errori: (6.1) shmget(IPC_PRIVATE, sizeof(registro), 0660); Alloca un segmento di memoria condivisa. Se ha successo restituisce lid del nuovo segmento creato. IPC_PRIVATE indica che il programmatore incarica il kernel di generare una chiave univoca per il segmento di memoria condivisa. IPC_PRIVATE si usa unicamente nellallocazione di nuove facility, quindi IPC_CREAT implicito e non richiesto. Sizeof(registro) stabilisce che la dimensione del segmento deve essere sufficientemente grande da contenere una variabile di tipo registro (che gi sar stata definita) Infine 0660 sono i permessi associati al segmento: rw- per lutente corrente e per tutti gli utenti del suo gruppo. (6.2) msgrcv(q_id, &msg, size, IPC_NOWAIT); Restituisce il numero di byte letti dalla coda con id q_id, se ha successo, -1 altrimenti. msg la variabile che conterr il messaggio letto size indica il numero di byte da leggere dalla coda manca il campo type, che pu essere 0 (preleva il primo messaggio presente nella coda), oppure >0 (preleva il primo messaggio nella coda con il tipo richiesto). IPC_NOWAIT indica che se la coda non contiene messaggi del tipo richiesto la receive ritorna immediatamente (non bloccante) (6.3) open(test", O_WRONLY | O_EXCL | O_CREAT, 0600); Apre un file di nome test in sola lettura (O_WRONLY), se non esiste viene create (O_CREAT), se il file gi esiste la funzione ritorna -1 (O_EXCL=creazione esclusiva). Se la open ha successo ritorna il file descriptor associato al file. 2

0600 indica i permessi (rw- per il solo utente corrente) (6.4) semctl(semid, 0, IPC_RMID, 0); Rimuove il pool di semafori identificato da semid, i due parametri a 0 sono in questo caso non richiesti. Quesito 7. (2 punti) Spiegare cosa si intende per chiave di una facility di IPC, e in quali modi possibile generare una chiave. La chiave di una facility di IPC un identificatore univoco lato programmatore, svolge lo stesso ruolo di un nome di file. Le diverse funzioni get servono per recuperare lid corrispondente ad un chiave. Lid lidentificatore univoco lato kernel, e svolge lo stesso ruolo di un file descriptor. Tre modi per creare una chiave: - Il programmatore la sceglie a caso (poco sicuro) - Utilizzo della funzione ftok - Utilizzo dellopzione IPC_PRIVATE nellinvocazione della funzione get. Linguaggio C (6 punti) Esercizio 1 (3 punti) Si implementi la funzione con prototipo: /*?*/ allocate_matrix(int rows, int cols, int val); allocate_matrix una funzione che alloca una matrice di interi di rows righe e cols colonne dinamicamente e restituisce un puntatore alla matrice cosi` allocata; ogni cella della matrice sar inizializzata al valore val. Completare il tipo del valore di ritorno. int** allocate_matrix(int rows, int cols, int val){

int i,j; int** m = (int**)malloc(sizeof(int*) * rows); for (i=0; i<rows; ++i){ m[i] = (int*)malloc(sizefo(int)* cols); for (j=0; j<cols; ++j){ m[i][j] = val; } } return m; } Esercizio 2 (3 punti) Data la struttura node, implementare la funzione con prototipo int remove_element_h (link* head, int val); remove_element_h elimina tutti i nodi in testa alla lista che hanno valore pari a val; la funzione ritorna il numero di nodi effettivamente eliminati. Leliminazione deve lasciare lo heap pulito. 3

Ad esempio: l1: 556754; val = 5; l1 viene modificata come: 6754, valore di ritorno 2. l2: 655754; val = 5; l2 non viene modificata, valore di ritorno 0. La struttura node definita come segue: typedef node* link; typedef struct node { int value; link next; } node; int remove_element_h (link* head, int val){ if (head==NULL) return 0; int count = 0; while( (*head)!= NULL && (*head)->value == val){ link tmp = (*head); (*head) = (*head)->next; free(tmp); ++count; } return count; }