Exercice 1.
Expliquer le fonctionnement du
programme suivant.
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <signal.h>
struct sigaction action;
void hand_sigusr1(int sig){
printf("(de %d) Signal SIGUSR1
recu\n", getpid());
exit(0);
}
int main() {
pid_t pid;
int i = 0;
int status;
action.sa_handler=hand_sigusr1;
sigaction(SIGUSR1,&action,NULL);
if((pid=fork())==0){
printf("Je suis le fils de PID %d\n",
getpid());
/* processus fils bouclant */
while(1) { i = 0; };
}
printf("Je suis le pere de PID %d\n", getpid());
if(kill(pid,0)==-1){
printf("(de %d) Fils %d inexistant\n",
getpid(), pid);
}
else{
printf("(de %d) Envoi du signal SIGUSR1 au
processus %d\n", getpid (), pid);
kill(pid,SIGUSR1);
}
pid=waitpid(pid,&status,0);
printf("(de %d) Status du fils %d : %d\n",getpid(),pid,status);
}
Exercice
2.
(Dispositif de l'homme mort.) Ecrire un programme qui prend un
entier n en
argument sur la ligne de commande et compte à rebours à
partir de n : le programme
doit afficher les valeurs n, n-1, n-2, ... à raison d'une
valeur toutes les secondes et il termine si le compteur atteint 0. Si l'utilisateur tape Ctrl+C avant que le compteur arrive
à 0, alors le compte
rebours reprend à partir de n.
Exemple d'exécution :
$ compte-a-rebours 5
5 4 3 2
(l'utilisateur tape Ctrl+C)
5 4 3 2 1 0
Alerte : vous dormez !
$
Exercice 3.
(Jeu de dés.) Ecrire un
programme qui boucle en
attendant que l'utilisateur tape Ctrl+C.
Lorsque
l'utilisateur tape Ctrl+C,
le programme choisit aléatoirement 2 valeurs entre 1 et 6 et les
affiche. Le programme termine lorsque l'utilisateur tape 2 fois Ctrl+C en moins d'1
seconde.
Exemple d'exécution :
$ jeu-de-des
(appui sur Ctrl+C)
2 3
(appui sur Ctrl+C)
5 1
appui sur Ctrl+C)
6 6
(appui 2 fois rapidemment sur
Ctrl+C)
$
Exercice 4.
La suite de Syracuse est définie par :
u(n+1)
= u(n)/2, si u(n) est pair
3u(n)
+ 1, sinon
Une conjecture est que quelque soit le terme initial u(0) (non nul) de
la suite, celle-ci finit par valoir 1 (puis par boucler sur 4, 2, 1).
Etant donnée une valeur initiale u(0) de la suite, on appelle
temps de vol, le plus petit indice k pour lequel u(k) = 1 pour la
première fois, et altitude maximale la valeur maximale prise par
la suite durant ce temps de vol. Nous utilisons un pro-
gramme calculant la suite de Syracuse pour chaque valeur initiale comme
exemple d’utilisation possible des signaux.
Pour simplifier, les variables liées à
la suite de Syracuse seront globales.
1. Ecrire une fonction void syracuse() qui étant
donnée une valeur initiale calcule les termes de la suite de
Syracuse jusqu’à ce qu’elle vaille 1.
2. Faire une boucle infinie pour i = 1, 2, 3, . . . qui
fixe u(0) = i et lance le calcul précédent. Le programme
boucle indéfiniment sans rien afficher.
3. Faire en sorte qu’à la réception du
signal SIGTSTP (Ctrl-Z), le programme affiche la valeur initiale
courante, l’indice du dernier terme calculé et la valeur prise
par la suite, sans stopper le programme.
4. Faire en sorte que Ctrl-C (SIGINT) termine le programme
en affichant : la plus grande valeur initiale testée ;
l’altitude maximale atteinte et la valeur initiale pour laquelle cette
altitude maximale est atteinte ; le temps de vol maximal et la valeur
initiale pour laquelle ce temps de vol a été atteint.
5. Faire en sorte que Ctrl-C ne termine pas le programme
mais que retaper Ctrl-C dans les deux secondes termine le programme
(utiliser une alarme).
Exercice 5.
On souhaite faire un programme qui :
– crée un tube et N processus fils où N est
donné en argument.
– Lorsqu’il reçoit le signal SIGUSR1, le
père écrit un nombre sur le tube et renvoie le signal
SIGUSR2 au fils qui à émis SIGUSR1.
– Chaque fils :
– s’il n’a rien à
faire émet le signal SIGUSR1 au père.
– s’il reçoit le signal
SIGUSR2, lit le nombre dans le tube et exécute un calcul long
sur ce nombre (on pourra simplement endormir le processus pendant 5
secondes).