diff --git a/README.md b/README.md index cd83089..0fc3e5b 100644 --- a/README.md +++ b/README.md @@ -441,8 +441,31 @@ $mytimeout nbsec com [arg ...] ## Exercice 3 +> Le but est de protéger un morceau de code d'un éventuellement déroutement à cause de la prise en compte d'un signal. + +1. Lancez le programme, et envoyez (depuis le terminal) le signal `SIGQUIT` souvent. La fonction `swap` est-elle interrompue ? comment le voyez-vous ? + +> On peut voir que la fonction `swap` est interrompue car quand nous envoyons le signal `SIGQUIT` souvent dans le terminal, le programme s'arrête pour afficher soit "x=2 y=2" soit "x=3 y=3", alors que si la fonction `swap` n'était pas interrompue, le programme afficherait soit "x=2 y=3" ou "x=3 y=2". + +2. Ajoutez le code nécessaire pour assurer que `swap` ne soit jamais interrompue par `SIGQUIT`. + ## Exercice 4 +> On va simuler un match de ping-pong entre un père et son fils, en utilisant le signal `SIGUSR1`. +- Le père commence à jouer. + +- On simule 10 échanges. À chaque coup, le père affiche Ping, le fils Pong. L'envoie de la balle consiste à envoyer le signal `SIGUSR1` à son adversaire. + +>La difficulté consiste à synchroniser correctement les échanges. + +1. Expliquez pourquoi ce code n'est pas correct (Faites varier `N`). + +> Ce code n'est pas correct car il n'y a pas de synchronisation entre le père et le fils, donc le père peut envoyer le signal `SIGUSR1` au fils alors que le fils n'est pas encore en attente, ce qui fait que le fils ne va pas recevoir le signal et donc ne va pas afficher `Pong`. + +2. Proposez une solution. + +> Pour synchroniser le père et le fils, on peut utiliser `sigprocmask` pour bloquer les signaux `SIGUSR1` dans le père et le fils, et les débloquer quand on veut envoyer le signal `SIGUSR1` au fils ou au père. + # TP 5 : Redirections, tubes ## Exercice 1 @@ -505,6 +528,44 @@ ls . | wc -l ## Exercice 3 +> Voici un programme qui calcule le nième terme de la suite de Fibonacci de manière récursive (ce n'est pas la meilleure approche comme vous le savez). + +```c +#include +#include +#include +#include +long int fibo (long int n) +{ + return (n<=1)?n:fibo(n-1)+fibo(n-2); +} + +int main(int argc, char *argv[]) +{ + long int n; + assert(argc > 1); + n=strtol(argv[1],NULL,0); + printf("fibo(%ld) = %ld\n",n,fibo(n)); + return 0; +} +``` + +> L'arbre d'appel correspondant pour n=4 : + +``` + fibo(4) + / \ + / \ + fibo(2) fibo(3) + / \ / \ + / \ / \ + fibo(0) fibo(1) fibo(1) fibo(2) + / \ + / \ + fibo(0) fibo(1) +``` +> Modifiez le programme pour qu'il crée 2 fils. Le premier calculera fibo(n-2), le deuxième fibo(n-1). Le père récupérera les résultats et les additionnera. La communication sera assurée par des tubes. + ## Exercice 4 > Le but est de mettre en oeuvre le cribble d'Ératosthène à l'aide d'une chaîne de processus reliés entre eux par des pipes. diff --git a/TP4/Exo3/helpers.c b/TP4/Exo3/helpers.c new file mode 100644 index 0000000..718fe40 --- /dev/null +++ b/TP4/Exo3/helpers.c @@ -0,0 +1,19 @@ +#include "helpers.h" +#include +#include + +int set_signal_handler(int signo, void (*handler)(int)) { + struct sigaction sa; + sa.sa_handler = handler; // call `handler` on signal + sigemptyset(&sa.sa_mask); // don't block other signals in handler + sa.sa_flags = SA_RESTART; // restart system calls + return sigaction(signo, &sa, NULL); +} + +double tstamp(void) { + struct timespec tv; + clock_gettime(CLOCK_REALTIME, &tv); + return tv.tv_sec + tv.tv_nsec * 1.0e-9; +} + + diff --git a/TP4/Exo3/helpers.h b/TP4/Exo3/helpers.h new file mode 100644 index 0000000..2084c6a --- /dev/null +++ b/TP4/Exo3/helpers.h @@ -0,0 +1,7 @@ +#ifndef _HELPERS_H +#define _HELPERS_H + +int set_signal_handler(int signo, void (*handler)(int)); +double tstamp(void); + +#endif diff --git a/TP4/Exo3/section_critique.c b/TP4/Exo3/section_critique.c new file mode 100644 index 0000000..82c9392 --- /dev/null +++ b/TP4/Exo3/section_critique.c @@ -0,0 +1,44 @@ +#include +#include +#include +#include +#include +#include +#include "helpers.h" +#include "helpers.c" + +int x = 2, y = 3; + +sigset_t quitset; + +int swap(int *x, int *y) +{ + sigemptyset(&quitset); + sigaddset(&quitset, SIGQUIT); + sigprocmask(SIG_BLOCK, &quitset, NULL); + + int tmp = *x; + *x = *y; + *y = tmp; + + sigprocmask(SIG_UNBLOCK, &quitset, NULL); +} + +void sig_handler(int signo) +{ + switch (signo) + { + case SIGQUIT: + printf("x=%d y=%d\n", x, y); + break; + } +} + +int main(int argc, char *argv[]) +{ + assert(set_signal_handler(SIGQUIT, sig_handler) == 0); + while (1) + { + swap(&x, &y); + } +} \ No newline at end of file