Esercizio 1 - 25.09.2014
Jump to navigation
Jump to search
Scrivere un programma che preso come parametro un file contenente un elenco di comandi (con I relativi parametri) li attivi
tutti in esecuzione concorrente e rimanga in attesa. Quando il primo termina, vengono terminati (con segnale SIGTERM) tutti
gli altri. (consiglio: puo' essere utile usare la mia libreria s2argv-execs)
esempio:
wta commands
il file commands contiene:
./ttest 40
./ttest 10
./ttest 20
lo script ./ttest contiene:
#!/bin/bash
echo waiting for $1 seconds
sleep $1
echo done $1
l'ouptut sara':
waiting for 40 seconds
waiting for 10 seconds
waiting for 20 seconds
done 10
e poi basta perche' gli altri processi verranno terminati.
Possibile soluzione
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <s2argv.h>
#include <sys/types.h>
#include <signal.h>
#define MAX 20
int contaRighe (FILE *A){
char *a;
int i=0;
a= malloc (MAX*sizeof(char));
if (a==NULL) {
perror ("malloc");
return -1;
}
while (fgets(a, MAX, A)){
if (*a==EOF || *a=='\n') break;
i++;
}
return i;
}
int main (int argc, char *argv []){
int status;
int i=0;
int j=0;
int z=0; /*indice per ampiezza "pid_t ID" e "char *comando"*/
char *comando[z];
pid_t ID [z]; /* memorizza i pid di tutti i processi attivati */
pid_t terminato; /* memorizza il pid del primo processo che termina*/
FILE *fd = fopen (argv[1], "r");
if( fd==NULL ) {
perror("Errore in apertura del file");
return -1;
}
j=contaRighe (fd); /*ritorna il numero di righe del file dato in input*/
z=j; /* setto gli array con il numero di righe del file contenente i comandi */
rewind(fd); /*ritorno all'inizio del file*/
/* riempie "comando[z]" con tutti i comandi presenti nel file passato, i comando sono contati da 1 a z. */
while (j!=0){
comando [i] = malloc (MAX*sizeof(char));
fgets(comando [i], MAX, fd);
i++;
j--;
}
i--; /* diminuisco "i" di uno perchè prima di uscire dall'ultimo ciclo è aumentata di uno, "j" è uguale a 0 */
/*ESEGUE TUTTI I COMANDI */
while (i>=0){
switch (ID[j]=fork()) {
case 0:
execsp(comando[j]);
perror("exec");
case -1:
perror ("fork");
return -1;
}
i--;
j++;
}
i=0; /*setto "i" a 0 per il prossimo while */
terminato=wait(&status);
/* TERMINA TUTTI I PROCESSI */
while(i<j){ /* "i" strettamente minore di "j" poichè nell'ultimo ciclo del precedente while viene incrementata di uno */
if (ID[i]!=terminato) {
printf ("Termina processo %d\n",ID[i]);
kill(ID[i], SIGTERM); /* mando segnale di terminazione a tutti i PID che non sono ancora terminati */
}
else printf ("Processo completato %d\n",ID[i]);
i++;
}
fclose (fd);
return 0;
}
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <s2argv.h>
#include <signal.h>
int main(int argc, char *argv[]){
char buff[256];
int num_cmd=0, tmp=0, i=0, pfd[2];
FILE *file=fopen(argv[1], "r");
while(fgets(buff, sizeof(buff), file)!=NULL){//ottengo numero comandi
num_cmd++;
}
rewind(file);
char cmd[num_cmd][256];
int pid[num_cmd];
pipe(pfd);
for(i=0; i<num_cmd; i++){
fgets(cmd[i], sizeof(cmd[i]), file);
//printf("Comando %d: %s", i, cmd[i]);
switch(pid[i]=fork()){
case 0:
close(pfd[0]);
close(pfd[1]);
execsp(cmd[i]);
exit(1);
case -1: exit(1);
}
}
int status;
close(pfd[0]);
close(pfd[1]);
tmp=wait(&status);
for(i=0; i<num_cmd; i++){
if(tmp==pid[i])
continue;
kill(pid[i], SIGTERM);
printf("terminato il processo: pid[%d]=%d\n", i, pid[i]);
}
fclose(file);
}