Esercizio 1 - 25.09.2014

From Sistemi Operativi
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);
}

--Blissett (talk) 14:12, 11 March 2015 (CET)