Département INFormatique 
 CSC4508/M2 : Conception et programmation des systèmes centralisés


   Évaluation



TÉLÉCOM SudParis 2ème année

TP Noté CSC4508/M2 du 19/05/16

(Corrigés)

Modalités

Durée : 3 heures

Tous documents autorisés.

Les questions 1, 2 et 3 sont indépendantes les unes des autres. Aussi, n'hésitez pas à lire tout le sujet avant de commencer pour déterminer l'ordre dans lequel vous souhaitez traiter les questions.

Le barème est donné à titre indicatif des poids entre les différentes questions.

La « livraison » de votre travail en fin de TP noté se fera par remontée sous Moodle (rubrique « TP noté de 3 heures ») du fichier d'extension tgz constitué de la manière suivante :
cd votreRepertoireDeTravailPourCSC4508M2
tar cvfz ${USER}.tgz ${USER}_TPNote2016

Préparation

		cd votreRepertoireDeTravailPourCSC4508M2
		wget http://www-inf.it-sudparis.eu/COURS/CSC4508/Current/Documents/ExoCoursSys/TPNote2016/WWW/tPNote2016.tgz
		tar xvfz tPNote2016.tgz
		mv TPNote2016 ${USER}_TPNote2016
		cd ${USER}_TPNote2016
	      

Question 1 : Débugger un code (6.5 points)

Le fichier question1.c, qui implémente quelques fonctions comporte plusieurs bugs. Le but de cet exercice est de les identifier et de proposer des correctifs.

Question 1.1

Dans le fichier Q1/reponses1.txt, indiquez, en justifiant votre réponse, le nombre d'octets que la procédure writeBytes écrit dans le fichier associé au descripteur fd.

---beginCorr (0.5 points)
SIZE=1<<16, donc SIZE=2^16 = 65536
---endCorr

Question 1.2

La fonction newFilledStruct compile avec un warning.
  • Expliquez (dans le fichier Q1/reponses1.txt) ce warning (surtout pourquoi cela pose un problème à l'appelant de newFilledStruct)
  • Corrigez le problème en modifiant le fichier Q1/Q1.2/question1.c.

---beginCorr (1.5 points)
newFilledStruct renvoie un pointeur sur une structure locale à newFilledStruct, donc une variable stockée sur la pile d'exécution. De ce fait, quand l'appelant se servira de la valeur pointée, la structure risque de contenir quelque chose qui n'a rien à voir avec ce qui a été initialisé dans newFilledStruct.
programme corrigé
---endCorr

Question 1.3

La procédure writeBytes contient deux bugs. Le premier bug explique que, quand un même programme appelle fréquemment writeBytes, à un moment le programme s'arrête sur l'assert(buf != NULL).

Dans le fichier Q1/reponses1.txt,

  • Expliquez le bug et la raison de cet arrêt sur assert.
  • Proposez une correction
  • Expliquez l'autre bug.
  • Proposez-en une correction

---beginCorr (3 points)

  • Une fois que writeBytes a fini de s'exécuter, les 64 Kio qui ont été alloués sont perdus (fuite mémoire). Si writeBytes est appelé fréquemment, l'ordinateur risque de ne plus avoir de mémoire vive pour exécuter le programme qui échoue alors lorsqu'il demande pour la n-ième fois 64 Kio.
  • A la fin de writeByte, ajouter free(buf), sans oublier de faire buf=NULL; juste derrière.
  • writeBytes écrit une zone mémoire non initialisée. writeBytes écrit donc n'importe quoi dans le fichier.
  • Remplacer "buf = malloc(SIZE)" par "buf = calloc(1,SIZE)" pour être sûr que la zone mémoire pointée par buf est initialisée à 0.
---endCorr

Question 1.4 (difficile)

La procédure createThread contient un bug. Dans le fichier Q1/reponses1.txt,
  • Expliquez ce bug.
  • Décrivez le principe d'une correction qui ne fait pas de malloc (NB : on ne vous demande pas de coder cette solution)

---beginCorr (1.5 points)

  • Le problème est très similaire au problème de la question 1.2: createThread crée un thread en lui un passant un pointeur sur sa structure myStruct locale à createThread, donc une variable stockée sur la pile d'exécution. De ce fait,quand aFunc démarrera son exécution, il se peut très bien que createThread ait fini de s'exécuter et donc que le pointeur sur myStruct pointe sur des valeurs qui n'ont rien à voir avec les valeurs initialisées par createThread.
  • Pour corriger ce problème, dans createThread, on crée une structure (définie sur la pile) contenant les valeurs de myStruct et un sémaphore initialisé à 0. createThread crée le thread aFunc en lui passant un pointeur sur cette nouvelle structure. Quand createThread a détaché le thread, createThread fait un sem_wait sur le sémaphore. En parallèle, aFunc s'exécute : il récupère en local toutes les valeurs contenues dans myStruct, puis fait sem_post sur le sémaphore. createThread() sort donc de sem_wait(). Il peut alors invoquer sem_destroy sur ce sémaphore.
---endCorr

Question 2 : Jobs. (8 points)

Le programme jobs.c crée NJOBS jobs qui doivent être traités par la fonction process_job(). Le résultat de chaque job est écrit dans le fichier results.dat de façon à ce que le fichier contienne, à la fin de l'exécution du programme:

AAAABBBBCCCCDDDDEEEE...XXXX

où AAAA est le résultat (écrit en binaire) du job 0, BBBB le résultat du job 1, etc.

La liste des jobs à traiter est dans la liste chaînée jobs qui pointe vers le premier élément de la liste (ou NULL si la liste ne contient aucun élément). Chaque élément pointe vers l'élément suivant à traiter (sauf le dernier, qui pointe sur NULL).

A la fin du programme, la fonction check_result vérifie que le contenu du fichier est correct.

Question 2.1

Dans le répertoire Q2/Q2.1, complétez le programme de manière à ce que les résultats des jobs soient écrits dans le fichier "results.dat". Il vous est demandé ici de compléter les fonctions suivantes:

  • init_workers(): ajouter le code permettant d'ouvrir le fichier
  • finalize_workers(): ajouter le code permettant de fermer le fichier
  • save_result(): ajouter le code permettant d'écrire le résultat d'un job (j->res) dans le fichier

La fonction check_result, appelée à la fin du programme vérifie que chaque job a écrit le résultat au bon endroit du fichier.

---beginCorr (3 points)
corrigé

  • 0.75 pts pour init_workers
  • 0.75 pts pour finalize_workers
  • 1.5 pts pour save_results
Des malus sont appliqués en fonction du code produit:
  • -0.5 en cas de code retour non testé
  • -0.5 en cas de problème d'indentation
  • -0.5 en cas de warning à la compilation
---endCorr

Question 2.2

On souhaite maintenant paralléliser le traitement des jobs afin d'exploiter les processeurs multi-coeurs des machines.

Recopiez les fichiers que vous avez modifiés lors de la question 2.1 dans le répertoire Q2/Q2.2. Complétez ensuite ce code afin que:

  • La fonction init_workers crée MAX_PARALLEL_JOBS threads
  • Les threads attendent que des jobs soient soumis pour les traiter
  • La fonction finalize_workers signifie aux threads qu'il n'y a plus de job à soumettre (par exemple, en soumettant un job avec un 'identifiant particulier, ou en utilisant une primitive de synchronisation) , et qu'elle attende que tous les threads aient fini de traiter les jobs soumis.
  • Tous les accès concurrents à des structures de données ou ressources partagées soient protégés correctement.

---beginCorr (5 points)
corrigé

  • 1.5 pt pour la création des threads
  • 2 pt pour la récupération des jobs par les threads
  • 0.5 pts pour la détection de la terminaison par les threads
  • 1 pt pour la protection des accès concurrents
Des malus sont appliqués en fonction du code produit:
  • -0.5 en cas de code retour non testé
  • -0.5 en cas de problème d'indentation
  • -0.5 en cas de warning à la compilation
---endCorr

Question 3 : Parcours d'une arborescence (5.5 points)

Le programme browse_dir compte le nombre de fichiers dans un répertoire (NB: le programme ignore les liens symboliques vers des fichiers). Pour lancer ce programme, il suffit de lui donner un répertoire en paramètre:

$ ./browse_dir /home/trahay
Il y a 32 fichiers dans le répertoire /home/trahay

Actuellement, le programme n'inclut pas les fichiers stockés dans les sous-répertoires du répertoire passé en argument. Le but de l'exercice est de modifier le programme pour que ce soit le cas.

Question 3.1

Dans le fichier Q3/Q3.1/browse_dir.c, modifiez la fonction count_files afin qu'elle compte tous les fichiers d'un répertoire et de ses sous-répertoires, de manière récursive.

---beginCorr (3 points)
browse_dir_corrige_Q3.1.c

  • 1.5 pts pour construction correcte de la chaîne concaténée
  • 1.5 pts pour l'appel récursif
Des malus sont appliqués en fonction du code produit:
  • -0.5 en cas de code retour non testé
  • -0.5 en cas de problème d'indentation
  • -0.5 en cas de warning à la compilation
---endCorr

Question 3.2

Copiez browse_dir.c dans le répertoire Q3/Q3.2, puis modifiez le afin qu'il ne compte que les fichiers accessibles en écriture par l'utilisateur.

---beginCorr (2.5 points)
browse_dir_corrige_Q3.2.c

  • 2.5 pts pour appel à stat
Des malus sont appliqués en fonction du code produit:
  • -0.5 en cas de code retour non testé
  • -0.5 en cas de problème d'indentation
  • -0.5 en cas de warning à la compilation
---endCorr





Page mise à jour le 18 mai 2016