CdS in Ingegneria Informatica - Prof. Paolo Bellavista
Parte di Programmazione di Sistema (16 punti)
Si
scriva un programma C che, utilizzando le System Call del sistema operativo UNIX, abbia un’interfaccia
del tipo:
telefonoSenzaFili NomeFile
Num1 Num2
dove NomeFile è un nome assoluto di file già esistente nel file
system e Num1, Num2 sono numeri naturali minori di 10. Dopo aver effettuato gli opportuni controlli sugli argomenti, il
processo iniziale P0 deve generare
due processi, P1 e P2, entrambi figli di P0.
P0 deve leggere il contenuto del file NomeFile e trasmetterlo a P1. P1 e P2 devono "giocare a telefono senza fili": P1 deve fungere da filtro e trasferire
tutti i caratteri ricevuti a P2 TRANNE
i caratteri di posizione multipla di Num1;
tali caratteri scartati devono essere scritti sul file scartati.txt.
P2 deve comportarsi analogamente,
considerando i caratteri comunicatigli da P1,
eliminando quelli di posizione multipla di Num2,
e rimandando i restanti indietro a P0;
anche in questo caso i caratteri scartati devono essere scritti da P2 su scartati.txt.
Al termine del processamento di tutto il contenuto di
NomeFile
da parte dei tre processi, P0 deve
stampare a video la somma del numero di caratteri ricevuti da P2 e dei caratteri presenti su
scartati.txt e verificare che questa coincida con la lunghezza originaria di NomeFile.
Nel caso in cui l'utente, in qualunque istante
durante l’esecuzione del programma concorrente, prema la combinazione di
tasti <CTRL-C>, i processi P1 e P2 devono essere immediatamente terminati. In tal caso, il processo padre P0 deve portare a termine da solo il lavoro, considerando i
caratteri ancora non comunicati prima della segnalazione utente: su tali
caratteri devono essere svolte le solite operazioni di eliminazione
dei caratteri di posizione multipla di Num1, Num2 e di scrittura dei caratteri
scartati su scartati.txt. Ovviamente, in questo caso,
la somma finale calcolata da P0
potrà differire dalla lunghezza originaria di NomeFile.
Si facciano le scelte di sincronizzazione dei processi ritenute più opportune, cercando di sequenzializzare il meno possibile le varie operazioni richieste.
Parte Thread (8 punti)
Si scriva un programma che utilizzi i Java Thread per la gestione di code di vetture in attesa di essere aggiustate da un meccanico.
Dal momento che il meccanico non ha aiutanti, una sola vettura alla volta può essere aggiustata; le altre vengono parcheggiate in attesa del proprio turno. L'officina è dotata di un parcheggio stretto e lungo (largo tanto quanto basta ad ospitare una singola vettura), che termina contro un muretto, come mostrato in figura.
I file allegati Launcher.java e Vettura.java contengono le implementazioni, rispettivamente, del programma principale e della classe Vettura. In particolare, il metodo run() della classe Vettura cerca di accedere alla risorsa condivisa. Nel caso la vettura non sia accettata, viene stampato un messaggio di errore. Altrimenti (si noti che in questo secondo caso il metodo arrivo() dovrà restituire il controllo solamente nel momento in cui la vettura ha terminato l'attesa in coda e può essere aggiustata dal meccanico), Vettura simula le operazioni del meccanico tramite un’attesa di alcuni secondi, dopo di che invoca il metodo uscita() per liberare la risorsa. Inoltre, il file Officina.java contiene lo scheletro della classe Officina.
I candidati implementino i metodi mancanti arrivo() e uscita() della classe Officina che servono a regolare l'accesso alla risorsa meccanico secondo le specifiche di sincronizzazione sopra illustrate.