Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
T
TP3_Bykes
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
khalil.elajeri
TP3_Bykes
Commits
7141ac60
Commit
7141ac60
authored
3 weeks ago
by
Lou Davila
Browse files
Options
Downloads
Patches
Plain Diff
Lou Final version code+doc
parent
d82ec91d
Branches
main
No related tags found
No related merge requests found
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
TP3_rapport_bykes.txt
+99
-0
99 additions, 0 deletions
TP3_rapport_bykes.txt
byke_simulation
+0
-0
0 additions, 0 deletions
byke_simulation
tp.c
+64
-24
64 additions, 24 deletions
tp.c
with
163 additions
and
24 deletions
TP3_rapport_bykes.txt
0 → 100644
+
99
−
0
View file @
7141ac60
TP3 : Gestion d’un parc de vélos
Nom : El Ajeri Nom : Davila Prado
Prénom : Khalil Mokhtar Prénom : Lou
Groupe : 14
--------------------------------------------------
Statut du projet
--------------------------------------------------
Projet fonctionnel.
- Le programme gère correctement la concurrence entre threads à l’aide de mutex et sémaphores.
- Tous les trajets sont effectués sans blocage (tests répétés).
- Le nombre total de vélos reste constant à la fin de la simulation : S * (N - 2) + 2.
- Chaque site possède entre 0 et N vélos à la fin.
- Les affichages reflètent bien les prises, dépôts, attentes et les actions du camion.
- La logique du dépôt et du rééquilibrage est bien gérée.
- Les délais usleep ont été désactivés pour les tests de performance/stabilité.
- On a eu un bug avec un grand nombre d'habitants donc à cause de la concurrence au niveau de la gestion des vélos
qu'on a pu régler par la suite.
--------------------------------------------------
Algorithme de gestion des habitants
--------------------------------------------------
Chaque habitant est un thread. Il effectue M trajets :
1. Il attend passivement qu’un vélo soit disponible sur son site actuel (sémaphore velos), en incrémentant personnes_attente.
2. Une fois le vélo obtenu, il décrémente le compteur local velos_dispo du site, puis libère une borne (bornes).
3. Il choisit un autre site (aléatoirement) et attend passivement qu’une borne soit libre (sémaphore bornes) pour y déposer le vélo.
4. Il incrémente alors velos_dispo de ce site, poste sur le sémaphore velos, et libère ainsi le vélo pour un autre utilisateur.
Toutes les modifications des variables critiques (velos_dispo, personnes_attente) sont protégées par un mutex par site.
Un mutex global (mutex_trajets) est utilisé pour suivre le nombre total de trajets réalisés par tous les habitants.
--------------------------------------------------
Gestion de la concurrence
--------------------------------------------------
- Les accès partagés (velos_dispo, bornes, velos, personnes_attente, variables utilisées dans les printf) sont protégés par des mutex individuels.
- Les accès globaux (trajets_effectues, velos_depot) sont protégés par des mutex globaux.
- Les sémaphores assurent des attentes passives :
- velos pour prendre un vélo.
- bornes pour déposer un vélo.
- Les sections critiques sont réduites au strict minimum.
- Chaque affichage est fait après la section critique pour limiter la contention.
--------------------------------------------------
Fonctions codées:
--------------------------------------------------
void *habitant(void *arg)
---------------------------------
Cette fonction représente le comportement d’un habitant modélisé par un thread.
- Chaque habitant commence à un site choisi aléatoirement.
- Il effectue TRAJETS fois la séquence de prise et dépôt de vélo entre deux sites différents.
- Il utilise les sémaphores pour attendre passivement la disponibilité d’un vélo ou d’une borne.
- Les compteurs internes (velos_dispo, personnes_attente) sont mis à jour dans des sections critiques protégées par mutex.
- Le compteur global trajets_effectues est également protégé par un mutex.
- À chaque dépôt de vélo, le site actuel est mis à jour.
- Les affichages indiquent les actions de l’habitant et les situations d’attente.
void *gestion_camion(void *arg)
---------------------------------
Cette fonction modélise la camionnette de maintenance qui équilibre les vélos entre les sites.
- Elle tourne tant que tous les trajets ne sont pas effectués (condition vérifiée avec mutex_trajets).
- Pour chaque site :
a. Si trop de vélos : enlève jusqu’à CAMION_CAPACITE - velos_camion vélos pour atteindre N - 2.
b. Si trop peu de vélos : ajoute jusqu’à 2 vélos selon disponibilité du camion et bornes.
- Après la boucle des sites :
a. Dépôt des vélos excédentaires si velos_camion > 2.
b. Recharge depuis le dépôt si velos_camion < 2.
- L’accès au dépôt est protégé par mutex_velos_depot.
- Le comportement respecte la capacité max du camion (4 vélos).
int main(int argc, char *argv[])
---------------------------------
Fonction principale qui :
- Récupère les paramètres SITES, HABITANTS, TRAJETS et BORNES depuis la ligne de commande.
- Initialise les sémaphores et mutex de chaque site.
- Lance les threads pour chaque habitant et un thread pour le camion.
- Attend la fin de tous les threads avec pthread_join.
- Affiche les vélos par site et la vérification du total global à la fin de l’exécution.
- Détruit les sémaphores et mutex à la fin.
--------------------------------------------------
Bugs résiduels
--------------------------------------------------
Lorsqu'un trop grand nombre d'habitants est spécifié au lancement du programme, le programme finit par se bloquer après un certain temps d'exécution.
Nous pensons que ceci est dû à un trop grand nombre de threads concurrents crées par rapport à la capacité de la machine.
Il faudrait probablement limiter le nombre de threads créés simultanement pour éviter ce genre de problème.
--------------------------------------------------
Conclusion
--------------------------------------------------
Le programme respecte toutes les exigences du TP : cohérence des vélos, absence de blocage, affichages pertinents, gestion propre de la concurrence.
\ No newline at end of file
This diff is collapsed.
Click to expand it.
tp
→
byke_simulation
+
0
−
0
View file @
7141ac60
No preview for this file type
This diff is collapsed.
Click to expand it.
tp.c
+
64
−
24
View file @
7141ac60
/*Authors: Lou Davila Prado, Khalil El Ajeri
Groupe: 14*/
#include
<stdio.h>
#include
<stdlib.h>
#include
<pthread.h>
...
...
@@ -14,7 +17,7 @@ typedef struct
int
velos_dispo
;
int
personnes_attente
;
pthread_mutex_t
mutex
;
}
Site
;
}
Site
;
int
SITES
,
HABITANTS
,
TRAJETS
,
BORNES
;
Site
*
sites
;
...
...
@@ -36,38 +39,46 @@ void *habitant(void *arg)
{
site_suivant
=
rand
()
%
SITES
;
}
while
(
site_
suivant
==
site_
actuel
);
while
(
site_
actuel
==
site_
suivant
);
pthread_mutex_lock
(
&
sites
[
site_actuel
].
mutex
);
sites
[
site_actuel
].
personnes_attente
++
;
int
velos
=
sites
[
site_actuel
].
velos_dispo
;
int
attente
=
sites
[
site_actuel
].
personnes_attente
;
pthread_mutex_unlock
(
&
sites
[
site_actuel
].
mutex
);
printf
(
"(GET) Habitant %d attend un vélo au site %d
\n
"
,
habitant_id
,
site_actuel
);
printf
(
"(GET) Habitant %d attend un vélo au site %d
(%d vélos, %d personnes en attente)
\n
"
,
habitant_id
,
site_actuel
,
velos
,
attente
);
sem_wait
(
&
sites
[
site_actuel
].
velos
);
pthread_mutex_lock
(
&
sites
[
site_actuel
].
mutex
);
sites
[
site_actuel
].
velos_dispo
--
;
sites
[
site_actuel
].
personnes_attente
--
;
velos
=
sites
[
site_actuel
].
velos_dispo
;
attente
=
sites
[
site_actuel
].
personnes_attente
;
pthread_mutex_unlock
(
&
sites
[
site_actuel
].
mutex
);
printf
(
"(GET) Habitant %d prend un vélo au site %d
\n
"
,
habitant_id
,
site_actuel
);
printf
(
"(GET) Habitant %d prend un vélo au site %d
(%d vélos, %d personnes en attente)
\n
"
,
habitant_id
,
site_actuel
,
velos
,
attente
);
sem_post
(
&
sites
[
site_actuel
].
bornes
);
//usleep((rand()%1000+1000));
pthread_mutex_lock
(
&
sites
[
site_suivant
].
mutex
);
sites
[
site_suivant
].
personnes_attente
++
;
velos
=
sites
[
site_suivant
].
velos_dispo
;
attente
=
sites
[
site_suivant
].
personnes_attente
;
pthread_mutex_unlock
(
&
sites
[
site_suivant
].
mutex
);
printf
(
"(PUT) Habitant %d attend d'avoir accès à une borne du site %d
\n
"
,
habitant_id
,
site_suivant
);
printf
(
"(PUT) Habitant %d attend d'avoir accès à une borne du site %d
(%d vélos, %d personnes en attente)
\n
"
,
habitant_id
,
site_suivant
,
velos
,
attente
);
sem_wait
(
&
sites
[
site_suivant
].
bornes
);
pthread_mutex_lock
(
&
sites
[
site_suivant
].
mutex
);
sites
[
site_suivant
].
velos_dispo
++
;
sites
[
site_suivant
].
personnes_attente
--
;
velos
=
sites
[
site_suivant
].
velos_dispo
;
attente
=
sites
[
site_suivant
].
personnes_attente
;
pthread_mutex_unlock
(
&
sites
[
site_suivant
].
mutex
);
sem_post
(
&
sites
[
site_suivant
].
velos
);
printf
(
"(PUT) Habitant %d dépose un vélo au site %d
\n
"
,
habitant_id
,
site_suivant
);
printf
(
"(PUT) Habitant %d dépose un vélo au site %d
(%d vélos, %d personnes en attente)
\n
"
,
habitant_id
,
site_suivant
,
velos
,
attente
);
//usleep((rand()%1000+1000));
site_actuel
=
site_suivant
;
...
...
@@ -96,6 +107,8 @@ void *gestion_camion(void *arg)
for
(
int
i
=
0
;
i
<
SITES
;
i
++
)
{
pthread_mutex_lock
(
&
sites
[
i
].
mutex
);
int
velos
=
sites
[
i
].
velos_dispo
;
int
attente
=
sites
[
i
].
personnes_attente
;
if
(
CAMION_CAPACITE
>
velos_camion
&&
sites
[
i
].
velos_dispo
>
BORNES
-
2
)
{
...
...
@@ -110,15 +123,23 @@ void *gestion_camion(void *arg)
aRetirer
=
sites
[
i
].
velos_dispo
-
1
;
}
pthread_mutex_unlock
(
&
sites
[
i
].
mutex
);
for
(
int
j
=
0
;
j
<
aRetirer
;
j
++
)
{
sem_wait
(
&
sites
[
i
].
velos
);
pthread_mutex_lock
(
&
sites
[
i
].
mutex
);
sites
[
i
].
velos_dispo
--
;
velos
=
sites
[
i
].
velos_dispo
;
attente
=
sites
[
i
].
personnes_attente
;
pthread_mutex_unlock
(
&
sites
[
i
].
mutex
);
velos_camion
++
;
sem_post
(
&
sites
[
i
].
bornes
);
}
printf
(
"Camion prend d
es
vélos au site %d (Vélos dans camion: %d)
\n
"
,
i
,
velos_camion
);
printf
(
"Camion prend
%
d vélos au site %d
(%d vélos, %d personnes en attente)
(Vélos dans
le
camion: %d)
\n
"
,
aRetirer
,
i
,
velos
,
attente
,
velos_camion
);
}
else
if
(
sites
[
i
].
velos_dispo
<
2
&&
velos_camion
>
0
)
{
...
...
@@ -134,18 +155,29 @@ void *gestion_camion(void *arg)
aAjouter
=
spotsDisponibles
;
}
pthread_mutex_unlock
(
&
sites
[
i
].
mutex
);
for
(
int
j
=
0
;
j
<
aAjouter
;
j
++
)
{
sem_wait
(
&
sites
[
i
].
bornes
);
pthread_mutex_lock
(
&
sites
[
i
].
mutex
);
sites
[
i
].
velos_dispo
++
;
velos
=
sites
[
i
].
velos_dispo
;
attente
=
sites
[
i
].
personnes_attente
;
pthread_mutex_unlock
(
&
sites
[
i
].
mutex
);
velos_camion
--
;
sem_post
(
&
sites
[
i
].
velos
);
}
printf
(
"Camion dépose des vélos au site %d (Vélos dans camion: %d)
\n
"
,
i
,
velos_camion
);
printf
(
"Camion dépose %d vélos au site %d (%d vélos, %d personnes en attente) (Vélos dans le camion: %d)
\n
"
,
aAjouter
,
i
,
velos
,
attente
,
velos_camion
);
}
else
{
pthread_mutex_unlock
(
&
sites
[
i
].
mutex
);
}
pthread_mutex_unlock
(
&
sites
[
i
].
mutex
);
//usleep((rand()%100+100));
}
...
...
@@ -154,7 +186,7 @@ void *gestion_camion(void *arg)
{
velos_depot
+=
(
velos_camion
-
2
);
velos_camion
=
2
;
printf
(
"Camion vide les vélos au dépôt (Vélos en dépôt: %d)
\n
"
,
velos_depot
);
printf
(
"Camion vide les vélos au dépôt (Vélos en dépôt: %d)
\n
"
,
velos_depot
);
}
else
if
(
velos_depot
>
0
&&
velos_camion
<
2
)
{
...
...
@@ -165,11 +197,11 @@ void *gestion_camion(void *arg)
}
velos_depot
-=
requis
;
velos_camion
+=
requis
;
printf
(
"Camion prend des vélos
d
u dépôt (Vélos en dépôt: %d)
\n
"
,
velos_depot
);
printf
(
"Camion prend des vélos
a
u dépôt (Vélos en dépôt: %d)
\n
"
,
velos_depot
);
}
pthread_mutex_unlock
(
&
mutex_velos_depot
);
printf
(
"Camion fait un tour,
v
élos restants: %d, vélos en dépôt: %d
\n
"
,
velos_camion
,
velos_depot
);
printf
(
"Camion fait un tour,
V
élos restants: %d, vélos en dépôt: %d
\n
"
,
velos_camion
,
velos_depot
);
//usleep((rand()%100+100));
}
return
NULL
;
...
...
@@ -179,23 +211,31 @@ int main(int argc, char *argv[])
{
if
(
argc
!=
5
)
{
fprintf
(
stderr
,
"Usage: %s <SITES> <HABITANTS> <TRAJETS> <BORNES>
\n
"
,
argv
[
0
]);
fprintf
(
stderr
,
"Usage: %s <SITES> <HABITANTS> <TRAJETS> <BORNES>
\n
"
,
argv
[
0
]);
return
1
;
}
SITES
=
atoi
(
argv
[
1
]);
HABITANTS
=
atoi
(
argv
[
2
]);
TRAJETS
=
atoi
(
argv
[
3
]);
BORNES
=
atoi
(
argv
[
4
]);
if
(
SITES
<=
2
||
HABITANTS
<=
2
||
TRAJETS
<=
0
||
BORNES
<=
4
)
{
printf
(
"Les contraintes suivantes doivent être respectées:
\n
"
);
printf
(
"SITES > 2, HABITANTS > 2, TRAJETS > 0, BORNES > 4
\n
"
);
exit
(
EXIT_FAILURE
);
}
srand
(
time
(
NULL
));
sites
=
malloc
(
SITES
*
sizeof
(
Site
));
pthread_t
habitants
[
HABITANTS
],
camion
;
pthread_t
habitants
[
HABITANTS
],
camion
;
for
(
int
i
=
0
;
i
<
SITES
;
i
++
)
{
sem_init
(
&
sites
[
i
].
velos
,
0
,
BORNES
-
2
);
sem_init
(
&
sites
[
i
].
bornes
,
0
,
2
);
sem_init
(
&
sites
[
i
].
velos
,
0
,
BORNES
-
2
);
sem_init
(
&
sites
[
i
].
bornes
,
0
,
2
);
pthread_mutex_init
(
&
sites
[
i
].
mutex
,
NULL
);
sites
[
i
].
velos_dispo
=
BORNES
-
2
;
sites
[
i
].
personnes_attente
=
0
;
...
...
@@ -204,24 +244,24 @@ int main(int argc, char *argv[])
{
int
*
habitant_id
=
malloc
(
sizeof
(
int
));
*
habitant_id
=
i
;
pthread_create
(
&
habitants
[
i
],
NULL
,
habitant
,
habitant_id
);
pthread_create
(
&
habitants
[
i
],
NULL
,
habitant
,
habitant_id
);
}
pthread_create
(
&
camion
,
NULL
,
gestion_camion
,
NULL
);
pthread_create
(
&
camion
,
NULL
,
gestion_camion
,
NULL
);
for
(
int
i
=
0
;
i
<
HABITANTS
;
i
++
)
{
pthread_join
(
habitants
[
i
],
NULL
);
pthread_join
(
habitants
[
i
],
NULL
);
}
pthread_join
(
camion
,
NULL
);
pthread_join
(
camion
,
NULL
);
int
total_velos
=
velos_depot
;
for
(
int
i
=
0
;
i
<
SITES
;
i
++
)
{
total_velos
+=
sites
[
i
].
velos_dispo
;
printf
(
"Site %d cont
ains %d byke
s
\n
"
,
i
,
sites
[
i
].
velos_dispo
);
total_velos
+=
sites
[
i
].
velos_dispo
;
printf
(
"Site %d cont
ient %d vélo
s
\n
"
,
i
,
sites
[
i
].
velos_dispo
);
}
total_velos
+=
2
;
printf
(
"Nombre total de vélos à la fin : %d (doit être %d)
\n
"
,
total_velos
,
SITES
*
(
BORNES
-
2
)
+
2
);
total_velos
+=
2
;
printf
(
"Nombre total de vélos à la fin : %d (doit être %d)
\n
"
,
total_velos
,
SITES
*
(
BORNES
-
2
)
+
2
);
printf
(
"Simulation terminée.
\n
"
);
for
(
int
i
=
0
;
i
<
SITES
;
i
++
)
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment