Prova Pratica 18-06-2015

From Sistemi Operativi
Jump to navigation Jump to search

Esercizio1

Usando signalfd (e non signal o sigaction) scrivere due programmi tx e rx.
Rx deve essere attivato per primo e per prima cosa stampa il suo pid e aspetta.
Tx ha due parametri: il pid del ricevente rx e una stringa.
Rx deve stampare la stringa passata come secondo parametro e uscire. La stringa deve essere spedita usando solo segnali.
Ogni bit di ogni carattere deve essere inviato usando SIGUSR1 se vale 1 e SIGUSR2 se vale 0.
Al ricevimento di ogni bit rx spedisce un segnale di acknowledgement a tx che provvede a spedire il successivo
// Esercizio1: Tx

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/signalfd.h>

#define EXIT_WITH_ERROR(function) \
	{ \
		printf("Error %i in ",errno); \
		printf(function); \
		printf(": %s\n",strerror(errno)); \
		exit(EXIT_FAILURE); \
	}

int main(int argc, char *argv[])
{
	pid_t rx;
	char *str;
	sigset_t mask;
	int sfd;
	struct signalfd_siginfo siginfo;
	
	if(argc != 3)
	{
		printf("Usage: Tx rx string\n");
		exit(1);
	}
	
	if(sscanf(argv[1],"%i",&rx) != 1)
		EXIT_WITH_ERROR("sscanf");
	str = argv[2];
	
	// setto il sigset_t a contenere SIGUSR1 (sara' l'acknowledgement)
	sigemptyset(&mask);
	sigaddset(&mask, SIGUSR1);
	
	// annullo l'azione standard per SIGUSR1
	if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
		EXIT_WITH_ERROR("sigprocmask")

	sfd = signalfd(-1, &mask, 0);
	if (sfd == -1)
		EXIT_WITH_ERROR("signalfd");
	
	while(1)
	{
		int i;
		char c = *str;
		
		// invia i bit del carattere (dal piu' al meno significativo)
		for(i=7; i>=0; i--)
		{
			if((c>>i)&1)	// prendo l'i-esimo bit di c:
			{				// SIGUSR1 se e' 1
				if(kill(rx,SIGUSR1) == -1)
					EXIT_WITH_ERROR("kill")
			}
			else 			// SIGUSR2 se invece e' 0
			{
				if(kill(rx,SIGUSR2) == -1)
					EXIT_WITH_ERROR("kill")
			}
			
			// attendo SIGUSR1 da Rx
			int len = read(sfd, &siginfo, sizeof(struct signalfd_siginfo));
			if(len != sizeof(struct signalfd_siginfo))
				EXIT_WITH_ERROR("read")
		}
		if(c == 0)	// esce se ha appena inviato fine-stringa
			break;
		str++;
	}
	return 0;
}
// Esercizio1: Rx

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/signalfd.h>

#define EXIT_WITH_ERROR(function) \
	{ \
		printf("Error %i in ",errno); \
		printf(function); \
		printf(": %s\n",strerror(errno)); \
		exit(EXIT_FAILURE); \
	}

int main(int argc, char *argv[])
{
	pid_t mypid;
	sigset_t mask;
	int sfd;
	struct signalfd_siginfo siginfo;
	char c;
	
	mypid = getpid();
	printf("%i\n",mypid);
	
	// setto il sigset_t
	sigemptyset(&mask);
	sigaddset(&mask, SIGUSR1);
	sigaddset(&mask, SIGUSR2);
	
	// annullo l'azione standard per SIGUSR1 e SIGUSR2
	if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
		EXIT_WITH_ERROR("sigprocmask")

	sfd = signalfd(-1, &mask, 0);
	if (sfd == -1)
		EXIT_WITH_ERROR("signalfd")
	
	do
	{
		int i;
		c = 0;
		
		// riceve 8 segnali per ogni carattere 
		for(i=7; i>=0; i--)
		{
			int len = read(sfd, &siginfo, sizeof(struct signalfd_siginfo));
			if(len != sizeof(struct signalfd_siginfo))
				EXIT_WITH_ERROR("read")
			
			if (siginfo.ssi_signo == SIGUSR1)	// se ho ricevuto SIGUSR1
				c = c | (1 << i);	// setto il bit a 1
			// altrimenti e' sicuramente SIGUSR2 => il bit resta 0
			
			kill(siginfo.ssi_pid, SIGUSR1);	// invio l'acknowledgement al mittente del segnale
		}
		printf("%c",c);
	} while(c != 0);	// se tutti i bit a 0 => fine stringa
	
	printf("\n");
	return 0;
}

Esercizio2

Si costruiscano due programmi txtime e rxnull per stimare l'efficienza di tx e rx.
Rxnull e' uguale all'rx precedente ma non stampa nulla.
Txtime ha come parametri il pid del ricevente e un numero intero n. Txtime deve spedire n caratteri 'K' al txtnull e alla fine deve stampare
il tempo medio impiegato per spedire un carattere.
// Esercizio2: txtime

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/signalfd.h>

#include <sys/timeb.h>

#define EXIT_WITH_ERROR(function) \
	{ \
		printf("Error %i in ",errno); \
		printf(function); \
		printf(": %s\n",strerror(errno)); \
		exit(EXIT_FAILURE); \
	}

int main(int argc, char *argv[])
{
	pid_t rx;
	int n;
	int j;
	
	// variabili per calcolare il tempo medio di trasmissione
	struct timeb time_start, time_end;
	int millisec;
	float media;
	
	sigset_t mask;
	int sfd;
	struct signalfd_siginfo siginfo;
	
	if(argc != 3)
	{
		printf("Usage: Tx rx string\n");
		exit(1);
	}
	
	if(sscanf(argv[1],"%i",&rx) != 1)
		EXIT_WITH_ERROR("sscanf");
	if(sscanf(argv[2],"%i",&n) != 1)
		EXIT_WITH_ERROR("sscanf");
	
	ftime(&time_start);
	
	// setto il sigset_t a contenere SIGUSR1 (sara' l'acknowledgement)
	sigemptyset(&mask);
	sigaddset(&mask, SIGUSR1);
	
	// annullo l'azione standard per SIGUSR1
	if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
		EXIT_WITH_ERROR("sigprocmask")

	sfd = signalfd(-1, &mask, 0);
	if (sfd == -1)
		EXIT_WITH_ERROR("signalfd");
	
	// invio n caratteri 'K' 
	for(j=0; j<n; j++)
	{
		int i;
		char c = 'K';
		
		for(i=7; i>=0; i--)
		{
			if((c>>i)&1)	// prendo l'i-esimo bit di c:
			{				// SIGUSR1 se e' 1
				if(kill(rx,SIGUSR1) == -1)
					EXIT_WITH_ERROR("kill")
			}
			else 			// SIGUSR2 se invece e' 0
			{
				if(kill(rx,SIGUSR2) == -1)
					EXIT_WITH_ERROR("kill")
			}
			
			// sospendo il processo in attesa div SIGUSR1
			int len = read(sfd, &siginfo, sizeof(struct signalfd_siginfo));
			if(len != sizeof(struct signalfd_siginfo))
				EXIT_WITH_ERROR("read")
		}
	}
	
	ftime(&time_end);
	
	// calcolo il tempo medio di trasmissione
	millisec = (time_end.time - time_start.time)*1000 + (time_end.millitm - time_start.millitm);
	media = (float)(millisec)/n;
	printf("Tempo medio: %f ms per carattere.\n",media);
}
// Esercizio2: rxnull

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/signalfd.h>

#define EXIT_WITH_ERROR(function) \
	{ \
		printf("Error %i in ",errno); \
		printf(function); \
		printf(": %s\n",strerror(errno)); \
		exit(EXIT_FAILURE); \
	}

int main(int argc, char *argv[])
{
	pid_t mypid;
	sigset_t mask;
	int sfd;
	struct signalfd_siginfo siginfo;
	char c;
	
	mypid = getpid();
	printf("%i\n",mypid);
	
	// setto il sigset_t
	sigemptyset(&mask);
	sigaddset(&mask, SIGUSR1);
	sigaddset(&mask, SIGUSR2);
	
	// annullo l'azione standard per SIGUSR1 e SIGUSR2
	if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
		EXIT_WITH_ERROR("sigprocmask")

	sfd = signalfd(-1, &mask, 0);
	if (sfd == -1)
		EXIT_WITH_ERROR("signalfd")
	
	do
	{
		int i;
		c = 0;
		
		for(i=7; i>=0; i--)
		{
			int len = read(sfd, &siginfo, sizeof(struct signalfd_siginfo));
			if(len != sizeof(struct signalfd_siginfo))
				EXIT_WITH_ERROR("read")
			
			if (siginfo.ssi_signo == SIGUSR1)	// se ho ricevuto SIGUSR1
				c = c | (1 << i);	// setto il bit a 1
			// altrimenti e' sicuramente SIGUSR2 => il bit resta 0
			
			kill(siginfo.ssi_pid, SIGUSR1);	// invio l'acknowledgement al mittente del segnale
		}
	} while(c != 0);	// se tutti i bit a 0 => fine stringa
	// NOTA: questo programma non termina normalmente se usato con txtime
	
	printf("\n");
}