2.2.1 Le modèle de nommage
Il est utile d’avoir un modèle de la façon dont les noms sont associés à des objets spécifiques. Un concepteur de système crée un schéma de nommage, qui se compose de trois éléments. Le premier élément est un espace de nom, qui comprend un alphabet de symboles ainsi que des règles syntaxiques qui spécifient quels noms sont acceptables. Le deuxième élément est un algorithme de mappage de noms, qui associe certains noms (pas nécessairement tous) de l’espace de noms à certaines valeurs (là encore, pas nécessairement toutes) dans un univers de valeurs, qui est le troisième et dernier élément du schéma de nommage. Une valeur peut être un objet, ou un autre nom de l’espace de noms original ou d’un autre espace de noms. Une correspondance nom-valeur est un exemple de liaison, et lorsqu’une telle correspondance existe, on dit que le nom est lié à la valeur. La figure 2.10 illustre.
Dans la plupart des systèmes, typiquement, plusieurs schémas de dénomination distincts sont en fonctionnement simultanément. Par exemple, un système peut utiliser un schéma de dénomination pour les noms de boîtes aux lettres électroniques, un deuxième schéma de dénomination pour les hôtes Internet, un troisième pour les fichiers et un quatrième pour les adresses de mémoire virtuelle. Lorsqu’un interprète de programme rencontre un nom, il doit savoir quel schéma de dénomination il doit invoquer. L’environnement entourant l’utilisation du nom fournit généralement suffisamment d’informations pour identifier le schéma de dénomination. Par exemple, dans un programme d’application, l’auteur de ce programme sait que le programme doit s’attendre à ce que les noms de fichiers soient interprétés uniquement par le système de fichiers et que les noms d’hôtes Internet soient interprétés uniquement par un certain service réseau.
L’interprète qui rencontre le nom exécute l’algorithme de mappage de noms du schéma de nommage approprié. L’algorithme de mappage de noms résout le nom, ce qui signifie qu’il découvre et renvoie la valeur associée (pour cette raison, l’algorithme de mappage de noms est également appelé un résolveur). L’algorithme de mappage de noms est généralement contrôlé par un paramètre supplémentaire, appelé contexte. Pour un schéma de nommage donné, il peut y avoir de nombreux contextes différents, et un même nom de l’espace de nommage peut correspondre à différentes valeurs lorsque le résolveur utilise différents contextes. Par exemple, dans le discours ordinaire, lorsqu’une personne se réfère aux noms “vous”, “ici” ou “Alice”, la signification de chacun de ces noms dépend du contexte dans lequel la personne le prononce. En revanche, certains systèmes de dénomination n’ont qu’un seul contexte. Ces schémas de dénomination fournissent ce que l’on appelle des espaces de noms universels, et ils ont la propriété agréable qu’un nom a toujours la même signification dans ce schéma de dénomination, peu importe qui l’utilise. Par exemple, aux États-Unis, les numéros de sécurité sociale, qui identifient les comptes de pension et d’impôts du gouvernement, constituent un espace de nommage universel. Lorsqu’il existe plus d’un contexte, l’interprète peut indiquer au résolveur celui qu’il doit utiliser ou le résolveur peut utiliser un contexte par défaut.
Nous pouvons résumer le modèle de dénomination en définissant l’opération conceptuelle suivante sur les noms :
value ← resolve (nom, contexte)
Lorsqu’un interprète rencontre un nom dans un objet, il détermine d’abord quel schéma de dénomination est impliqué et donc quelle version de resolve il doit invoquer. Il identifie ensuite un contexte approprié, résout le nom dans ce contexte, et remplace le nom par la valeur résolue en poursuivant l’interprétation. La variable context indique à resolve le contexte à utiliser. Cette variable contient un nom connu comme une référence de contexte.
Dans un processeur, les numéros de registre sont des noms. Dans un processeur simple, l’ensemble des noms de registres, et les registres auxquels ces noms sont liés, sont tous deux fixés au moment de la conception. Dans la plupart des autres systèmes qui utilisent des noms (y compris le schéma de nommage des registres de certains processeurs à haute performance), il est possible de créer de nouvelles liaisons et de supprimer les anciennes, d’énumérer l’espace de noms pour obtenir une liste des liaisons existantes, et de comparer deux noms. A ces fins, nous définissons quatre opérations plus conceptuelles :
état ← bind (nom, valeur, contexte)
état ← unbind (nom, contexte)
liste ← énumérer (contexte)
résultat ← comparer (nom1, nom2)
La première opération change le contexte en ajoutant une nouvelle liaison ; le résultat d’état signale si le changement a réussi ou non (il peut échouer si le nom proposé viole les règles syntaxiques de l’espace de noms). Après un appel réussi à bind, resolve renverra la nouvelle valeur de name.* La deuxième opération, unbind, supprime une liaison existante du contexte, le résultat de status indiquant à nouveau le succès ou l’échec (peut-être parce qu’il n’y avait pas de liaison existante). Après un appel réussi à unbind, resolve ne retournera plus cette valeur pour name. Les opérations bind et unbind permettent d’utiliser les noms pour établir des connexions entre les objets et de modifier ces connexions ultérieurement. Le concepteur d’un objet peut, en utilisant un nom pour faire référence à un objet composant, choisir l’objet auquel ce nom est lié, soit à ce moment-là, soit ultérieurement, en invoquant bind, et éliminer une liaison qui n’est plus appropriée en invoquant unbind, le tout sans modifier l’objet qui utilise le nom. Cette possibilité de retarder et de modifier les liaisons est un outil puissant utilisé dans la conception de presque tous les systèmes. Certaines implémentations de nommage fournissent une opération enumerate, qui renvoie une liste de tous les noms qui peuvent être résolus dans le contexte. Certaines implémentations de enumerate peuvent également retourner une liste de toutes les valeurs actuellement liées dans le contexte. Enfin, l’opération compare rapporte (vrai ou faux) si nom1 est identique ou non à nom2. La signification de “même” est une question intéressante abordée dans la section 2.2.5, et elle peut nécessiter de fournir des arguments de contexte supplémentaires.
Différents schémas de nommage ont des règles différentes sur l’unicité des mappings nom-valeur. Certains schémas de nommage ont une règle selon laquelle un nom doit correspondre à exactement une valeur dans un contexte donné et une valeur ne doit avoir qu’un seul nom, tandis que dans d’autres schémas de nommage, un nom peut correspondre à plusieurs valeurs, ou une valeur peut avoir plusieurs noms, même dans le même contexte. Un autre type de règle d’unicité est celui d’un espace de noms à identifiant unique, qui fournit un ensemble de noms qui ne seront jamais réutilisés pendant la durée de vie de l’espace de noms et qui, une fois liés, resteront toujours liés à la même valeur. On dit d’un tel nom qu’il a une liaison stable. Si un espace de noms d’identificateurs uniques a également pour règle qu’une valeur ne peut avoir qu’un seul nom, les noms uniques deviennent utiles pour garder la trace des objets sur une longue période, pour comparer les références afin de voir si elles concernent le même objet, et pour la coordination des copies multiples dans les systèmes où les objets sont répliqués pour des raisons de performance ou de fiabilité. Par exemple, le numéro de compte client de la plupart des systèmes de facturation constitue un espace de nom d’identifiant unique. Le numéro de compte fera toujours référence au même compte client tant que ce compte existe, malgré les changements d’adresse, de numéro de téléphone ou même de nom personnel du client. Si le compte d’un client est supprimé, le numéro de compte de ce client ne sera pas un jour réutilisé pour le compte d’un autre client. Les champs nommés au sein du compte, tels que le solde dû, peuvent changer de temps en temps, mais la liaison entre le numéro de compte du client et le compte lui-même est stable.
L’algorithme de mappage de noms plus un contexte unique ne mappent pas nécessairement tous les noms de l’espace de noms en valeurs. Ainsi, un résultat possible de l’exécution de resolve peut être un résultat non trouvé, que resolve peut communiquer à l’appelant soit comme une valeur réservée, soit comme une exception. D’autre part, si le schéma de nommage permet à un nom de correspondre à plusieurs valeurs, le résultat possible peut être une liste de valeurs. Dans ce cas, l’opération de déliaison peut nécessiter un argument supplémentaire qui spécifie la valeur à délier. Enfin, certains schémas de nommage fournissent une recherche inverse, ce qui signifie qu’un appelant peut fournir une valeur comme argument à l’algorithme de mappage de noms, et trouver quel(s) nom(s) est (sont) lié(s) à cette valeur.
La figure 2.10 illustre le modèle de nommage, montrant un espace de noms, l’univers de valeurs correspondant, un algorithme de mappage de noms, et un contexte qui contrôle l’algorithme de mappage de noms.
En pratique, on rencontre trois algorithmes de mappage de noms fréquemment utilisés :
Recherche dans une table
■
Recherche récursive
■
Recherche multiple
L’implémentation la plus courante d’un contexte est une table de paires {nom, valeur}. Lorsque l’implémentation d’un contexte est une table, l’algorithme de mappage de noms est juste un lookup du nom dans cette table. La table elle-même peut être complexe, impliquant un hachage ou des arbres B, mais l’idée de base reste la même. Lier un nouveau nom à une valeur consiste à ajouter cette paire {nom, valeur} à la table. La figure 2.11 illustre cette mise en œuvre courante du modèle de nommage. Il existe une telle table pour chaque contexte, et différents contextes peuvent contenir différentes liaisons pour le même nom.
Les exemples du monde réel du modèle de nommage général et de la mise en œuvre de la consultation de table abondent :
Un annuaire téléphonique est un contexte de consultation de table qui lie les noms des personnes et des organisations aux numéros de téléphone. Comme dans l’exemple du réseau de communication de données, les numéros de téléphone sont eux-mêmes des noms que la compagnie de téléphone résout en apparences de lignes physiques, à l’aide d’un algorithme de mappage de noms qui implique des codes régionaux, des centraux et des commutateurs physiques. Les annuaires téléphoniques de Boston et de San Francisco sont deux contextes du même schéma de dénomination ; tout nom particulier peut apparaître dans les deux annuaires, mais si c’est le cas, il est probablement lié à des numéros de téléphone différents.
De petits entiers nomment les registres d’un processeur. La valeur est le registre lui-même, et le mappage du nom à la valeur est accompli par câblage.
Les cellules de mémoire sont nommées de façon similaire avec les nombres appelés adresses, et le mappage du nom à la valeur est à nouveau accompli par câblage. Le chapitre 5 décrit un mécanisme de renommage d’adresses appelé mémoire virtuelle, qui lie des blocs d’adresses virtuelles à des blocs de cellules de mémoire contiguës. Lorsqu’un système met en œuvre plusieurs mémoires virtuelles, chaque mémoire virtuelle constitue un contexte distinct ; une adresse donnée peut faire référence à une cellule de mémoire différente dans chaque mémoire virtuelle. Les cellules de mémoire peuvent également être partagées entre les mémoires virtuelles, auquel cas la même cellule de mémoire peut avoir les mêmes adresses (ou des adresses différentes) dans différentes mémoires virtuelles, comme déterminé par les liaisons.
Un système de fichiers informatique typique utilise plusieurs couches de noms et de contextes : les secteurs de disque, les partitions de disque, les fichiers et les répertoires sont tous des objets nommés. Les répertoires sont des exemples de contextes de consultation de table. Un nom de fichier particulier peut apparaître dans plusieurs répertoires différents, liés à des fichiers identiques ou différents. La section 2.5 présente une étude de cas du nommage dans le système de fichiers unix.
Les ordinateurs se connectent aux réseaux de communication de données à des endroits connus sous le nom de points d’attachement réseau. Les points d’attache du réseau sont généralement nommés avec deux schémas de nommage distincts. Le premier, utilisé à l’intérieur du réseau, implique un espace de nom constitué de nombres dans un champ de longueur fixe. Ces noms sont liés, parfois de façon permanente et parfois seulement brièvement, à des points d’entrée et de sortie physiques du réseau. Un deuxième schéma de dénomination, utilisé par les clients du réseau, fait correspondre un espace de dénomination universel plus convivial de chaînes de caractères aux noms du premier espace de dénomination. La section 4.4 est une étude de cas du système de noms de domaine, qui fournit un nommage convivial des points d’attache pour l’Internet.
Un programmeur identifie les variables de procédure par des noms, et chaque activation de la procédure fournit un contexte distinct dans lequel la plupart de ces noms sont résolus. Certains noms, identifiés comme “statiques” ou “globaux”, peuvent au contraire être résolus dans un contexte qui est partagé entre les activations ou entre différentes procédures. Lorsqu’une procédure est compilée, certains des noms originaux conviviaux des variables peuvent être remplacés par des identifiants entiers plus pratiques à manipuler pour une machine, mais le modèle de dénomination tient toujours.
Un localisateur de ressources uniformes (URL) du World Wide Web est mis en correspondance avec une page Web spécifique par un algorithme relativement compliqué qui décompose l’URL en plusieurs parties constitutives et résout les parties en utilisant différents schémas de dénomination ; le résultat identifie finalement une page Web particulière. La section 3.2 est une étude de cas de ce schéma de nommage.
Un système de facturation client maintient généralement au moins deux types de noms pour chaque compte client. Le numéro de compte nomme le compte dans un espace de nom d’identifiant unique, mais il existe également un espace de nom distinct de noms personnels qui peuvent également être utilisés pour identifier le compte. Ces deux noms sont généralement mis en correspondance avec les enregistrements de compte par un système de base de données, de sorte que les comptes peuvent être récupérés soit par le numéro de compte, soit par le nom personnel.
Ces exemples mettent également en évidence une distinction entre le “nommage” et la liaison. Certains contextes, mais pas tous, “nomment” les choses, dans le sens où ils mettent en correspondance un nom avec un objet dont on pense communément qu’il porte ce nom. Ainsi, l’annuaire téléphonique ne “nomme” ni les personnes ni les lignes téléphoniques. Ailleurs, il existe des contextes qui lient les noms aux personnes et qui lient les numéros de téléphone à des téléphones physiques particuliers. L’annuaire téléphonique lie les noms des personnes aux noms des téléphones.