Prova Pratica 18-06-2015
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");
}