:: Enseignements :: Licence :: L3 :: 2008-2009 :: Programmation système en C ::
[LOGO]

Projection en mémoire (mmap)


MMAP est une abréviation pour memory-map. En français: projection mémoire. Plus précisément, on parle ici de projection de fichiers. L'appel système mmap() permet de faire correspondre une partie de la mémoire à un fichier du disque. Voici quelques exemples d'utilisation de cette primitive:

Nous allons ici utiliser mmap et les signaux pour construire un protocole d'échange de messages entre plusieurs processus.

Exercice 1 - Premier clap

Exercice 2 - Bout d'essai

Écrire maintenant un programme prenant deux arguments et effectuant une recopie de fichier grâce à mmap. Attention, le fichier d'origine peut faire n'importe quelle taille cette-fois ci (truc et astuce: stat et memcpy sont tes amis). Note: pour faire une projection "en écriture", il faut avoir ouvert le fichier écriture, l'avoir projeté en écriture aussi, et de façon partagée (sinon les modifications ne sont pas reflétées sur le fichier réel).

Exercice 3 - Ça tourne

Passons aux choses sérieuses! écrire un programme arbitre qui prend en argument un nom de fichier et une taille. Le programme doit créer le fichier, lui donner la taille voulue, le projeter en mémoire, puis y écrire son PID sur 4 octets (comme un int) au tout début, puisremplir le reste avec des zéros.

Écrire maintenant un programme utilisateur, prenant en argument un nom de fichier et un message. Ce programme doit ouvrir le fichier, le projeter intégralement en mémoire, lire le PID contenu au début et l'afficher. Puis il doit lire toutes les chaînes présentes dans le fichier, et ajouter le message passé comme argument de la ligne de commande au bout des chaînes déjà existantes. On considère que les chaînes sont séparées par des zéros. Ainsi, au bout de quelques messages, le fichier pourra contenir ceci: "XXXXJe crois que nous avons affaire à un serial killer.\0Un quoi?\0Un serial killer.\0\0\0\0\0", avec ensuite autant de \0 que nécessaires pour compléter le fichier. XXXX est le PID sur 4 octets.

Tester le programme en ajoutant quelques messages. Sauter de joie en levant les deux bras en l'air et en s'exclamant d'un air satisfait : "Yes!" Puis réfléchir aux problèmes de ce "protocole". Si vous ne voyez pas ce qui peut arriver, modifiez le programme utilisateur pour qu'il copie les octets 1 par 1, avec une attente de 1 seconde entre deux octets, puis lancez-le plusieurs fois en même temps.

Exercice 4 - Promotion

Passons aux signaux. écrire un programme qui affiche son PID, puis met en place un gestionnaire de signaux pour SIGUSR1, et attend la réception de ce signal (avec pause() par exemple). Lorsque le signal est reçu, il faut afficher le PID du processus qui a envoyé le signal. Pour celà, utiliser le flag SA_SIGINFO et un gestionnaire de signaux à trois arguments (voir la manpage de sigaction pour le prototype exact). Tester le programme en faisant kill X depuis le shell (où X est le PID du programme - qui a été affiché, rappelez-vous).

Modifier arbitre et utilisateur de façon à ce qu'avant d'écrire un message, l'utilisateur doive envoyer le signal USR1 à l'arbitre (dont le PID est dans le fichier d'échange, n'est-ce pas). L'arbitre envoie à ce moment là un signal USR1 à l'utilisateur si personne d'autre n'est en train d'accéder à la zone d'échange. Sinon il envoie USR2. Si l'utilisateur a reçu USR1, il peut alors lire et écrire des messages, puis il envoie USR2 à l'arbitre pour indiquer qu'il a fini. Si l'utilisateur avait reçu USR2 (signifiant "ressource occupée"), il a le droit de réessayer régulièrement d'envoyer USR1 (pour dire "je demande l'accès") jusqu'à ce qu'il y arrive (ou bien il peut immédiatement afficher un message d'erreur disant "réessayez plus tard" et quitter).