\chapter{Le développement} \section{Outils utilisés pour le développement} \subsection{Travail collaboratif} \par Nous avons travaillé ensemble gr{\^a}ce à CVS (Concurrent Versions System). Notre projet est hébergé chez Sourceforge\footnote{\url{http://www.sourceforge.net}}. Le CVS permet la modification du code du projet en m{\^e}me temps par plusieurs personnes. Les modifications et les mises à jour de chacun des membres du projet sont diffusées instantanément, avec un risque minimisé de conflits lors des modifications du m{\^e}me code. \subsection{Moyens techniques} \par Chacun selon nos préférences, nous avons utilisés des machines sous GNU/Linux ou Microsoft Windows et codé avec Vim. La personne sous Microsoft Windows avait une session graphique sur un serveur GNU/Linux, appartenant a un autre membre du projet, gr{\^a}ce à l'utilisation de VNC\footnote{\url{http://www.realvnc.com}} (Virtual Network Computing). Cela afin de permettre à l'utilisateur de Microsoft Windows de pouvoir tester la bibliothèque dans les meilleures conditions, car sous Microsoft Windows l'utilisateur n'est pas prévenu des {\em segmentation fault} et autres erreurs système. \section{Programmation} \subsection{Description des fonctions et de leurs effets} \par Nous allons dresser un descriptif de l'utilité des fonctions utilisées dans notre bibliothèque. Vous trouverez tous les prototypes des fonctions dans le fichier \\``\verb+/src/proto.h+'', avec en commentaire le fichier d'où il est issu. Par contre pour les fonctions qui génèrent les {\em ids}, leur prototype est dans le fichier ``\verb+/src/ids.h+'', généré par ``\verb+/src/ids.c+''. Le fichier ``\verb+/src/proto.h+'' est connu des logiciels qui utilisent notre bibliothèque, tandis que ``\verb+/src/ids.h+'' non. Nous allons donc vous décrire nos différentes fonctions en les classant par famille. \newline \par Nous avons quatre grandes {\em familles} de fonctions. \begin{description} \item{\sc msgBuffer*} Ce sont toutes les fonctions qui concernent les buffers : comment on les créés, les ``attachent'' aux processus. \item{\sc msgPool*} Ce sont les fonctions qui permettent de créer ou de détruire une {\em pool}, de l'ouvrir ou encore de poser un ``verrou''. \begin{description} \item{\sc msgPool*} Fonctions servant à gérer une {\em pool}, qui correspond à un ensemble de {\em buffers}. \item{\sc msgPoolDataTab*} Fonctions utiles pour la gestion des informations d'une {\em pool} telles que la taille des {\em buffers}, leur nombre\dots \end{description} \item{\sc msgQueue*} Toutes les fonctions gérant les ``queues'', {\em files de maessages}. On y trouve celle qui en créé une, celles qui vérifient si elle est disponible ou pas, celles qui ajoutent un élément ou au contraire en enlève un. \begin{description} \item{\sc msgQueue*} Rassemble toutes les fonctions servant à la gestion des files de messages. \item{\sc msgQueueElem*} Les fonctions utiles pour gérer un élément d'une file de messages. \item{\sc msgQueue(Prot/Read)*} Fonctions servant à protéger une file. \end{description} \item{\sc msgSpace*} Ensemble de fonctions qui gèrent les espaces de messages : création, ouverture, listes\ldots \begin{description} \item{\sc msgSpace*} Fonctions pour la création, ``ouverture'', ``fermeture''\dots d'un espace de messages. \item{\sc msgSpaceList*} Ce sont toutes les fonctions utiles pour la gestion de la liste cha{\^i}née des {\em msgSpace} existants. \item{\sc msgSpaceListElem*} Fonctions correspondant à la gestion d'un élément de la {\em msgSpaceList}. \end{description} \end{description} \subsection{Détails sur certaines fonctions} \par Nous détaillerons ici quelques fonctions qui peuvent ne pas par{\^i}tre claires, malgré les explications au-dessus, ou qui n'ont pas encore été abordées. \par Voici la liste des fonctions non abordées dans la partie précédente, mais néanmoins utiles pour la compréhension de notre bibliotèque. Les fonctions pour la génération d'{\em ids} ne seront pas traitées ici, car leur utilité est décrite dans la partie {\sc Difficultés recontrées}. \begin{itemize} \item{\sc msgAllocate(\dots)} Prend en argument : un espace de mesage\\ {\em msgSpace *}, un numéro de {\em pool} qui est un {\em int}, une taille {\em int} et une option {\em int}. Cette fonction, comme spécifié dans l'énoncé, alloue un buffer dans le {\em pool} spécifié, ou sinon dans le {\em pool} le plus proche en taille (supérieure ou égale) et qui sera ``potentiellement'' libre le plus rapidement, sauf s'il l'est déjà. Pour cela, on regarde le nombre de {\em locks}, qu'il y a dessus gr{\^a}ce aux sémaphores. On choisit le buffer dont le {\em pool} a le moins de ``locks'' en fonction du nombre de ses buffers. \item{\sc msgFree(\dots)} Cette fonction prend en argument un espace de message {\em msgSpace *} et l'adresse d'un buffer {\em void *}. Celle-ci restitue le buffer au {\em pool} d'où il a été extrait. \item{\sc msgGet(\dots)} Notre fonction {\em void * msgGet(\dots)}, est telle qu'elle corresponde bien à l'énoncé. Elle prend en argument un espace de messages {\em msgSpace *}, un numéro de file, ou {\em queue}, {\em int} et l'adresse d'un buffer {\em void *}. Elle renvoie l'adresse du buffer en t{\^e}te de la file du numéro donné dans l'espace de messages spécifiés. Lors d'un appel à cette fonction, celle-ci ``locke'' d'abord le sémaphore qu'il y a sur la {\em queue}. Si la file est vide, cela bloque le {\em get}.\\ {\sc Remarque :} Nous n'avons pas implémenté le cas du \verb+ANYFILE+. \item{\sc msgPut(\dots)} Cette fonction fait exactement ce qu'elle est sensée faire tel que énoncé dans le rapport. Elle prend en argument un espace de messages {\em msgSpace *}, un numéro de file, ou {\em queue}, {\em int} et l'adresse d'un buffer {\em void *}. Elle insère le buffer dans le numéro de file de messages de l'espace de messages. Lorsque l'on appelle cette fonction, à la fin, on ``délocke'' le sémaphore sur la {\em queue}. \item{\sc msgSpaceState(\dots)} Cette fonction prend en argument, un ``id'' d'espace de message, {\em msgSpaceId}, et permet de conna{\^i}tre l'état de l'espace de message dont l'``id'' est donnée en argument. \end{itemize} \newpage \section{Difficultés rencontrées} \par Nous n'avons pas eu de grosses difficultés à proprement parlé. Nous avions juste quelques restrictions, comme le fait de ne pas pouvoir utiliser de pointeurs absolus, car l'espace d'adressage entre les différents processus n'est pas forcément le m{\^e}me. Ils ont seulement un segment de mémoire partagée en commun. Il a donc fallu utiliser les différentes {\em id} des espaces de messages {\em msgSpace}, ou encore des {\em pools} pour pouvoir faire en sorte que les processus peuvent bien accéder aux {\em buffers} situés dans la mémoire partagée. \par Le choix des identifiants ne fut pas simple non plus, car il fallait en changer en fonction des différentes implémentations. Par exemple nous pouvions avoir des identifiants du type ``\verb+/tmp/identifiant+'', qui ne marchaient que sur un type de machines. Sur les autres il fallait en avoir un du type ``\verb+/identifiant+''. Cela nous a amener à faire une distinction de cas et générer un identifiant différent selon que l'on soit sur une machine de type {\em HP-UX}, {\em SunOS} ou {\em Linux}. \par Malheureusement le fait de travailler sur plusieurs types de machines n'était pas seulement g{\^e}nant pour les identifiants, mais également pour créer la bibliothèque. En effet, il faut ajouter plus ou moins d'options à la compilation: soit il faut ajouter \verb+-lrt+, dans un cas ou \verb+-lrt -lpthread+ dans l'autre. Ceci afin d'inclure les bonnes librairies pour que notre bibliothèque puisse fonctionner convenablement. \par Ces distinctions se font dans les {\em Makefile}, \verb+/src/Makefile+ et \verb+/test/Makefile+. \par Encore une autre difficulté d{\^u}e à Posix, est la projection de fichier ou {\em mapping} avec {\em mmap}. L'offset peut {\^e}tre aligné sur les pages mémoires sur certains systèmes. Or ceci est emb{\^e}tant lorsque l'on veut accéder à un fichier qui commence n'importe où dans le bloc mémoire. Pour remédier à cela, nous {\em mappons} jusqu'à ``juste derrière le buffer''. Nous autorisons le buffer en lecture/écriture et nous déplaçons l'adresse obtenue au début du buffer.