Difference between revisions of "Esercizio 1, prova pratica 29.05.2013"

From Sistemi Operativi
Jump to navigation Jump to search
 
(One intermediate revision by one other user not shown)
Line 67: Line 67:
  
 
==Soluzione di Maldus==
 
==Soluzione di Maldus==
 +
Semaforo implementato usando un altro eventfd.
 
<source lang="c">
 
<source lang="c">
 
#include <stdio.h>
 
#include <stdio.h>
Line 73: Line 74:
 
#include <sys/types.h>
 
#include <sys/types.h>
 
#include <signal.h>
 
#include <signal.h>
#include <semaphore.h>
+
 
  
 
int main(){
 
int main(){
sem_t empty , full ;
 
 
pid_t son ;
 
pid_t son ;
int ed , status, i;
+
int ed1 , ed2 , i;
 
uint64_t x = 1;
 
uint64_t x = 1;
ed = eventfd(0,0) ;
+
int y = 1 ;
sem_init( &full , 1 , 0) ;
+
ed1 = eventfd(0,0) ; /*eventfd usato per la comunicazione effettiva del numero*/
sem_init( &empty , 1 , 1 ) ;
+
ed2 = eventfd( 1 , EFD_SEMAPHORE ) ; /*eventfd usato come semaforo*/
 
switch( son = fork() ){
 
switch( son = fork() ){
 
case 0:
 
case 0:
while( x){
+
while( 1 ){
 +
read( ed1 , &x , 8) ; /*se ci sono dei dati li legge*/
 +
for(i = x ; i > 0 ; i--) printf( "x" ) ;
 +
printf("\n");
 +
write(ed2 , &y , 8 ) ; /*dopo la lettura dei dati, dà il via libera sul semaforo per scrivere di nuovo*/
 +
}
 +
return 1;
 +
default:
 +
while( x ){
 +
read( ed2 , &y , 8 ) ; /*si blocca sul semaforo se i dati non sono ancora stati letti*/
 
scanf("%" PRIu64 , &x) ;
 
scanf("%" PRIu64 , &x) ;
sem_wait(&empty) ;
+
write(ed1 , &x , 8 ) ; /*scrittura dei dati*/
write(ed , &x , 8 ) ;
 
sem_post(&full) ;
 
 
}
 
}
 
kill(son ,SIGTERM);
 
kill(son ,SIGTERM);
return 0 ;
+
return 0 ;
default:
 
while( 1 ){
 
sem_wait(&full);
 
read( ed , &x , 8) ;
 
for( i = x ; i > 0 ; i--) printf( "x\n" ) ;
 
sem_post(&empty) ;
 
}
 
return 1;
 
 
}
 
}
}
 
</source>
 
Siccome la write su di un event descriptor somma il valore dal buffer, se questa viene effettuata prima della lettura (che lo riporta a 0) il risultato ottenuto non è quello richiesto. Benchè sia altamente improbabile che una situazione del genere si verifichi in questo programma, ho cercato di evitarla usando i semafori (si tratta di un problema produttore/consumatore), senza successo: non riesco a capire perchè, ma sembra che le sem_post non incrementino il valore del semaforo.
 
Togliendo sem_wait e sem_post il programma funziona correttamente.
 
 
==Soluzione di Eddy==
 
Ho preso libera ispirazione da Maldus, ma ho usato la poll al posto dei semafori.
 
<source lang="c">
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <sys/eventfd.h>
 
#include <inttypes.h>
 
#include <sys/types.h>
 
#include <signal.h>
 
#include <poll.h> 
 
 
#define INF (-1)
 
 
int main()
 
{
 
  pid_t child;
 
  int efd, status;
 
  uint64_t x = 1;
 
  efd = eventfd(0,0);
 
 
  nfds_t nfds = 1;
 
  struct pollfd *fds = (struct pollfd *) malloc (sizeof (struct pollfd));
 
    fds->fd = efd;
 
    fds->events = POLLIN;
 
 
 
  switch (child = fork())
 
  {
 
    case 0:
 
      //child
 
      while (1)
 
      {
 
        int i;
 
        poll( fds, nfds, INF); // wait for data to read.
 
        read( efd , &x , 8);
 
        for ( i = x; i > 0; i--)
 
          printf( "x" ) ;
 
        printf ("\n");
 
      }
 
      return 1;
 
    default:
 
      //parent
 
      while (x){
 
        scanf("%" PRIu64 , &x) ;
 
        write(efd , &x , 8 ) ;
 
      }
 
      kill(child ,SIGTERM);
 
      return 0 ;
 
  }
 
 
}
 
}
 
</source>
 
</source>

Latest revision as of 10:28, 25 March 2015

Scrivere un programma testeventfd che faccia uso della system call eventfd.
In particolare il programma deve eseguire una fork, quando l'utente digita un numero letto dal processo padre, il processo
figlio deve stampare un numero uguale di x.

Soluzione di Pierg

#include <sys/eventfd.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h> 

int main (int argc, char *argv[]) {
	
	int efd, i; 
	long long unsigned int val;
    	ssize_t s;
	
	/* Check for eventfd error */
	efd = eventfd(0, 0);
	if (efd == -1) {
		perror("Eventfd Error"); 
	}

	/* Use fork to move eventfd form parent to child */
	switch (fork()) {
		
		case 0:
			/* Read parent event */
			s = read(efd, &val, sizeof(long long unsigned int));

            		if (s != sizeof(long long unsigned int)) {
                		perror("Read Error");
				exit(EXIT_FAILURE);
        		}

			/* For is used to print the 'x' of the argument passed by terminal */
			for (i = (int)val; i > 0; i--) {
				printf ("x\n");
			}

			exit(EXIT_SUCCESS);
		
		/* Check for error */
		case -1:
			perror("Fork Error"); 
			exit(EXIT_FAILURE);

		default:
			/* Wait for number */
			printf ("Inserisci un intero diverso da 0: \n");
			scanf ("%llu", &val);

			/* Write parent event */
           		s = write(efd, &val, sizeof(long long unsigned int));

            		if (s != sizeof(long long unsigned int)) {
                		perror("Write Error");
				exit(EXIT_FAILURE);
        		}
	
			exit(EXIT_SUCCESS);
	}
}

Soluzione di Maldus

Semaforo implementato usando un altro eventfd.

#include <stdio.h>
#include <sys/eventfd.h>
#include <inttypes.h>
#include <sys/types.h>
#include <signal.h>


int main(){
	pid_t son ;
	int ed1 , ed2 ,  i;
	uint64_t x = 1;
	int y = 1 ;
	ed1 = eventfd(0,0) ;	/*eventfd usato per la comunicazione effettiva del numero*/
	ed2 = eventfd( 1 , EFD_SEMAPHORE ) ;	/*eventfd usato come semaforo*/
	switch( son = fork() ){
		case 0:
			while( 1 ){
				read( ed1 , &x , 8) ;	/*se ci sono dei dati li legge*/
				for(i = x ; i > 0 ; i--) printf( "x" ) ;
				printf("\n");
				write(ed2 , &y , 8 ) ;	/*dopo la lettura dei dati, dà il via libera sul semaforo per scrivere di nuovo*/
				}
			return 1;
		default:
			while( x ){
				read( ed2 , &y , 8 ) ;	/*si blocca sul semaforo se i dati non sono ancora stati letti*/
				scanf("%" PRIu64 , &x) ;
				write(ed1 , &x , 8 ) ;	/*scrittura dei dati*/
			}
			kill(son ,SIGTERM);
			return 0 ;		
	}
}