Exercice 1 : Programmation modulaire

Transcription

Exercice 1 : Programmation modulaire
Magistère STIC
Module Programmation 2
Examen du 7 avril 2005
2004–2005
Le devoir est à rendre par e-mail à [email protected] au plus tard le lundi 11 avril à
12h00, sous la forme d’un archive tar contenant
– en trois répertoires différents le code pour résoudre les trois parties du devoir, avec un Makefile correct pour les compiler et exécuter vos tests ;
– un bref document expliquant vos choix et les éventuels problèmes rencontrés, et détaillant
la structure de la modélisation objet pour l’exercice 2.
Exercice 1 : Programmation modulaire
Une pile de protocoles est usuellement représentée dans les livres de texte comme suit :
···
TCP
IP
Ethernet
où chaque protocole peut appeler le protocole immédiatement inférieur pour demander l’exécution de fonctions de niveau inférieur.
Le but de ces deux exercices est de vous faire réaliser une pile de protocoles composables très simplifiée
selon l’approche modulaire et selon l’approche orienté objet.
Protocoles comme foncteurs
Nous nous fixons la signature suivante, où un message est représenté comme une suite d’entiers (une
simplification d’un paquet réseau).
module
sig
type
type
val
val
val
val
end
type PROTOCOL =
connection
message = int list
int_of_connection : connection -> int
connect : (message -> unit) -> connection
send : connection -> message -> unit
c_close: connection -> unit
Quelques explications. Les valeur du type connection retournés par connect sont des identifiants
de connexion, utilisés pour envoyer des messages sur une connexion (opération send), et pour fermer une
connexion (opération close).
Il n’y a pas de fonction receive : la fonction connect prend en effet en paramètre une fonction de
type message->unit qui sera appelée par la pile de protocole chaque fois qu’un message arrive sur la
connexion ouverte ; on appelle ce genre de fonctions des callback.
1
Dans notre modèle très simplifié, on n’introduira pas d’adresses ou ports : nous évitons de modéliser
le mécanisme complexe nécessaire pour établir des communications point à point entre deux parties,
en décidant qu’une connexion revient à un canal de communication partagé entre toutes les parties qui
exécutent l’opération connect. Chaque opération send effectuera en pratique un broadcast de son message qui sera traité par tous les callbacks actifs, sauf celui de la connexion qui a envoyé le message.
Enfin, int of connection rend un entier unique qui distingue une connexion de toutes les autres.
Exercice 1.1
Réalisez un foncteur Ether (X : sig end) : PROTOCOL qui réalise la couche basse de la pile
de protocole. Chaque module produit en appliquant Ether à (struct end)devra effectuer les tâches
suivantes :
– garder la liste des connexion actives,
– passer chaque message reçu à toutes les fonctions qui ont été enregistrées par les opérations connect
précédentes, sauf celle qui a envoyé le message.
Par exemple, la séquence
module Ethernet = Ether (struct end);;
let handler l = List.iter (Printf.printf "%d - ") l; print_newline();;
let c1 = Ethernet.connect handler;;
Ethernet.send c1 [32];;
ne produira rien, le message est perdu.
let handler l = List.iter
let c1 = Ethernet.connect
let c2 = Ethernet.connect
let c3 = Ethernet.connect
Ethernet.send c1 [32];;
(Printf.printf "%d - ") l; print_newline();;
handler;;
handler;;
handler;;
produira deux impressions, une effectuée par le callback de la connexion c2 et une effectuée par le callback
de la connexion c3
32 32 -
Exercice 1.2
Réalisez un foncteur Noduplicates (Lower :PROTOCOL) : PROTOCOL qui garantie qu’un même
paquet ne sera jamais traité deux fois, en jetant tous les duplicata. Pour faire cela, la fonction send de cette
couche ajoutera dans le paquet une étiquette unique pour chaque paquet.
Exercice 1.3
Réalisez un foncteur Checksum (Lower :PROTOCOL) : PROTOCOL qui garantie l’intégrité des
données d’un paquet, en ajoutant un checksum en tête du paquet au moment de l’envoi, et le vérifie à la
réception.
2
Exercice 1.4
Modifiez votre module Ether de façon que une fois sur deux il duplique le paquet et une fois sur trois
modifie un des entiers le composant, puis testez votre pile de protocoles, en utilisant au moins le code
suivant
module T1 = Ether(struct end)
let c1 = T1.connect handler
let c2 = T1.connect handler
for i = 0 to 15 do T1.send c1 [i] done
module T2 = Checksum(Ether(struct end))
let c1 = T2.connect handler
let c2 = T2.connect handler
for i = 0 to 15 do T2.send c1 [i] done
module T3 = Noduplicates(Checksum(Ether(struct end)))
let c1 = T3.connect handler
let c2 = T3.connect handler
for i = 0 to 15 do T3.send c1 [i] done
Exercice 2 : Protocoles orientés objets
Proposez une modélisation de la même pile modulaire de protocoles en utilisant des classes et des objets,
et en réalisant les mêmes tests.
Exercice 3 : Programmation parallèle
Écrivez un programme OCaml sieve.ml, en utilisant la librairie Unix, qui lit un entier n en entrée, et
puis produit les premiers n nombres premiers par la méthode du crible d’Eratosthene, implémentée en
parallèle, selon le schéma suivant :
1. avec n opérations fork successives, on construit n processus, tels que le processus i est relié a i+1
par un canal en écriture, et à i-1 par un canal en lecture
2. le processus 0 (le père) imprime 1 et envoyé au processus 1 les entiers à partir de 2
3. le processus i (> 0) lit le premier entier provenant de i-1, l’imprime et le mémorise dans une
variable premier, puis lit tous les autres entiers, jette les multiples de premier et envoie les
autres au processus i+1
Modifiez ensuite votre programme de la sorte que, une fois le n-ème nombre premier imprimé, les n
processus terminent sans erreur.
3

Documents pareils