ESERCIZI per il LABORATORIO di SISTEMI OPERATIVI

Il giudizio sul profitto che ciascuno studente ha ottenuto seguendo il Laboratorio, necessario alla valutazione complessiva del Corso di Sistemi Operativi, verrà determinato in due fasi distinte. Nell'una, è richiesta la soluzione degli esercizi riportati di seguito, il cui numero totale sarà aggiornato nel corso dell'anno accademico, e la cui presentazione collettiva dovrà avvenire nell'ambito del gruppo in cui lo studente risulta registrato.

Parallelamente, nel corso delle lezioni di Laboratorio, a ciascuno studente verrà richiesta individualmente la soluzione di semplici esercizi presentati dal docente, e la cui valutazione sarà utilizzata per ridistribuire il giudizio complessivo del gruppo con un peso dipendente dalle abilità individuali di ciascun componente.

Programmazione della Shell

Gli esercizi proposti nel seguito devono essere realizzati utilizzando la bash shell di Linux, eventualmente nella forma ridotta di Bourne shell sh, il cui manuale è disponibile in formato PDF oppure in modalità ipertestuale

La soluzione degli esercizi deve essere accompagnata ciascuna da una breve relazione che ne spieghi le caratteristiche rilevanti dell'implementazione e da una traccia della loro esecuzione con un input di prova.

  1. Svecchiamento del contenuto di un direttorio

    Utilizzando come base dell'implementazione il comando di shell mv, per spostare file e direttori da un direttorio all'altro, si realizzi un comando di ripulitura purge del contenuto del direttorio (passato come secondo parametro) nel cestino .wastebasket, posizionato nella home directory in base alla data dell'ultima modifica così come apppare dall'esecuzione del comando ls -l di long listing.

    La sintassi generale del comndo da implementare deve seguire lo schema riportato di seguito
    purge [-opt1 [-opt2 ...]] date dir

    dove le opzioni opt1, opt2, ... sono le stesse del comando mv, mentre date rappresenta la data in base alla quale tutti i file e directory la cui data di ultima modifica è inferiore ad essa, devono essere spostati nel cestino.

    Si impieghi il parametro $* per rappresentare la lista dei parametri passati al comando in questione. Inoltre, se lo si ritiene opportuno, si utilizzi ls -l --time-style=+'FORMAT' come comando di listing, dove FORMAT è lo stesso di quello specificato dal comando date.

  2. Archiviazione e Compressione

    Utilizzando come base dell'implementazione il comando di shell tar, per archiviare file e direttori, si realizzi il comando di compressione pkz dei file e directory passati come parametri rimanenti.

    La sintassi generale del comando da implementare deve seguire lo schema riportato di seguito
    pkz   c|l|x|i   [-opt ...]  pkzfile  file ... dir ...

    dove il primo parametro, indicato con una delle 4 lettere c, l, x o i, rappresenta una delle azioni create , list, extract oppure insert, i successivi opt, ... le opzioni (le stesse del comando tar). Il parametro successivo pkzfile definisce l'archivio compresso nel quale sono inseriti i rimanenti parametri file ... dir ... .

    Si ricordi che la compressione dell'archivio tar si ottiene passando il flag z al comando tar. Si consulti, inoltre, il manuale in linea del comando per i dettagli del suo utilizzo.

  3. Autorizzazione d'Accesso

    Si consideri il problema di gestire l'accesso controllato ad un server remoto per mezzo di un meccanismo di autenticazione che richieda una username e una password, specifici per ciascuno degli utenti autorizzati. La richiesta di accesso avviene mediante la pagina HTML login.html che deve contenere obbligatoriamente i campi uname e passwd.

    Si realizzi lo script CGI bash login.cgi in modo da poter verificare l'identità dell'utente ed, eventualmente, consentirne l'accesso. Si preveda, inoltre, la possibilità per gli utenti non registrati di poterlo fare, utilizzando lo stesso schema di "form" con ulteriori campi da compilare per generare un nuovo utente da autorizzare.

    Si ternga presente che è necessario mantenere il database passwd.db contenente le informazioni rilevanti per ciascun utente autorizzato. Lo si implementi come un file di testo, una riga per utente, così strutturato

    uname:passwd: name:surname: info
     
    ed, inoltre, in caso di successo al login o in fase di registrazione si produca un'adeguata pagina di risposta. Si utilizzi il campo info a piacimento.

Programmazione di Sistema in C

Gli esercizi proposti nel seguito devono essere realizzati nel linguaggio C impiegando, laddove è necessario, le chiamate di sistema e le funzioni di libreria del caso. A tal fine vanno aggiunte le opportune righe di include, contenenti i riferimenti ai file di intestazione (estensione .h) con le relative dichiarazioni di tipo e di funzione, ed inoltre compilare i sorgenti con le opzioni per il linker in modo ad ottenere la risoluzione dei nomi con le funzioni di libreria richieste.

  1. Implementazione in C dei comandi di shell

    Prendendo come riferimento il comando di shell expr per la valutazione di espressioni aritmetiche negli script, si realizzi in C il comando arith in modo che il suo impiego avvenga secondo la sintassi che appare nel seguito
    arith val1 op val2
    dove op è uno dei caratteri +, -, *, /, & che rappresentano le operazioni di somma, sottrazione, moltiplicazione, divisione e modulo rispettivamente. Si tenga presente, inoltre, che il carattere * ha uno speciale significato per la shell.

    Facoltativamente si consideri l'estensione del comando arith affinchè possa eseguire le operazioni quadrato (sqr) e radice quadrata (sqrt), la seconda delle quali potendo produrre valori reali. Naturalmente, in questo caso il comando viene invocato con 2 soli argomenti.

    Realizzare l'implementazione in modo che il comando arith sia a tutti gli effetti un comando di shell per cui passaggio dei parametri, impiego in espressioni booleane e assegnazione di valore a variabili devono avvenire in modo del tutto trasparente.

  2. Relazione Client/Server fra Thread

    Si consideri il caso di un processo sequenziale che genera, durante la sua esecuzione, un numero N + 1 di thread dei quali uno funge da server dei rimanenti N client. Si supponga che il thread server abbia la tipica struttura di loop in cui, dopo la necessaria inizializzazione, si pone in attesa di richieste dai client sulla porta Port. Ricevuta una richiesta il server la elabora e restituisce la dovuta risposta al client; successivamente il server si rimette in ascolto per una nuova richiesta.

    Si realizzino gli N client come semplici thread che, dopo l'ovvia inizializzazione, attendono s secondi, col comando sleep(s), eseguono una qualche computazione e, quindi, lanciano la richiesta al server sulla porta Port per poi attendere la risposta. Si implementi tale protocollo di richiesta in modo da permettere solo un numero M < N di richieste vengano contemporaneamente evase dal server. Questo significa che la coda delle richieste pendenti non può superare M.

    Dunque, un cliente dovrà negoziare col server la sua disponibilità ad accettare la richiesta inviandola alla porta Free e, soltanto in caso affermativo, la sua richiesta verrà inoltrata alla porta Port dove il client continuerà l'attesa. Altrimenti terminerà immediatamente l'esecuzione.

  3. Client TCP per connessioni seriali

    Facendo riferimento al server connesso discusso a lezione e del quale sono stati forniti alcuni esempi di possibili routine da eseguire, si implementi un client connesso, che utilizza il protocollo di trasmissione TCP, in grado di colloquiare col predetto server in modo del tutto analogo al client TELNET. Si ricordi che, in questo caso, è necessario utilizzare, all'interno dello schema generale delle socket, la chiamata di sistema connect.

  4. Schema Client/Server non connesso

    Facendo sempre riferimento al predetto server si realizzi uno schema di funzionamento analogo ma in ambito non connesso ossia, impiegando socket datagram UDP. Si supponga di realizzare la stessa routine discussa a lezione relativa al gioco di indovinare la parola proposta dal server. Si tenga presente, comunque, che è necessario implementare lo schema client/server come se fosse aperta una sessione di lavoro in cui i due processi si scambiano i pacchetti sulla stessa coppia di porte.

Piattaforma RoboCup

Assegnato il soccerserver della piattaforma RoboCup, si implementi un client asincrono , secondo le direttive descritte nel manuale d'uso e ampiamente discusse a lezione. Per la realizzazione del client ciascuna squadra è libera di utilizzare il software disponibile nelle pagine che descrivono il funzionamento di un player. Tuttavia, è necessario indicare chiaramente le parti specificatamente implementate da ciascuna squadra che dovrà controllare l'avatar messo a disposizione dalla piattaforma. La realizzazione deve permettere la clonazione di N processi clienti (fino a un massimo di 11) per ottenere una squadra capace di giocare una partita simulata.