This repository has been archived by the owner on May 13, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
worker.c
160 lines (139 loc) · 5.79 KB
/
worker.c
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
#if defined HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include "myassert.h"
#include "master_worker.h"
// Bibliothéques ajoutés
#include <unistd.h> // Pour: fork, pipe
#include <sys/types.h> // Pour: wait
#include <sys/wait.h> // Pour: wait
/************************************************************************
* Données persistantes d'un worker
************************************************************************/
// on peut ici définir une structure stockant tout ce dont le worker
// a besoin : le nombre premier dont il a la charge, ...
typedef struct worker
{
int prime;
int previous_pipe;
int next_pipe;
int master_pipe;
} workerDonnees;
/************************************************************************
* Usage et analyse des arguments passés en ligne de commande
************************************************************************/
static void usage(const char *exeName, const char *message)
{
fprintf(stderr, "usage : %s <n> <fdIn> <fdToMaster>\n", exeName);
fprintf(stderr, " <n> : nombre premier géré par le worker\n");
fprintf(stderr, " <fdIn> : canal d'entrée pour tester un nombre\n");
fprintf(stderr, " <fdToMaster> : canal de sortie pour indiquer si un nombre est premier ou non\n");
if (message != NULL)
fprintf(stderr, "message : %s\n", message);
exit(EXIT_FAILURE);
}
static void parseArgs(int argc, char * argv[], workerDonnees *data)
{
if (argc != 4)
usage(argv[0], "Nombre d'arguments incorrect");
// Convertit les arguments en entier
int prime = atoi(argv[1]);
int fd_RD = atoi(argv[2]);
int fd_WR = atoi(argv[3]);
// Remplit la structure
data->prime = prime;
data->previous_pipe = fd_RD;
data->next_pipe = NO_NEXT;
data->master_pipe = fd_WR;
}
/************************************************************************
* Boucle principale de traitement
************************************************************************/
void loop(workerDonnees data)
{
// Boucle infinie
while (true)
{
// Attente de l'arrivée d'un nombre à tester
int number = workerNumberToCompute(data.previous_pipe);
// Si c'est un ordre d'arrêt
if (number == STOP)
{
// Si il y a un worker suivant
if (data.next_pipe != NO_NEXT)
{
// On transmet l'ordre d'arrêt au suivant
// et on attend que le suivant se soit terminé
workerToNextWorker(data.next_pipe, STOP);
wait(NULL);
}
// On sort de la boucle
printf("Destruction du worker qui a pour charge le nombre premier %d\n", data.prime);
break;
}
// Si c'est un nombre à tester
else
{
// Si le nombre à tester est égal au nombre premier dont le worker à la charge
if (number == data.prime)
{
workerIsPrime(data.master_pipe, NUMBER_IS_PRIME); // SUCCES
}
// Si le nombre à tester est divisible par le nombre premier dont le worker à la charge
else if ((number % data.prime) == 0)
{
workerIsPrime(data.master_pipe, NUMBER_NOT_PRIME); // ECHEC
}
// Si il y a un worker suivant alors lui transmettre le nombre à tester
else if (data.next_pipe != NO_NEXT)
{
workerToNextWorker(data.next_pipe, number); // Transmission au suivant
}
// Sinon il faut créer le nouveau worker qui aura la charge du nombre à tester qui est donc premier
else
{
// Création du tube anonyme connectant 2 workers
int workerToWorkerPipe[2];
int ret = pipe(workerToWorkerPipe);
myassert(ret != -1, "Le tube anonyme Worker->Worker s'est mal créé");
// Création d'un nouveau processus pour executer le premier worker
pid_t ret_fork = fork();
myassert(ret_fork != -1, "Le fork du master pour créer les workers s'est mal exécuté");
// Processus fils issus du fork
if (ret_fork == 0)
{
// On envoie au prochain worker le tube anonyme lui permettant
// de lire les données que le worker précédent lui evoie
// ainsi que le tube vers le master et le nombre premier dont il a la charge
int fdReadingWorker = readingSidePipe(workerToWorkerPipe);
createWorker(number, fdReadingWorker, data.master_pipe); // Exec donc le fils s'arrête ici
}
// Processus père issus du fork
// On initialise le tube anonyme suivant vers le nouveau worker qui vient d'être crée
int fdWritingWorker = writingSidePipe(workerToWorkerPipe);
data.next_pipe = fdWritingWorker;
}
}
}
}
/************************************************************************
* Programme principal
************************************************************************/
int main(int argc, char * argv[])
{
// Déclaration de la structure à remplir
workerDonnees data;
// Traitement des arguments envoyé au master lors de sa création
parseArgs(argc, argv, &data);
// Quand le worker est crée on envoie le nombre premier
// de celui-ci au master
workerIsPrime(data.master_pipe, data.prime);
// Boucle infinie pour tester si un nombre est premier
loop(data);
// Libérer les ressources : fermeture des files descriptors par exemple
closeFD(data.previous_pipe, data.next_pipe, data.master_pipe);
return EXIT_SUCCESS;
}