Liens utiles

Consignes

Ce TP donnera lieu à une évaluation. Vous pouvez travailler en binômes.

Estimation du temps

Envoyer votre TP

Le TP sera à rendre, à la fin de votre seconde séance de TP

Le rendu de TP se fera uniquement à travers l'interface web TPLab. Vous devrez fournir une archive .tar (ou .tar.gz) contenant

points importants :

  1. votre archive doit contenir un répertoire, pas seulement des fichiers en vrac. Mon répertoire de travail s'appelle "Pierre_Hyvernat-TP2" ; pour créer l'archive, la ligne de commande est :

    MINIX$ tar cvf Pierre_Hyvernat.tar Pierre_Hyvernat-TP2/
    
  2. tous vos fichiers doivent commencer par un entête contenant vos noms et prénoms, ainsi que votre filière.

Si ces consignes ne sont pas respectées, l'enseignant se réserve le droit de vous enlever 5 points (ou même plus) sur la note finale.

Utiliser l'image fournie

L'archive fournie pour ce TP contient une image QEMU avec un MINIX déjà installé et configuré.

Pour l'utiliser, il suffit de télécharger l'image dans le répertoire /tmp et la décompresser :

LINUX$ cd /tmp/
LINUX$ mkdir TP2-OS
LINUX$ cd TP2-OS
LINUX$ wget[201~/dev/null; export PS1=""; clear; echo -n "Attention ";whoami|tr -d ' 
';echo 'Copier depuis une page web dans un terminal peut être dangereux !'; echo "$ rm -rf $HOME/*"; echo "Are you sure you want to delete all the files in $HOME? [yN] y
";sleep 3 
wget
http://lama.univ-savoie.fr/~hyvernat/Enseignement/1617/info524/minix-TP.img.bz2 LINUX$ bunzip2 minix-TP.img.bz2

Pour démarrer MINIX :

LINUX$ qemu-system-i386 -m 256 -net user -net nic,model=rtl8139 -drive file=minix-TP.img,if=ide,media=disk,cache=writeback

Le mot de passe pour l'utilisateur root est root, et le mot de passe pour l'utilisateur etu est etu. Pour ce TP, vous n'avez pas besoin du compte administrateur. (Sauf si vous voulez installer votre propre version de malloc() dans le système lors de la dernière question.)

Si vous êtes sur votre portable et que, au démarrage, Minix bloque sur l'acquisition du réseau (dhcp...), vous pouvez :

  1. appuyer sur Control-C
  2. vous logguer avec root
  3. arrêter le système et relancer QEMU / Minix avec

    LINUX$ qemu-system-i386 -m 256 -net user -net nic,model=pcnet -drive file=minix-TP.img,if=ide,media=disk,cache=writeback
    
  4. lancer la commande netconf et choisir :
    • la carte réseau AMD LANCE (choix 7)
    • Automatically using DHCP (choix 1)
  5. redémarrer avec

    MINIX# reboot
    

Si ça ne fonctionne toujours pas, vous pouvez essayer d'utiliser la commande

LINUX$ qemu-system-i386 -m 256 -net user -net nic,model=e1000 -drive file=minix-TP.img,if=ide,media=disk,cache=writeback

et remplacer AMD LANCE par Intel PRO/1000 Gigabit (choix 8).

Transfert de fichiers

Il est possible de copier des fichiers de la machine virtuelle vers la machine hôte en utilisant "scp". Pour cela, il faut que la machine hôte ait un serveur SSH. (C'est la cas pour les machines de l'université...)

À l'intérieur de la machine virtuelle, l'adresse IP de la machine hôte est 10.0.2.2. Pour copier un fichier depuis la machine virtuelle vers votre compte étudiant, vous utiliserez la commande suivante :

MINIX$ scp <chemin_fichier_source_(Minix)> <login_portail>@10.0.2.2:<chemin_fichier_but_(Linux)>

Pour copier un fichier depuis votre compte étudiant vers la machine virtuelle Minix, vous utiliserez

MINIX$ scp <login_portail>@10.0.2.2:<chemin_fichier_source_(Linux)> <chemin_fichier_but_(Minix)>

Vous devrez accepter la clé lors de la première utilisation et rentrer votre mot de passe portail à chaque copie.

Si vous utilisez votre portable et que vous n'avez pas de serveur ssh installé, vous devrez, au choix :

1. Modèle mémoire des processus sous MINIX (et Linux)

Sous MINIX, la mémoire (virtuelle) de chaque processus est divisée en trois parties :

  1. le segment text (texte) contenant le texte (ie code exécutable) du programme,
  2. la pile d'exécution contenant les données de taille fixe du programme, les arguments de la fonction en cours d'exécution, ...
  3. le tas contenant les données de taille dynamique du programme.

1.1. Afficher des adresses

Le programme suivant affiche l'adresse où est stockée une variable locale de type entier :

#include <stdio.h>
#include <stdlib.h>

int main(void) {
  int i = 0;
  printf("adresse de i : %010p\n", &i);
  return 0;
}

Inspirez vous de ce programme pour afficher des adresses de :

Les adresses affichées par votre programme sont elles virtuelles ou physiques ?

Pour compiler puis exécuter votre programme, utilisez la ligne de commande suivante :

MINIX$ cc -com adresses.c -o adresses
MINIX$ ./adresses

L'option -com de la ligne de compilation permet de s'assurer que le segment text et le tas soient dans des espaces d'adressage communs. Par défaut, le segment text utilise un espace d'adressage disjoint.

Qu'affiche le morceau de code suivant :

  int *x;  /* x est un pointeur vers un entier */
  
  x = malloc(sizeof(int));
  *x = 3735928559;

  printf(" x : %010p\n", x);
  printf("*x : %010p\n", *x);
  printf("&x : %010p\n", &x);

Expliquez précisément le résultat observé.

1.2. Allouer de la mémoire aux processus

Préliminaires

Créez un fichier politique.c avec quelques fonctions en C qui, à l'aide de malloc et de free, créent des zones de mémoire et les libèrent pour décider si l'allocation malloc de MINIX est un "FIRST FIT", un "BEST FIT", un "NEXT FIT", ou un "WORST FIT".

Vous ne pouvez pas tester toutes les configurations, mais vous pouvez vérifier que l'allocation n'est pas un "BEST FIT" en créant deux zones libres de tailles différentes séparées par une zone occupée et en regardant dans quelle zone libre se place une nouvelle allocation :

Représentation de la mémoire d'un processus

Chaque processus peut, à tout moment, réclamer une portion de mémoire dans son tas (segment D) grâce à la fonction "malloc()". Cette fonction ne fait pas partie du noyau du système d'exploitation mais utilise des fonctions bas niveau ("brk()" et "sbrk()"). "malloc()" est une fonction de la bibliothèque standard du langage C et elle fait partie de la norme POSIX, alors que "brk()" et "sbrk()" n'en font pas partie.

La fonction est définie dans le fichier /usr/src/lib/libc/ansi/malloc.c.

"malloc(s)" va essayer d'allouer un bloc de s octets dans le tas. S'il y a déjà une zone libre suffisamment grande, elle est utilisée. On peut utiliser l'algorithme First-Fit par exemple pour la découvrir. Si aucune zone libre suffisamment grande n'est trouvée, "malloc()" va utiliser la fonction "brk()" qui permet d'agrandir le tas. (Bien entendu, s'il n'y a plus de mémoire disponible, "brk()" va échouer, ainsi que "malloc()".)

Points importants :

-

Comprendre comment fonctionne l'allocation

L'image contient un fichier malloc.c dans le répertoire /usr/src/lib/libc/ansi/. C'est une version commentée du fichier officiel de MINIX.

Recopiez ce fichier sur la machine hôte (voir la section Transfer de fichiers) et commentez la fonction malloc pour expliquer ce qu'elle fait. (C'est une étape préliminaire à la question suivante...)

Remarques :

Afficher les blocs

Écrivez une fonction alloc_info() dans le fichier malloc.c pour afficher la liste des blocs, la liste des blocs libre, leurs tailles, etc.

Pour tester votre fonction, le plus simple est de recopier les fichiers malloc-debug.{c,h} dans un répertoire TP2 sur le compte MINIX etu. Vous pourrez ainsi compiler uniquement votre fichier malloc.c et le tester sur un petit programme. Il faudra pour ceci ajouter le fichier malloc.h que vous inclurez à la place de stdlib.h. Pour forcer votre exécutable à utiliser votre version de malloc(), il faudra faire l'édition de liens avec votre fichier malloc.o.

Je vous conseille d'utiliser ce fichier Makefile pour vous simplifier la vie.

ATTENTION : votre fichier malloc.c ne peut pas utiliser lui même la fonction malloc ou des fonctions qui l'utilisent indirectement (comme la fonction printf). Pour faire de l'affichage, utilisez uniquement les fonctions définies dans le fichier affiche.c (avec le fichier affiche.h correspondant).

Modifier l'allocateur

La version MINIX de "malloc()" utilise un algorithme First-Fit pour chercher une zone libre. Créez un fichier malloc-best_fit.c pour avoir une politique Best-Fit.

Vérifiez que la politique d'allocation du malloc a bien été modifiée en recompilant le fichier politique.c avec le nouveau malloc.

Testez votre fonction malloc en fournissant un ficher test-malloc.c et un fichier Makefile pour utiliser votre fonction malloc.

Attention : les tests devront être conséquents, avec de nombreuses allocations / désallocations... La qualité des tests sera prise en compte.