interpreter : Analisi e progettazione - Owanesh/unifi-eos GitHub Wiki
La politica di esecuzione viene scelta dall’utente all’avvio del programma, attraverso un menù di selezione. Si esaminano separatamente la progettazione delle due richieste effettuate nel testo:
Esecuzione sequenziale
Il processo main (presente dall’attivazione del programma) gestisce l’acquisizione dei comandi da parte dell’utente, delegandoli uno per uno ad un processo figlio appositamente creato sul momento; dal momento che il testo esplicita che l’esecuzione è sequenziale, il padre attende che il figlio termini il suo compito prima di tornare a ricevere il comando successivo.
Un esempio di esecuzione è il seguente:
- Il processo main attende un comando;
- L’utente digita “ls” e preme “invio”;
- Alla digitazione di “invio” il processo main crea un processo figlio tramite fork() e si mette in attesa tramite wait();
- Il processo figlio sostituisce il proprio codice tramite exec() e avanza fino alla terminazione del suo compito, evento che verrà segnalato al processo padre;
- Il processo main viene risvegliato e torna ad attendere un comando dall’utente; Notare quindi come l’esecuzione avviene in maniera sequenziale, non ci sono processi eseguiti parallelamente (inoltre non possono essere presenti allo stesso tempo 2 o più processi figli, ma il processo main e l’eventuale figlio).
Esecuzione parallela
Non essendo ulteriormente specificato nel testo, per il contesto dell’esecuzione parallela la realizzazione è molto simile a quella dell’esecuzione sequenziale, con l’unica differenza che il processo main non si metterà in attesa del figlio ma tornerà subito a disposizione dell’utente: ciò permette quindi a più processi figli di essere attivi nel sistema contemporaneamente assieme al padre. Ogni qual volta che un processo figlio termina, non ci sarà il padre a raccoglierne lo stato di terminazione perché ciò implicherebbe l’impossibilità da parte dell’utente di inserire comandi (come nella esecuzione sequenziale): per evitare la proliferazione di zombies è presente un handler specifico che li rimuove dalla tabella dei processi.
Analogamente, se il padre terminasse prima dei figli, essi sarebbero promossi a figli di init, il quale gestirebbe automaticamente la loro terminazione.
L’utente potrà passare come argomento il percorso della cartella in cui salvare i file di output prodotti dall’esecuzione dei figli, se non specificato verrà usato quello di default
“./output_file
”. Il percorso selezionato deve esistere o verrà mostrato un messaggio d’errore all’esecuzione di qualsiasi comando.
Si riportano le dipendenze dei moduli (sintassi simile ad un file .make, dove a sinistra in grassetto è presente il modulo oggetto e a destra la lista delle dipendenze):
main.o: main.c. parallelExec.h readCommand.h handle_sigchld.h sequentialExec.h utilities.h
parallelExec.o: parallelExec.c parallelExec.h readCommand.h. handle_sigchld.h utilities.h
handle_sigchld.o: handle_sigchld.c handle_sigchld.h
readCommand.o: readCommand.c readCommand.h utilities.h
sequentialExec.o: sequentialExec.c sequentialExec.h readCommand.h utilities.h
utilities.o: utilities.c utilities.h