Difference between revisions of "Esercizio 1 Prova Pratica 25-09-2014"

From Sistemi Operativi
Jump to navigation Jump to search
Line 1: Line 1:
 
<source lang ="text">
 
<source lang ="text">
 +
'''Esercizio 1'''
 
Scrivere un programma che preso come parametro un file contenente un elenco di comandi (con I relativi parametri)
 
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.  
 
  li attivi tutti in esecuzione concorrente e rimanga in attesa. Quando il primo termina, vengono terminati (con segnale SIGTERM) tutti gli altri.  
Line 92: Line 93:
  
 
</source>
 
</source>
 +
 +
<source lang ="text">
 +
'''Esercizio 2'''
 +
Completare wta in modo che l'output di ogni comando venga salvato separatemente e solo l'output del processo terminato per
 +
primo venga mostrato.
 +
Nell'esempio di prima l'output dovra' essere:
 +
waiting for 10 seconds
 +
 +
done 10
 +
</source>
 +
 +
==Soluzione di Maldus==
 +
<source lang="c">
 +
#include <s2argv.h>
 +
#include <poll.h>
 +
#include <fcntl.h>
 +
#include <sys/stat.h>
 +
#include <stdlib.h>
 +
#include <unistd.h>
 +
#include <stdio.h>
 +
#include <sys/types.h>
 +
#include <signal.h>
 +
 +
int main(int argc, char* argv[]){
 +
        int i=0, status, out;
 +
        FILE *fd, *output;
 +
        pid_t *idents, winner;
 +
        char *line=NULL, *string;
 +
        size_t n=1;
 +
        int pipefd[2];
 +
        pipe(pipefd);
 +
        struct pollfd pipepoll;
 +
        pipepoll.fd = pipefd[0];
 +
        pipepoll.events = POLLIN;
 +
        if( !(fd = fopen(argv[1], "r"))){
 +
                perror("fopen:");
 +
                exit(1);
 +
        }
 +
        while( getline(&line, &n, fd) > 0){
 +
                i++;
 +
                free(line);
 +
                line=NULL;
 +
        }
 +
        idents = malloc(sizeof(pid_t)*i);
 +
        rewind(fd);
 +
        i = 0;
 +
        while( getline(&line, &n, fd) >0 ){
 +
                switch( idents[i]=fork()){
 +
                        case 0:
 +
                                asprintf( &string, "out%i" ,getpid());
 +
                                if( (out=open(string, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR)) <0){
 +
                                        perror("open");
 +
                                        exit(1);
 +
                                }
 +
                                free(string);
 +
                                dup2(out, 1);
 +
                                close(out);
 +
                                poll(&pipepoll, 1, -1);
 +
                                execsp(line);
 +
                                exit(0);
 +
                        default:
 +
                                free(line);
 +
                                line=NULL;
 +
                                i++;
 +
                                break;
 +
                }
 +
        }
 +
        write(pipefd[1], "g", 1);
 +
        winner = wait(&status);
 +
        i--;
 +
        for( ; i >= 0 ; i--){
 +
                if(idents[i]!=winner){
 +
                        kill(idents[i], SIGTERM);
 +
                        asprintf( &string, "out%i", idents[i]);
 +
                        unlink(string);
 +
                        free(string);
 +
                }
 +
        }
 +
        asprintf( &string, "out%i" , winner);
 +
        if( !(output = fopen(string, "r"))){
 +
                perror("fopen");
 +
                exit(1);
 +
        }
 +
        while( getline(&line, &n, output)>0){
 +
                printf("%s", line);
 +
                free(line);
 +
                line=NULL;
 +
        }
 +
        unlink(string);
 +
        fclose(fd);
 +
        fclose(output);
 +
        return 0 ;
 +
}
 +
</source>
 +
 +
Per stampare solo l'output del processo vincente salvo quello di ciascun processo in un file di testo ( che poi cancello ). Mi viene però da pensare che debba esistere un modo migliore per farlo...

Revision as of 12:16, 9 May 2015

'''Esercizio 1'''
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);
}
'''Esercizio 2'''
Completare wta in modo che l'output di ogni comando venga salvato separatemente e solo l'output del processo terminato per
primo venga mostrato. 
Nell'esempio di prima l'output dovra' essere:
waiting for 10 seconds

done 10

Soluzione di Maldus

#include <s2argv.h>
#include <poll.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>

int main(int argc, char* argv[]){
        int i=0, status, out;
        FILE *fd, *output;
        pid_t *idents, winner;
        char *line=NULL, *string;
        size_t n=1;
        int pipefd[2];
        pipe(pipefd);
        struct pollfd pipepoll;
        pipepoll.fd = pipefd[0];
        pipepoll.events = POLLIN;
        if( !(fd = fopen(argv[1], "r"))){
                perror("fopen:");
                exit(1);
        }
        while( getline(&line, &n, fd) > 0){
                i++;
                free(line);
                line=NULL;
        }
        idents = malloc(sizeof(pid_t)*i);
        rewind(fd);
        i = 0;
        while( getline(&line, &n, fd) >0 ){
                switch( idents[i]=fork()){
                        case 0:
                                asprintf( &string, "out%i" ,getpid());
                                if( (out=open(string, O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR)) <0){
                                        perror("open");
                                        exit(1);
                                }
                                free(string);
                                dup2(out, 1);
                                close(out);
                                poll(&pipepoll, 1, -1);
                                execsp(line);
                                exit(0);
                        default:
                                free(line);
                                line=NULL;
                                i++;
                                break;
                }
        }
        write(pipefd[1], "g", 1);
        winner = wait(&status);
        i--;
        for( ; i >= 0 ; i--){
                if(idents[i]!=winner){
                        kill(idents[i], SIGTERM);
                        asprintf( &string, "out%i", idents[i]);
                        unlink(string);
                        free(string);
                }
        }
        asprintf( &string, "out%i" , winner);
        if( !(output = fopen(string, "r"))){
                perror("fopen");
                exit(1);
        }
        while( getline(&line, &n, output)>0){
                printf("%s", line);
                free(line);
                line=NULL;
        }
        unlink(string);
        fclose(fd);
        fclose(output);
        return 0 ;
}

Per stampare solo l'output del processo vincente salvo quello di ciascun processo in un file di testo ( che poi cancello ). Mi viene però da pensare che debba esistere un modo migliore per farlo...