Sistemi di Calcolo

Corso di Laurea in Ingegneria Informatica e Automatica - A.A. 2017-2018

HomePage | Avvisi | Diario lezioni | Programma | Materiale didattico | Esami | Forum | Login

Revision [3504]

Last edited on 2017-12-22 14:49:11 by EmilioCoppa
Deletions:
act.sa_flags = SA_SIGINFO;


Revision [3503]

Edited on 2017-12-22 14:48:40 by EmilioCoppa

No differences.

Revision [3502]

Edited on 2017-12-22 14:46:29 by EmilioCoppa
Additions:

// qui non c'è bisogno di recuperate lo stato di terminazione
// del processo figlio in quanto la funzione kill
// portera' alla terminazione del processo figlio e
// il padre ricevera' il segnale SIGCHLD,
// recuperando nel gestore lo stato di terminazione
// del processo figlio.


Revision [3499]

Edited on 2017-12-21 18:40:02 by CamilDemetrescu
Additions:
fprintf(stderr, "execif: error in wait\n");
exit(EXIT_FAILURE);
Deletions:
while (wait(&status) != p);


Revision [3496]

Edited on 2017-12-21 18:26:43 by CamilDemetrescu
Additions:
Esempio: ##execif mioprogramma ls -l##
**Gestione degli errori**: se il programma viene lanciato con meno di 2 argomenti, segnala l’errore su ##stderr## mediante testo: "##usage: execif []##". In caso di questo o di altri errori (es. system call che
falliscono) il programma termina con codice ##1##.
// STEP 3: se sono nel processo figlio, allora eseguo il comando ricevuto; in caso di errore termino processo
// STEP 4: se sono nel padre, aspetto terminazione figlio; se terminazione con errore ritorno 1 altrimenti 0
// STEP 3: se esecuzione comando non è andata a buon fine, allora eseguo altro comando invocando exec
Deletions:
**Gestione degli errori**: se il programma viene lanciato con meno di 2 argomenti, segnala l’errore su ##stderr## mediante testo: "##usage: execif []##". In caso di questo o di altri errori (es. system call che falliscono) il programma termina con codice ##1##.
// STEP 3: se sono nel processo figlio, allora eseguo il comando ricevuto;
// in caso di errore termino processo
// STEP 4: se sono nel padre, aspetto terminazione figlio;
// se terminazione con errore ritorno 1 altrimenti 0
// STEP 3: se esecuzione comando non è andata a buon fine,
// allora eseguo altro comando invocando exec


Revision [3495]

Edited on 2017-12-21 16:19:12 by EmilioCoppa
Additions:
// STEP 3: se esecuzione comando non è andata a buon fine,
// allora eseguo altro comando invocando exec
Deletions:
// STEP 3: se esecuzione comando non è andata a buon fine, allora eseguo altro comando invocando exec


Revision [3494]

Edited on 2017-12-21 16:18:47 by EmilioCoppa
Additions:
// in caso di errore termino processo
// se terminazione con errore ritorno 1 altrimenti 0
Deletions:
in caso di errore termino processo
se terminazione con errore ritorno 1 altrimenti 0


Revision [3493]

Edited on 2017-12-21 16:17:53 by EmilioCoppa
Additions:
**Gestione degli errori**: se il programma viene lanciato con meno di 2 argomenti, segnala l’errore su ##stderr## mediante testo: "##usage: execif []##". In caso di questo o di altri errori (es. system call che falliscono) il programma termina con codice ##1##.
// STEP 3: se sono nel processo figlio, allora eseguo il comando ricevuto;
in caso di errore termino processo
// STEP 4: se sono nel padre, aspetto terminazione figlio;
se terminazione con errore ritorno 1 altrimenti 0
Deletions:
**Gestione degli errori**: se il programma viene lanciato con meno di 2 argomenti, segnala l’errore su ##stderr## mediante testo: "##usage: execif []##". In caso di questo o di altri errori (es. system call che
falliscono) il programma termina con codice ##1##.
// STEP 3: se sono nel processo figlio, allora eseguo il comando ricevuto; in caso di errore termino processo
// STEP 4: se sono nel padre, aspetto terminazione figlio; se terminazione con errore ritorno 1 altrimenti 0


Revision [3492]

Edited on 2017-12-21 15:54:48 by EmilioCoppa
Additions:
%%(c;runtimeout.c)
Suggerimento: testare il binario generato (##runtimeout##) eseguendo il comando sleep con un intervallo lungo e verificare che venga terminato come richiesto, ad esempio: ## ./runtimeout 2 sleep 10## deve terminare il comando sleep dopo 2 secondi.
%%(c;runtimeout.c)
if (wait(&status) == -1) {
perror("wait() fallita");
exitStatus = WEXITSTATUS(status);
// registrazione signal handler per SIGCHLD
if (sigaction(SIGCHLD, &act, NULL)) {
perror("sigaction() fallita");
// esecuzione comando
perror("fork() fallita");
perror("execvp() fallita");
// invio SIGKILL se processo ancora attivo
if (exitStatus == -1) {
if (kill(p, SIGKILL)) {
perror("kill() fallita");
exit(EXIT_FAILURE);
Deletions:
%%(c;core.c)
Suggerimento: testare il binario generato (##runtimeout##) eseguendo il comando sleep con un intervallo lungo e verificare che viene terminato come richiesto, ad esempio: ## ./runtimeout 2 sleep 10## deve terminare il comando sleep dopo 2 secondi.


Revision [3491]

Edited on 2017-12-21 15:43:33 by EmilioCoppa
Additions:
=== Esercizio 3 ===
L’obiettivo dell’esercizio è realizzare un programma che permetta di eseguire un comando con un timeout, ovvero che ne termini l’esecuzione se essa sta richiedendo un tempo più lungo di quanto specificato dall’utente.
Si completi il seguente codice:
%%(c;core.c)
volatile int exitStatus = -1;
int runWithTimeout(char* pathname, char* args[], int timeout) {
// COMPLETARE QUI - registrazione signal handler per SIGCHLD
// COMPLETARE QUI - esecuzione comando
sleep(timeout);
// COMPLETARE QUI - invio SIGKILL
return exitStatus;
in modo che:
1) venga eseguito il comando ##pathname## corrispondente al primo parametro del metodo, usando come array di argomenti il parametro ##args## (array di stringhe già fornito nell’opportuno formato ##NULL##-terminated);
2) invece di attendere la terminazione del processo, dopo l’istruzione ##sleep()## inviare un segnale ##SIGKILL## al processo creato al punto precedente se il valore della variabile globale ##exitStatus## è pari a ##-1##;
3) installare all’inizio del metodo un signal handler per il segnale ##SIGCHLD##, di modo che se il processo dovesse terminare prima del timeout, il signal handler imposti lavariabile globale ##exitStatus## con l’exit status del comando eseguito (suggerimento: usare la macro ##WEXITSTATUS## per estrarre l’exit status).
Gestire eventuali errori restituiti dalle system call invocate.
Per testare il codice inserito, utilizzare il seguente main di prova:
%%(c;main.c)
int runWithTimeout(char* pathname, char* args[], int instances);
printf("Sintassi: %s [ ... ]\n", argv[0]);
return 1;
int timeout = atoi(argv[1]);
if (!timeout) {
printf("Il timeout (in secondi) deve essere maggiore di zero!\n");
return 1;
int status = runWithTimeout(argv[2], argv+2, timeout);
return (status == -1) ? 2 : status;
Suggerimento: testare il binario generato (##runtimeout##) eseguendo il comando sleep con un intervallo lungo e verificare che viene terminato come richiesto, ad esempio: ## ./runtimeout 2 sleep 10## deve terminare il comando sleep dopo 2 secondi.


Revision [3490]

Edited on 2017-12-21 15:34:40 by EmilioCoppa
Additions:
6) vengano gestite opportunatamente le interruzione dovute a segnali durante l'esecuzione di ##write##
Deletions:
6) vengono gestite opportunatamente le interruzione dovute a segnali durante l'esecuzione di ##write##


Revision [3489]

Edited on 2017-12-21 15:34:13 by EmilioCoppa
Additions:
5) eventuali errori di invocazione delle system call vengano gestiti opportunatamente
6) vengono gestite opportunatamente le interruzione dovute a segnali durante l'esecuzione di ##write##
Deletions:
Gestire eventuali errori restituiti dalle system call invocate. Per semplicità al punto 2 si assuma che interruzioni e scritture parziali non possano verificarsi.


Revision [3488]

Edited on 2017-12-21 15:31:14 by EmilioCoppa
Additions:
#include
#define START 86028157
ssize_t byte_scritti = 0;
while (byte_scritti < len) {
ssize_t res = write(fd, buf + byte_scritti, len - byte_scritti);
if (res == -1) { // errore
// analizziamo la causa dell'errore
switch (errno) {
case EINTR:
// se e' arrivato un segnale, non e' un errore fatale possiamo ritentare la scrittura
continue;
break;
default:
// consideriamo le altre cause come errori fatali non recuperabili
perror("errore write");
exit(EXIT_FAILURE);
}
byte_scritti += res;
void handler(int signo) {
act.sa_handler = handler;
Deletions:
// per semplicità non gestiamo interruzioni e scritture parziali
if (write(fd, buf, len) == -1) {
perror("write fallita");
void handler(int signo, siginfo_t *siginfo, void *context) {
act.sa_sigaction = handler;


Revision [3487]

Edited on 2017-12-21 15:25:49 by EmilioCoppa
Additions:
1) all'avvio del programma venga creato un file di output denominato out.txt (se il file esiste già, troncarne il contenuto) con permessi: utente => lettura e scrittura, gruppo => lettura, altri => lettura;
Deletions:
1) all'avvio del programma venga creato un file di output denominato out.txt (se il file esiste già, troncarne il contenuto) con permessi 0644;


Revision [3486]

Edited on 2017-12-21 15:19:25 by EmilioCoppa
Additions:
**Suggerimento**: utilizzare il seguente template per generare la soluzione:
// STEP 1: fork
// STEP 2: verifico fork sia andato a buon fine
// STEP 3: se sono nel processo figlio, allora eseguo il comando ricevuto; in caso di errore termino processo
// STEP 4: se sono nel padre, aspetto terminazione figlio; se terminazione con errore ritorno 1 altrimenti 0
// STEP 1: verifico numero di argomenti ricevuto, ritorno 1 in caso di errore
// STEP 2: invoco la funzione exec indicando comando da eseguire e i suoi argomenti
// STEP 3: se esecuzione comando non è andata a buon fine, allora eseguo altro comando invocando exec


Revision [3485]

Edited on 2017-12-21 15:08:23 by EmilioCoppa
Additions:
==Soluzione==
// per semplicità non gestiamo interruzioni e scritture parziali
if (write(fd, buf, len) == -1) {
perror("write fallita");
exit(1);
void handler(int signo, siginfo_t *siginfo, void *context) {
char* s = (signo == SIGINT) ? "SIGINT" : "SIGTERM";
printf("Segnale %s ricevuto: imposto shouldStop = 1\n", s);
shouldStop = 1;
// registrazione signal handler (comune per i due segnali)
struct sigaction act;
memset(&act, 0, sizeof(struct sigaction));
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = handler;
if (sigaction(SIGINT, &act, NULL)) {
perror("sigaction fallita");
exit(1);
if (sigaction(SIGTERM, &act, NULL)) {
perror("sigaction fallita");
exit(1);
// apertura descrittore
int fd = open("out.txt", O_WRONLY|O_CREAT|O_TRUNC, 0644);
if (fd == -1) {
perror("open fallita");
exit(1);
// chiusura descrittore
if (close(fd) == -1) {
perror("close fallita");
exit(1);


Revision [3484]

Edited on 2017-12-21 15:07:15 by EmilioCoppa
Additions:
Si completi codice presenti in ##primer.c## di modo che:
1) all'avvio del programma venga creato un file di output denominato out.txt (se il file esiste già, troncarne il contenuto) con permessi 0644;
2) writeToFile() scriva i primi len bytes nel buffer buf sul descrittore di file fd;
3) alla ricezione di un segnale TERM o alla pressione di CTRL-C da parte dell’utente la variabile globale shouldStop venga settata ad 1 (senza uscire immediatamente);
4) in uscita dal ciclo while del metodo main il descrittore del file venga chiuso.
Gestire eventuali errori restituiti dalle system call invocate. Per semplicità al punto 2 si assuma che interruzioni e scritture parziali non possano verificarsi.


Revision [3483]

Edited on 2017-12-21 15:04:50 by EmilioCoppa
Additions:
Si consideri il seguente codice:
%%(c;primer.c)
#include
#include
#include
#define START 86028157
volatile int shouldStop = 0;
void writeToFile(int fd, char* buf, int len) {
// DA COMPLETARE
int prime(unsigned int n) { // solo per n>=3 dispari
unsigned int i;
for (i=3; i if (n%i==0) return 0;
return 1;
int main() {
int fd = -1; // apertura descrittore - DA COMPLETARE
// main loop per generazione numeri e stringhe da salvare in out.txt
char buf[11];
unsigned int num = START, found = 0;
while (!shouldStop) {
if (prime(num)) {
int ret = sprintf(buf, "%u", num);
buf[ret++] = '\n';
writeToFile(fd, buf, ret);
++found;
}
num += 2;

printf("Numeri primi trovati partendo da %u: %u\n", START, found);


Revision [3482]

Edited on 2017-12-21 15:03:01 by EmilioCoppa
Additions:
=== Esercizio 2===


Revision [3481]

The oldest known version of this page was created on 2017-12-21 15:01:55 by EmilioCoppa
Valid XHTML 1.0 Transitional :: Valid CSS :: Powered by WikkaWiki
Page was generated in 0.0928 seconds