1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
|
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <time.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <dirent.h>
#define MIN_VALUE 1
#define MAX_VALUE 99
#define TAILLE_CHAINE 256
volatile sig_atomic_t signal_recu = 0;
void raler (const char *msg)
{
perror (msg);
exit (1);
}
int getrandint (int a, int b)
{
srand(time(NULL)); // Initialisation du générateur de nombres aléatoires
return rand() % (b - a + 1) + a; // Retourne un entier aléatoire compris entre a et b inclus
}
void handler_usr (int signum)
{
if (signum == SIGUSR1)
{
signal_recu = 1;
} else if (signum == SIGUSR2)
{
signal_recu = 2;
}
}
void handler_fin (int signum)
{
(void) signum;
signal_recu = 3;
// Ajoutez ici les actions à exécuter à la réception de SIGTERM
}
void preparer(void) {
struct sigaction sa_usr, sa_fin;
// Préparation des actions pour les signaux SIGUSR1 et SIGUSR2
sa_usr.sa_handler = handler_usr;
sigemptyset(&sa_usr.sa_mask);
sa_usr.sa_flags = 0;
sigaction(SIGUSR1, &sa_usr, NULL);
sigaction(SIGUSR2, &sa_usr, NULL);
// Préparation de l'action pour le signal SIGTERM
sa_fin.sa_handler = handler_fin;
sigemptyset(&sa_fin.sa_mask);
sa_fin.sa_flags = 0;
sigaction(SIGTERM, &sa_fin, NULL);
}
void fils (int tube)
{
// Envoi 1ère proposition
int proposition = getrandint (MIN_VALUE, MAX_VALUE);
pid_t pid_fils = getpid ();
// Création de la chaîne de caractères à envoyer
char message[TAILLE_CHAINE];
snprintf(message, sizeof(message), "%d:%d", pid_fils, proposition);
if (write(tube, message, strlen(message)+1) < 0)
{
raler("Erreur écriture 1ère proposition dans tube");
}
printf ("Message 1 : %s\n", message);
sigset_t new, old, vide;
while(1)
{
sigemptyset (&new);
sigaddset (&new, SIGUSR1);
sigaddset (&new, SIGUSR2);
sigaddset (&new, SIGTERM);
sigprocmask (SIG_BLOCK, &new, &old);
printf ("Valeur de signal recu 1 %i\n", signal_recu);
if (! signal_recu)
{
sigemptyset (&vide);
sigsuspend (&vide); // Attente de la réception d'un signal
}
sigprocmask (SIG_SETMASK, &old, NULL);
printf ("Valeur de signal recu 2 %i\n", signal_recu);
// Vérification du signal reçu
if (signal_recu == 1)
{
proposition -= 1; // Décrémentation de la proposition
} else if (signal_recu == 2)
{
proposition += 1; // Incrémentation de la proposition
} else if (signal_recu == 3)
{
// Terminaison de la fonction en cas de réception de SIGTERM
printf("Terminaison du processus fils\n");
return;
}
// Envoi de la nouvelle proposition sur le tube
snprintf(message, sizeof(message), "%d:%d", pid_fils, proposition);
printf ("Message dans boucle : %s\n", message);
if (write(tube, message, TAILLE_CHAINE) < 0)
{
raler ("Erreur écriture nouvelle proposition dans tube");
}
}
}
pid_t lecture(int val, int tube)
{
int valeur_lue;
pid_t pid_du_fils_qui_a_ecrit;
char chaine_lue[TAILLE_CHAINE];
// Bloque les signaux SIGUSR1, SIGUSR2 et SIGTERM pendant la lecture dans le tube
sigset_t masque;
sigemptyset(&masque);
sigaddset(&masque, SIGUSR1);
sigaddset(&masque, SIGUSR2);
sigaddset(&masque, SIGTERM);
sigprocmask(SIG_BLOCK, &masque, NULL);
// Pb : lire les valeurs dans le tube et connaître le pid du fils qui écrit
// chaque valeur
while (read(tube, chaine_lue, TAILLE_CHAINE) > 0)
{
// Extraction du pid et de la proposition depuis la chaîne lue
pid_du_fils_qui_a_ecrit = atoi(strtok(chaine_lue, ":"));
valeur_lue = atoi(strtok(NULL, ":"));
printf ("Pid = %i\n", pid_du_fils_qui_a_ecrit);
printf ("Valeur = %i\n", valeur_lue);
// On compare
if (valeur_lue > val)
{
// Ici, comment trouver le bon pid ?
kill (pid_du_fils_qui_a_ecrit, SIGUSR1);
} else if (valeur_lue < val)
{
kill (pid_du_fils_qui_a_ecrit, SIGUSR2);
} else
{
kill (pid_du_fils_qui_a_ecrit, SIGTERM);
kill (0, SIGTERM);
return pid_du_fils_qui_a_ecrit;
}
}
sigprocmask(SIG_UNBLOCK, &masque, NULL); // Débloque les signaux SIGUSR1, SIGUSR2 et SIGTERM
return pid_du_fils_qui_a_ecrit;
}
void attendre_fils (int n)
{
// On attend n fois (nb de processus fils) que le processus se termine
for (int i = 0; i < n; i++)
{
int raison;
if (wait (&raison) == -1)
raler ("wait");
if (WIFEXITED (raison))
{
printf ("code de retour du fils %d\n", WEXITSTATUS (raison));
} else
{
raler ("Erreur exit");
}
}
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
raler ("usage: ./devinette <nb_secret> <nb_de_processus>");
}
int nb_secret = atoi (argv[1]);
int nb_de_processus = atoi (argv[2]);
// On prépare avant le fork
preparer ();
int tube[2];
if (pipe(tube) == -1)
{
raler ("Erreur création tube");
}
pid_t pid;
int i;
for (i = 0; i < nb_de_processus; i++) {
switch (pid = fork())
{
case -1:
raler ("Fork");
break;
case 0:
printf ("%i fils\n", i);
//Fils
close (tube[0]);
fils (tube[1]);
close (tube[1]);
exit (0);
default:
break;
}
}
close (tube[1]);
int vainqueur = lecture (nb_secret, tube[0]);
close (tube[0]);
printf("Le fils avec PID %d a trouvé le nombre secret\n", vainqueur);
attendre_fils (nb_de_processus);
return 0;
} |
Partager