tp6
This commit is contained in:
@@ -33,6 +33,9 @@ Rappels sur la gestion de la [mémoire](cours/memoire.pdf), [td1](td/td1/td1.pdf
|
|||||||
#### Semaine 5 (28/09 - 02-10)
|
#### Semaine 5 (28/09 - 02-10)
|
||||||
[Signaux](cours/signaux.pdf), [td5](td/td5/td5.pdf), [tp5](tp/tp5).
|
[Signaux](cours/signaux.pdf), [td5](td/td5/td5.pdf), [tp5](tp/tp5).
|
||||||
|
|
||||||
|
### Semaine 6 (05/10 - 09/10)
|
||||||
|
[Tubes, redirections](cours/pipe.pdf), [td6](td/td6/td6.pdf), [tp6](tp/tp6).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
# Redirections, tubes, synchronisation
|
||||||
|
|
||||||
|
#### Ex1
|
||||||
|
Soit le graphe de processus suivant (un tube est établi entre Pf2 et
|
||||||
|
Pf1f1)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
| P
|
||||||
|
|____
|
||||||
|
| \ Pf1
|
||||||
|
| \
|
||||||
|
| \
|
||||||
|
|\Pf2 |\
|
||||||
|
| \ | \Pf1f1
|
||||||
|
| \ | \
|
||||||
|
O O O O
|
||||||
|
()-->--()
|
||||||
|
```
|
||||||
|
|
||||||
|
1. Ecrivez un programme pipe-ex.c qui implante le graphe ci-dessus
|
||||||
|
(y compris le tube) et tel que :
|
||||||
|
- Pf2 écrive en permanence toutes les 3 secondes son PID dans
|
||||||
|
le tube en affichant ce qu'il écrit
|
||||||
|
- Pf1f1 lise en permanence chaque seconde depuis tube
|
||||||
|
`sizeof(pid_t)` en affichant ce qu'il lit
|
||||||
|
|
||||||
|
Vérifiez que le programme fonctionne comme prévu, i.e il affiche
|
||||||
|
:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
16411 sent 16411
|
||||||
|
16412 received 16411
|
||||||
|
16411 sent 16411
|
||||||
|
16412 received 16411
|
||||||
|
.....
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Lancez le programme ci-dessus et faites les essais suivants
|
||||||
|
(relancez le programme après chaque essai). Expliquez à chaque
|
||||||
|
fois vos observations.
|
||||||
|
1. Envoyez le signal `SIGSTOP` à Pf2, puis le signal SIGCONT à
|
||||||
|
Pf2.
|
||||||
|
2. Envoyez le signal `SIGSTOP` à Pf1f1, puis le signal SIGCONT à
|
||||||
|
Pf1f1.
|
||||||
|
3. Envoyez le signal `SIGTERM` à Pf2.
|
||||||
|
4. Envoyez le signal `SIGTERM` à Pf1f1.
|
||||||
|
3. Modifiez le programme pipe-ex.c en assurant que tous les
|
||||||
|
processus ferment les descripteurs du tube non utilisés. Faites
|
||||||
|
les mêmes essais que ci-dessus et expliquez ce que vous
|
||||||
|
observez.
|
||||||
|
4. Modifiez encore une fois le programme pipe-ex.c pour que les
|
||||||
|
deux processus Pf1, Pf2 écrivent dans le tube simultanement et
|
||||||
|
que seul Pf1f1 le lise. Qu'observez-vous ?
|
||||||
|
|
||||||
|
#### Ex1
|
||||||
|
Reprendre l'[exercice 1](../tp5/parallelisme.md) du tp précédent. Vous devez utiliser comme
|
||||||
|
seul moyen de communication, entre les fils et le pere, des tubes (plus de `mmap`).
|
||||||
|
Les processus fils, à la création, ne savent pas quelle tranche ils doivent sommer.
|
||||||
|
|
||||||
|
1. De combien de tubes a-t-on besoin ?
|
||||||
|
2. On rappelle que l'écriture dans un tube est atomique jusqu'à `PIPE_BUF`.
|
||||||
|
3. Écrire le programme correspondant.
|
||||||
|
|
||||||
|
|
||||||
|
#### Ex2
|
||||||
|
Il s'agit d'un [exercice](./src/billes.c) classique de synchronisation. Des billes, dans une zone rectangulaire, se déplacent en rebodissant
|
||||||
|
sur les parois et les unes sur les autres. Chaque bille est un processus. L'état global est une zone partagée, protégée
|
||||||
|
en écriture par un sémaphore (cf cours).
|
||||||
|
|
||||||
|
L'affichage graphique est géré par le processus père (superviseur). Chaque bille, après mise à jour de sa position,
|
||||||
|
envoie un message au superviseur par un tube qui peut mettre à jour la fenêtre d'affichage. **Seule cette partie est à compléter**.
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<img src="billes.png">
|
||||||
|
</div>
|
||||||
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 816 B |
@@ -0,0 +1,175 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <semaphore.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <assert.h>
|
||||||
|
#include <X11/Xlib.h>
|
||||||
|
|
||||||
|
#define NB_BILLES 20
|
||||||
|
#define LARGEUR 640
|
||||||
|
#define HAUTEUR 480
|
||||||
|
#define RAYON 12
|
||||||
|
#define FPS_DELAY_US 16000
|
||||||
|
|
||||||
|
/* =========================================================
|
||||||
|
* ÉTAT D'UNE BILLE + MESSAGE D'AFFICHAGE + ZONE PARTAGÉE
|
||||||
|
* ========================================================= */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
float x, y, vx, vy; /* position + vitesse */
|
||||||
|
} etat_bille_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int id;
|
||||||
|
float x, y; /* position sur la grille */
|
||||||
|
} msg_bille_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
etat_bille_t billes[NB_BILLES];
|
||||||
|
sem_t sem_shm; /* protège billes[] */
|
||||||
|
} zone_partagee_t;
|
||||||
|
|
||||||
|
/* =========================================================
|
||||||
|
* PROCESSUS "BILLE" (fils)
|
||||||
|
* ========================================================= */
|
||||||
|
|
||||||
|
void processus_bille(int id, int fd_ecriture, zone_partagee_t *zone) {
|
||||||
|
while (1) {
|
||||||
|
sem_wait(&zone->sem_shm);
|
||||||
|
etat_bille_t *b = &zone->billes[id];
|
||||||
|
|
||||||
|
b->x += b->vx;
|
||||||
|
b->y += b->vy;
|
||||||
|
|
||||||
|
if (b->x - RAYON < 0) { b->x = RAYON; b->vx = -b->vx; }
|
||||||
|
if (b->x + RAYON > LARGEUR) { b->x = LARGEUR - RAYON; b->vx = -b->vx; }
|
||||||
|
if (b->y - RAYON < 0) { b->y = RAYON; b->vy = -b->vy; }
|
||||||
|
if (b->y + RAYON > HAUTEUR) { b->y = HAUTEUR - RAYON; b->vy = -b->vy; }
|
||||||
|
|
||||||
|
for (int j = id + 1; j < NB_BILLES; j++) {
|
||||||
|
etat_bille_t *autre = &zone->billes[j];
|
||||||
|
float dx = autre->x - b->x;
|
||||||
|
float dy = autre->y - b->y;
|
||||||
|
float dist = sqrtf(dx * dx + dy * dy);
|
||||||
|
|
||||||
|
if (dist > 0.0f && dist < 2.0f * RAYON) {
|
||||||
|
float nx = dx / dist, ny = dy / dist;
|
||||||
|
float overlap = 2.0f * RAYON - dist;
|
||||||
|
|
||||||
|
b->x -= nx * overlap / 2.0f;
|
||||||
|
b->y -= ny * overlap / 2.0f;
|
||||||
|
autre->x += nx * overlap / 2.0f;
|
||||||
|
autre->y += ny * overlap / 2.0f;
|
||||||
|
|
||||||
|
float v1n = b->vx * nx + b->vy * ny;
|
||||||
|
float v2n = autre->vx * nx + autre->vy * ny;
|
||||||
|
float diff = v2n - v1n;
|
||||||
|
|
||||||
|
b->vx += diff * nx;
|
||||||
|
b->vy += diff * ny;
|
||||||
|
autre->vx -= diff * nx;
|
||||||
|
autre->vy -= diff * ny;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_bille_t m = ; /* <- TODO */
|
||||||
|
sem_post(&zone->sem_shm);
|
||||||
|
|
||||||
|
write(); /* <- TODO */
|
||||||
|
|
||||||
|
usleep(FPS_DELAY_US);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* =========================================================
|
||||||
|
* PROCESSUS SUPERVISEUR (parent)
|
||||||
|
* ========================================================= */
|
||||||
|
|
||||||
|
void processus_superviseur(int fd_lecture) {
|
||||||
|
Display *dpy = XOpenDisplay(NULL);
|
||||||
|
|
||||||
|
assert(dpy != 0);
|
||||||
|
|
||||||
|
int screen = DefaultScreen(dpy);
|
||||||
|
Window win = XCreateSimpleWindow(dpy, RootWindow(dpy, screen),
|
||||||
|
0, 0, LARGEUR, HAUTEUR, 1,
|
||||||
|
BlackPixel(dpy, screen), WhitePixel(dpy, screen));
|
||||||
|
XSelectInput(dpy, win, ExposureMask | KeyPressMask);
|
||||||
|
XMapWindow(dpy, win);
|
||||||
|
GC gc = XCreateGC(dpy, win, 0, NULL);
|
||||||
|
|
||||||
|
float px[NB_BILLES] = {0}, py[NB_BILLES] = {0};
|
||||||
|
|
||||||
|
msg_bille_t m;
|
||||||
|
|
||||||
|
while (read(fd_lecture, &m, sizeof(m)) == (ssize_t)sizeof(m)) {
|
||||||
|
if (m.id >= 0 && m.id < NB_BILLES) {
|
||||||
|
px[m.id] = m.x;
|
||||||
|
py[m.id] = m.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
XClearWindow(dpy, win);
|
||||||
|
for (int i = 0; i < NB_BILLES; i++) {
|
||||||
|
XFillArc(dpy, win, gc,
|
||||||
|
(int)px[i] - RAYON, (int)py[i] - RAYON,
|
||||||
|
RAYON * 2, RAYON * 2, 0, 360 * 64);
|
||||||
|
}
|
||||||
|
XFlush(dpy);
|
||||||
|
}
|
||||||
|
|
||||||
|
XFreeGC(dpy, gc);
|
||||||
|
XCloseDisplay(dpy);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int fd[2]; /* --- tube : billes -> superviseur --- */
|
||||||
|
|
||||||
|
assert(pipe(fd) != -1);
|
||||||
|
|
||||||
|
/* --- zone partagée : billes + sémaphore, créée AVANT les fork() --- */
|
||||||
|
|
||||||
|
zone_partagee_t *zone = mmap(NULL, sizeof(zone_partagee_t),
|
||||||
|
PROT_READ | PROT_WRITE,
|
||||||
|
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
|
||||||
|
assert(zone != MAP_FAILED);
|
||||||
|
assert(sem_init(&zone->sem_shm, 1 , 1) != -1); /* --- semaphore --> section critique --- */
|
||||||
|
|
||||||
|
srand(time(NULL));
|
||||||
|
for (int i = 0; i < NB_BILLES; i++) {
|
||||||
|
zone->billes[i].x = RAYON + rand() % (LARGEUR - 2 * RAYON);
|
||||||
|
zone->billes[i].y = RAYON + rand() % (HAUTEUR - 2 * RAYON);
|
||||||
|
zone->billes[i].vx = (rand() % 5 + 2) * (rand() % 2 ? 1 : -1);
|
||||||
|
zone->billes[i].vy = (rand() % 5 + 2) * (rand() % 2 ? 1 : -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < NB_BILLES; i++) {
|
||||||
|
pid_t pid = fork();
|
||||||
|
|
||||||
|
assert(pid >= 0);
|
||||||
|
|
||||||
|
if (pid == 0) {
|
||||||
|
close(fd[0]); /* le fils ne lit pas le tube */
|
||||||
|
processus_bille(i, fd[1], zone);
|
||||||
|
close(fd[1]);
|
||||||
|
munmap(zone, sizeof(zone_partagee_t));
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd[1]); /* le parent n'écrit pas le tube */
|
||||||
|
processus_superviseur(fd[0]);
|
||||||
|
close(fd[0]);
|
||||||
|
|
||||||
|
for (int i = 0; i < NB_BILLES; i++) wait(NULL);
|
||||||
|
|
||||||
|
sem_destroy(&zone->sem_shm);
|
||||||
|
munmap(zone, sizeof(zone_partagee_t));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user