l3.libnazgul/doc/rapport/devel.tex

169 lines
8.7 KiB
TeX

\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 peuvent
ainsi être 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 compiler et tester
la bibliothèque dans de meilleurs conditions que sous son système initial\ldots
\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+''.
\par 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[msgBuffer*]{Ce sont toutes les fonctions qui concernent les
buffers : création, attachement aux processus\ldots}
\item[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[msgPool*]{Fonctions servant à gérer une {\em pool}, qui
correspond à un ensemble de {\em buffers}.}
\item[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[msgQueue*]{Toutes les fonctions gérant les ``queues'', {\em
files de messages}. On y trouve celle qui en créé une, celles i
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[msgQueue*]{ Rassemble toutes les fonctions servant à la gestion
des files de messages.}
\item[msgQueueElem*]{ Les fonctions utiles pour gérer un élément
d'une file de messages.}
\item[msgQueue(Prot|Read)*]{Fonctions servant à protéger une file
({\em read} indique la disponibilité d'une ressource en lecture,
{\em Prot} la protection contre les modification).}
\end{description}
}
\item[msgSpace*]{Ensemble de fonctions qui gèrent les espaces de
messages : création, ouverture, listes\ldots
\begin{description}
\item[msgSpace*]{Fonctions pour la création, ``ouverture'', ``fermeture''\dots d'un espace de messages.}
\item[msgSpaceList*]{Ce sont toutes les fonctions utiles pour la
gestion de la liste cha{\^i}née des {\em msgSpace} existants.}
\item[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}.
\end{itemize}
\newpage
\section{Difficultés rencontrées}
\subsection{Restrictions}
\par Nous n'avons pas eu de grosses difficultés à proprement parler.
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.
\par Il a donc fallu utiliser les différentes {\em id} (c'est à dire les identifiants POSIX) des espaces de messages {\em msgSpace}, des {\em pools}
et autres types de données stockées en mémoire partagée pour pouvoir permettre a tous les processus d'accéder correctement aux données.
\subsection{Libertés d'implémentations de POSIX\ldots}
\par Le choix des identifiants ne fut pas simple non plus, car il
fallait en changer en fonction des différentes implémentations de POSIX.
En effet la norme POSIX précise que l'identifiant doit commencer par un ``\verb+/+'' et si possible ne pas en comporter d'autres.
\par Si cela est vrai sur certains systèmes (comme GNU/Linux) d'autres
systemes (HP-UX, SunOS) requièrent que cet identifiant corresponde
au chemin absolu (dans l'arborescence UNIX) d'un fichier sur lequel
on possède des droits\ldots
\par Nous avons donc choisi les identifiants du type
``\verb+/tmp/identifiant+'', qui pour les systèmes avec la restrictions précédente et ``\verb+/identifiant+'' sur les autres. i
Cela nous a également conduit à faire une distinction dans le \verb+Makefile+
entre les options de compilation pour {\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
compiler et fonctionner convenablement.
\par La seconde difficulté liée à POSIX, est la projection de fichier
ou {\em mapping} avec {\em mmap}. Selon l'implémentation, l'offset (décalage par rapport au début de l'addresse mémoire du fichier) peut éventuellement {\^e}tre aligné sur la taille des pages mémoires\ldots
\par Ceci est assez génant lorsque l'on veut accéder à bloc de donnée
qui peut commencer n'importe où dans la zone de mémoire partagée.
Pour remédier à cela, nous {\em mappons} du début de la zone mémoire partagée jusqu'à ``juste derrière'' le bloc de donnée qui nous intéresse.
\par Puis nous changeons les droits d'acces (\verb+mprotect+) pour nous autoriser la modifiction uniquement sur le bloc de données qui nous intéresse.
\par Enfin nous opérons le décalage d'addresse ``à la main'' et renvoyons l'addresse qui correspond au début du bloc de données demandé.