ajout pipe

This commit is contained in:
Denis Monnerat 2024-10-02 07:37:12 +02:00
parent 7249bdff39
commit 985768540d
4 changed files with 204 additions and 0 deletions

View File

@ -30,3 +30,7 @@ Rappels sur la gestion de la [mémoire](cours/memoire.pdf), [td1](td/td1/td1.pdf
#### Semaine 4 (23/09 - 27/09)
[Signaux](cours/signaux.pdf), [td4](td/td4/td4.pdf), [tp4](tp/tp4).
#### Semaine 5
[Tubes, redirections](cours/pipe.pdf), [td5](td/td5/td5.pdf), [tp5](tp/tp5).

BIN
cours/pipe.pdf Normal file

Binary file not shown.

BIN
td/td5/td5.pdf Normal file

Binary file not shown.

200
tp/tp5/README.md Normal file
View File

@ -0,0 +1,200 @@
# Redirections, tubes
> Une vidéo de [Brian Kernighan](https://youtu.be/tc4ROCJYbm0?si=q9b7hnCwTXNmEcay&t=297) expliquant les tubes unix.
#### Ex1
1. Écrire un programme C pour calculer la taille du tampon système
associé à un tube. (on pourra rendre l'écriture non bloquante avec
`fcntl`)
2. Écrire un programme C qui a le même comportement que la commande
shell
```bash
ls -i -l /tmp >> log
```
3. Écrire un programme C qui a le même comportement que la commande
shell
```bash
ls . | wc -l
```
#### Ex2
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 ?
#### Ex3
Voici un programme qui calcule le nième terme de la suite de Fibonacci de
manière récursive (ce n'est pas la meilleure approche comme vous le savez).
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
long int fibo (long int n)
{
return (n<=1)?n:fibo(n-1)+fibo(n-2);
}
int main(int argc, char *argv[])
{
long int n;
assert(argc > 1);
n=strtol(argv[1],NULL,0);
printf("fibo(%ld) = %ld\n",n,fibo(n));
return 0;
}
```
L'arbre d'appel correspondant pour n=4 :
```bash
fibo(4)
/ \
/ \
fibo(2) fibo(3)
/ \ / \
/ \ / \
fibo(0) fibo(1) fibo(1) fibo(2)
/ \
/ \
fibo(0) fibo(1)
```
Modifiez le programme pour qu'il crée 2 fils. Le premier calculera fibo(n-2), le deuxième fibo(n-1).
Le père récupérera les résultats et les additionnera. La communication sera assurée par des tubes.
#### Ex4
Le but est de mettre en oeuvre le cribble d'Ératosthène à l'aide d'une chaîne de processus reliés entre eux par des pipes.
- un premier processus `P` crée un fils avec qui il est relié par un tube, et qui génére l'ensemble des nombres entre 2 et `N` (passé à la ligne de commande.
- Lorsqu'un nombre n'a pas été cribblé par les différents filtres, et arrive jusqu'à `P`, il est premier, et `P` crée un nouveau filtre.
```bash
┌────────┐
│ P │
└────────┘
┌────────┐ ────── ┌────────┐
│seq 2 N ├───►() ()───►│ P │
└────────┘ ────── └────────┘
┌────────┐ ────── ┌────────┐ ────── ┌────────┐
│seq 2 N ├───►() ()───►│ F2 ├───►() ()───►│ P │
└────────┘ ────── └────────┘ ────── └────────┘
┌────────┐ ────── ┌────────┐ ────── ┌────────┐ ────── ┌────────┐
│seq 2 N ├───►() ()───►│ F2 ├───►() ()───►│ F3 ├───►() ()───►│ P │
└────────┘ ────── └────────┘ ────── └────────┘ ────── └────────┘
┌────────┐ ────── ┌────────┐ ────── ┌────────┐ ────── ┌────────┐ ────── ┌────────┐
│seq 2 N ├───►() ()───►│ F2 ├───►() ()───►│ F3 ├───►() ()───►│ F5 ├───►() ()───►│ P │
└────────┘ ────── └────────┘ ────── └────────┘ ────── └────────┘ ────── └────────┘
```
Écrire un programme correspondant à ce schéma
#### Ex5
Le but est d'implanter une architecture client/serveur en utilisant des tubes nommés. (Il existe pour cela
un autre mécanisme dédié à la communication locale interprocessus avec les sockets)
```
+-------------+
+----------> | clt1 pipe | --------------------------+
| +-------------+ |
| |
| +-- client1 <--+
| |
| |
| +-------------+ <-+
+-- serveur <-------- | serveur pipe| <---- client2 <-------+
| +-------------+ <-+ |
| | |
| | |
| +-- client3 <---+ |
| +-------------+ | |
+----------> | clt3 pipe | ---------------------------+ |
| +-------------+ |
| |
| +-------------+ |
+----------> | clt2 pipe | -------------------------------+
+-------------+
```
**Le serveur**
Il permet de consulter les notes d'étudiants à un examen d'ASR.
Il récupére en boucle les requêtes des clients dans un tube nommé `srv.pipe`. Pour écouter en boucle
les demandes des clients (lecture bloquante), le serveur ouvre le tube en mode lecture/écriture (il y a toujours
un écrivain, même lorsqu'on n'a plus aucun client).
Chaque requête est composée :
- du pid du client
- du numéro de l'étudiant dont on veut la note.
Pour chaque requête, le serveur crée un fils qui renvoie la note de l'étudiant correspondant à la requête, en utlisant
le tube nommé `/tmp/clt.pid`. On prendra soin de traiter correctement le signal `SIGCHLD`.
**Le client**
- Il crée le tube nommé pour la réponse à sa requête.
- Il envoie sa requête dans le tube `srv.pipe`.
- Il récupère la réponse du serveur dans son tube nommé, et le détruit.