Département INFormatique 
  CSC4508/M2 : Concepts des systèmes d'exploitation et mise en œuvre sous Unix
    Évaluation

Institut National des Télécommunications
Télécom INT 2è année

TP Noté CS21 du 22/06/04
(2è session)

Corrigés

Modalités

Durée : 1 heure 30

Tous documents autorisés

Les questions sont indépendantes les unes des autres.

Le barême est donné à titre indicatif des poids entre les différentes questions. Seront notés :
  • La clarté du code,
  • Le fait que le code compile (sans warning),
  • Le fait que le code répond correctement à la question posée,
  • Le fait que le retour de chaque appel système, s'il y en a un, est testé et géré (traitement d'erreur),
  • Le fait que les ressources système réservées pendant l'exécution du programme sont libérées à la fin de l'exécution.
La «livraison» de votre travail en fin de TP noté se fera par remise de votre copie à l'enseignant et par envoi d'un mail à frederique.silber-chaussumier@int-evry.fr (sujet «CS21:TPNoteSession2») avec en pièce jointe le fichier d'extension tgz constitué de la manière suivante :
cd votreRepertoireDeTravailPourCS21
tar cvfz $USER.tgz TPNote2004Session2

Préparation

cd votreRepertoireDeTravailPourCS21
cp ~silber/CS21/tPNote2004Session2.tgz .
tar xvfz tPNote2004Session2.tgz
cd TPNote2004Session2

Question 1 : O_SYNC (4 points)

man 2 open décrit le rôle de l'option O_SYNC dans l'appel système open.
Q1.1 : Pourquoi n'utilise-t-on pas cette option en général ?
Q1.2 : Donner un exemple d'application où cette option est requise.
NB : Vous pouvez répondre sur votre copie ou bien dans le fichier Q1/reponse.txt (dans ce dernier cas, indiquez sur votre copie "Réponse dans Q1/reponse.txt").

Question 2 : Concurrence d'accès (8 points)

Le module suivant est utilisé pour gérer une liste chaînée de données.

#include <stdlib.h>

/* Structure utilisee pour stocker les differents elements de la liste */
typedef struct element_t{
   
/* Donnees stockees dans cet element de la liste chainee */
   char data[256];
   
/* Pointeur vers l'element suivant de la liste chainee (NULL si pas */
   /* d'element suivant)                                               */

   struct element_t *next;
} element_t;

/* Pointeur sur le premier element de la liste chainee */
static element_t *first=NULL;

/* Ajoute l'element unElement en tete de liste chainee */
void addFirst(element_t *unElement){
   /* Comme unElement va etre insere en tete de liste,          */
   /* son successeur sera le premier element actuel de la liste */
   unElement->next = first;
   /* La nouvelle tete de liste est unElement */
   first = unElement;
}


Dans un programme mono-thread, ce module donne entière satisfaction.
En revanche, dans le cas d'un programme contenant deux threads (qui appellent à certains moments la fonction addFirst), chacun ayant une politique d'ordonnancement FIFO, l'un ayant une priorité statique égale à 1, l'autre ayant une priorité statique égale à 2, on constate qu'addFirst perd des éléments.
Q2.1 : Pourquoi ?
Q2.2 : Aurait-on ce bug si les deux threads avaient la même priorité statique (comprise entre 1 et 99) ? Justifier votre réponse.
Q2.3 : Proposer, dans ses grandes lignes, une solution pour le bug d'addFirst quand les deux threads ont une priorité statique différente.
NB : Vous pouvez répondre sur votre copie ou bien dans le fichier Q2/reponse.txt  (dans ce dernier cas, indiquez sur votre copie "Réponse dans Q2/reponse.txt").

Question 3 : Tube versus mémoire partagée (8 points)

On souhaite comparer les performances des communications à travers un tube et celles à travers une zone de mémoire partagée synchronisée selon un paradigme producteur/consommateur.
Pour ce faire, on se propose de coder le programme Q3/tube.c (respectivement Q3/memoirePartagee.c) selon l'algorithme suivant
  • Création d'un tube (respectivement d'un tampon et des entités liées au paradigme producteur/consommateur)
  • Création d'un enfant
  • Déclaration d'une variable s de type structure_t
  • Initialisation de tous les octets de s à '\0'
  • répéter NBECHANGES fois
    • Envoyer s à l'enfant via le tube (respectivement la zone de mémoire partagée)
  • Fin Répéter
  • Attendre décès de l'enfant
Dans ce programme, le fils effectue l'algorithme suivant :
  • Définir une variable s de type structure_t
  • répéter NBECHANGES fois
    • Lire la valeur de s envoyée par le père via le tube (respectivement la zone de mémoire partagée)
  • Fin Répéter

Question 3.1 : Codage de Q3/tube.c

Le programme Q3/memoirePartagee.c est déjà fourni.
Compléter les lignes /*** A completer ***/ de Q3/tube.c pour qu'il fonctionne conformément à l'algorithme ci-dessus.
NB : même si vous n'arrivez pas à répondre à cette question, vous pouvez quand même travailler sur la question Q4.2.

Question 3.2 : Analyse

Dans le fichier Q3/commentaire.txt :
  • Q3.2.1. Indiquer le résultat de la commande /usr/bin/time appliqué à Q3/memoirePartagee et Q3/tube (ou Q3/tubeSiQ31KO si vous n'avez pas pu répondre à la question Q3.1)
  • Q3.2.2. Les résultats obtenus militent en faveur de l'utilisation systématique des tubes. En remarquant que le nombre d'octets contenus dans un tube n'est pas aisément paramétrables (recompilation du noyau requise), citer une situation où on préférera utililiser de la mémoire partagée plutôt que des tubes (même si les performances sont moins bonnes).
  • Q3.2.3. La différence de temps d'exécution peut surprendre. Expliquer pourquoi : on ne demande pas d'expliquer la différence de temps d'exécution en elle-même (il faudrait analyser le code du noyau Linux pour comprendre la gestion des tubes et de la mémoire partagée), mais on demande d'expliquer en quoi la différence de temps d'exécution est surprenante.
    NB : cette question est plus difficile que les autres. Il est donc recommandé de ne l'aborder que quand vous avez traité les autres questions.

  • Page mise à jour le 15 mai 2006