Esercizio 1 Prova Pratica 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 $i
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.

Soluzione di Stefano Zaniboni

#include <stdio.h>
#include <s2argv.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <error.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <poll.h>

int main(int argc, char *argv[]){
   FILE *stream;
   char *line=NULL;
   size_t len=0;
   ssize_t read;
   int i=0;
   int status;
   pid_t fineFirst; /*memorizzo il pid del primo processo terminato*/
   pid_t all[i];
   int pipefd[2];
   struct pollfd pipe_read_poll;

   if(argc!=2){
      fprintf(stderr,"Argomento Mancante!\n");
      exit(1);
   }

   stream=fopen(argv[1], "r");
   if(stream == NULL)
      exit(EXIT_FAILURE);

   /*aprire una pipe, dentro al while dove ho la fork fare poll che aspetta un carattere dalla pipe. Lo mando finito il while*/
   pipe(pipefd);
   pipe_read_poll.fd = pipefd[0];
   pipe_read_poll.events = POLLIN;

   while((read = getline(&line, &len, stream)) != -1) {
      if(fork()==0){
         i++;
         char **lines=s2argv(line, NULL);
         poll(&pipe_read_poll,1,-1);
         execvp(lines[0], lines);
         all[i]=getpid(); /**/
         s2argv_free(lines);
         perror("execvp fail!");
         exit(1);
      }
      else
         exit(2);
   }

   /*inviare carattere alla pipe*/
   char buf='g';
   write(pipefd[1], &buf, 1);
   fineFirst=wait(&status);
   /*kill the rest of process*/
   while(i > 0){
      if(all[i] != fineFirst){
         kill(all[i], SIGTERM);
      }
      --i;
   }
   fclose(stream);
   exit(0);
}