|
||||||||||||||||||||||||||||||||||||||||||||||
|
Le système d'exploitation de l'Amiga propose un système d'entrées-sorties souple et général. Ce système se décompose en plusieurs parties que je me propose d'étudier brièvement. Il ne s'agit pas ici d'une description technique exhaustive de l'organisation des fichiers ou du format des disques, ces sujets ayant déjà été amplement abordés par d'autres ouvrages ; il s'agit plutôt de dégager les concepts clefs employés. Afin de les relativiser, je me permettrai dans un second temps, de comparer ce système aux équivalents existant sous VMS et Unix, voire MS-DOS. Les périphériques et les fichiers : opérations de base L'Amiga permet la connexion de divers périphériques (imprimantes, lecteurs de disquette, disques durs...). Le DOS permet d'accéder à ceux-ci comme à des fichiers. Mieux, il étend cette notion et propose des périphériques qui n'ont pas de matériel correspondant (PIPE: ou RAM:), le tout grâce à une courte chaîne de caractères (nom logique) de la forme :
Exemple :
Quatre fonctions de base de la dos.library permettent de manipuler ces périphériques : Open, Read, Write et Close. Open() prend deux paramètres : la chaîne de caractères désignant le périphérique et le mode d'ouverture. Un appel réussi à Open() fournit un BPTR qui désigne un fichier logique (FileHandle). Il s'agit en fait d'une sorte de pointeur (pointeur BCPL) sur une structure normalement privée (privée signifie ici que l'utilisateur n'a pas à savoir ce qu'elle contient). Ce BPTR sera utilisé dans toutes les opérations sur ce fichier. Les quatre opérations de base sur les fichiers peuvent être qualifiées de génériques : elles ne dépendent nullement du type de fichier manipulé. Cela peut très bien être une fenêtre "NEWCON:", la prise série "SER:", un pipe, un fichier disque. Cela donne à AmigaDOS une souplesse remarquable et facilite grandement les opérations courantes. Ainsi, le Shell peut-il rediriger les entrées et les sorties d'une commande de façon totalement transparente. Comment cette généralité est-elle atteinte ? La solution utilisée est très élégante, il s'agit d'une solution orientée objet. Attention, ce mot très à la mode est souvent utilisé à tort ; ici, il convient parfaitement (Cf. cet article pour les aspects Orientés Objet) ; pour s'en convaincre, examinons de plus près la structure fichier, File-Handle. ![]() On remarque la présence de ports de messages. Nous reviendrons sur leurs rôles ultérieurement. On note que la structure FileHandle contient un pointeur sur un tampon, l'indication de la position courante et celle de la fin du tampon, ce qui permet de programmer un système de fichiers avec tampon mémoire. On note enfin la présence de trois champs "Func", pointeurs sur des fonctions qui sont appelées de façon interne quand on procède à une lecture et que le tampon est vide (fh_Func 1), à une écriture lorsque le tampon est plein (fh_Func2) ou à la fermeture de ce fichier (fh_Func3). Ainsi pour les opérations courantes, DOS n'a pas besoin de connaître le type de fichier auquel il a à faire. Dans la terminologie des langages orientés objets, ces fonctions sont qualifiées de méthodes virtuelles. Cela permet, tout en gardant un même type FileHandle de procéder à des traitements différents selon les types particuliers de fichiers. Le rôle des gestionnaires (handlers) Ce n'est pas directement la dos.library (les fonctions du DOS) qui procède aux traitements réels sur les fichiers. Interviennent à ce niveau les gestionnaires. Dans ce contexte, le terme "handler" peut être traduit par "gestionnaire d'entrée/sortie". Comment se présentent ces gestionnaires à l'utilisateur moyen ? S'il a eu le courage d'ouvrir les documentations qui accompagnent sa machine, il a pu lire "le répertoire L: qui contient les gestionnaires". L'autre endroit ou apparaissent les gestionnaires est la liste de montage (mountlist), dans laquelle figure des lignes de la forme :
S'il est curieux, il a pu tenter l'expérience suivante dans un Shell : "dir L:". Dans la liste obtenue, il a remarqué des noms de fichiers du type "qq_chose-handler" et d'autres comme FastFileSystem, Shell-Seg. Presque tous ces fichiers sont des gestionnaires au sens AmigaDOS du terme. Un gestionnaire est un programme exécutable qui gère un périphérique particulier au niveau DOS. Il permet à la dos.library d'opérer des opérations standard sur ce périphérique. Ce sont les gestionnaires qui définissent et gèrent les systèmes de fichiers, c'est-à-dire l'organisation d'une mémoire de masse. Nous verrons le cas des périphériques disques plus loin. Ces programmes sont exécutés lors de l'appel de la commande "Mount" ou, pour ceux qui résident en ROM (système de fichiers, gestionnaire propres à un contrôleur de disque dur autodémarrable), pendant la phase d'initialisation. Ils créent un processus chargé de gérer le périphérique au niveau DOS. Quel est le lien entre ces gestionnaires et la dos.library ? Chaque opération sur un périphérique au niveau DOS se traduit par un échange de messages entre le gestionnaire et la tâche qui exécute la routine de dos.library. En effet, chaque tâche est munie d'un port de message en standard. Ces messages sont appelés DOS-Packets et il existe un type de paquet pour chaque opération DOS. Rares sont les gestionnaires qui gèrent tous les types de paquets. Ce processus-handler opère comme un serveur ; les tâches envoient des requêtes qu'il exécute quand il le peut. Il répond en envoyant à chaque tâche cliente un message contenant un code d'erreur. C'est ce qui permet à votre tâche préférée d'entrer en état d'attente donc de ne pas consommer de puissance processeur. Ce système à une autre conséquence : il consacre le signal comme unique mécanisme de synchronisation. En effet, quand une tâche attend le résultat d'une opération, elle exécute un WaitPort, ce qui lui permet d'attendre le paquet-réponse du processus-handler. Ce WaitPort() est implémenté par un Wait() sur le signal alloué au port. La seconde conséquence est qu'il est possible de faire des opérations intéressantes du genre entrées/sorties DOS asynchrones (c'est-à-dire sans attendre le résultat) ou surveillance de multiples fichiers. Le rôle des périphériques logiques (devices) Avant d'attaquer les périphériques disques, un bref aperçu sur les périphériques logiques. Il suffit de savoir que les périphériques logiques sont une interface entre un périphérique physique et le système d'exploitation. Ils permettent la sérialisation des entrées/sorties (c'est-à-dire le traitement des requêtes une par une) nécessaire dans une machine multitâche et ils opèrent comme des serveurs. Les périphériques logiques possèdent une structure semblable à celle d'une bibliothèque bien que l'ouverture d'un périphérique logique provoque l'apparition d'une tâche spécifique. Le périphérique logique communique avec les autres tâches via un port de message et une sous-classe de messages appelée IO-Request. Il suffit, pour comprendre la suite de mon propos, de savoir qu'un périphérique logique se charge du dialogue avec le matériel et qu'il n'est en aucun cas directement accessible par DOS. Il faut ajouter que pour constituer un périphérique DOS, un périphérique logique n'est pas toujours nécessaire. Un gestionnaire seul peut suffire. La liste de montage contient des exemples où la ligne "device = <nom de fichier>" est absente. Les périphériques disques, la structure Lock L'intérêt de ce découpage en périphérique logique/gestionnaire apparaît lorsque l'on examine les périphériques disques. Une structure commune est liée à tous les périphériques disques. Il s'agit de la structure "Lock". Ce terme peut être traduit par "verrou". ![]() En effet, son rôle principal est de réserver un accès partageable ou exclusif (champ fl_Access) à un objet disque. Il permet donc d'éviter les collisions. La structure Lock elle-même contient principalement des informations sur le placement physique de l'objet disque concerné, à savoir :
L'apparition de cette structure Lock correspond à des besoins nouveaux. Il ne s'agit plus simplement d'ouvrir, de lire, d'écrire et de fermer un périphérique. A la notion de disque se rattachent les concepts de fichiers et d'arborescence des répertoires. On peut maintenant relire ce que l'on a écrit, renommer un fichier, le déplacer dans d'arborescence, le supprimer, etc. La plupart des appels système qui permettent de manipuler les fichiers, en dehors des quatre fonctions de base, manipulent des Locks. Le système 2.0 amène de nouvelles possibilités : on peut maintenant travailler sur des portions de fichiers (verrous partiels) ou se faire signaler toute modification d'un fichier. A chacune de ces manipulations sur le système de fichiers correspond un paquet qui est envoyé par le DOS au gestionnaire qui effectue l'opération. On comprend là son rôle capital puisque c'est lui qui définit et gère l'organisation du disque, les autres couches (device ou DOS) n'ayant rien à voir avec cette organisation. Quel est le lien entre la structure Lock et FileHandle ? A l'ouverture d'un fichier, DOS crée d'une part un Lock qu'il va transmettre comme argument dans le paquet et d'autre part un pointeur sur un FileHandle que le gestionnaire se chargera de compléter. Il utilisera les informations fournies par le Lock pour trouver l'emplacement physique du fichier sur le disque et maintiendra de façon interne ces informations. Par contre, dans les paquets de lecture, d'écriture et de fermeture, il n'y a aucune mention directe du Lock : c'est le gestionnaire qui se chargera de la libération. Aperçu synthétique Les périphériques disques illustrent parfaitement l'ordonnancement des différents sous-systèmes qui prennent en charge les entrées/sorties. On voit se dessiner l'architecture logicielle en quatre couches d'AmigaDOS. ![]() Architecture logicielle du système d'entrée/sortie de l'Amiga 2. La couche Device : les divers périphériques logiques dialoguent avec la couche précédente en écrivant dans les registres appropriés, en traitant les interruptions générées par le matériel et en se chargeant du travail spécifique au type de matériel lors des opérations de lecture et d'écriture. Cette couche offre des services d'entrées-sorties brutes qui sont commandés par des IO-Request (lecture de secteur, écriture de secteur, lecture et écriture tamponnée de la prise série, etc.). 3. La couche Handler : elle structure les entrées-sorties en fichiers et définit parfois l'organisation d'ensemble de fichiers (système de fichiers). Elle adresse les périphériques logiques à travers des IO-Requests conformément à la structure qu'elle définit et offre ses services au DOS en dialoguant grâce à des paquets. Elle interprète les chemins des fichiers, les informations à l'ouverture d'une fenêtre CON:... 4. La couche DOS permet des opérations sur les fichiers, chacune de ces opérations se traduisant par un échange de paquets. Elle se charge du travail commun à tous les types de fichiers (réservation et initialisation de structures) et offre aux applications un ensemble de fonctions qui permettent de manipuler les fichiers Read(), Write(), Open(), Seek()... Flexibilité de l'architecture gestionnaire/périphérique logique Prenons l'exemple de MessyDOS, un logiciel DP qui permet de manipuler les disquettes au format MS-DOS comme des disquettes Amiga. Le paquetage logiciel consiste principalement en un périphérique logique qui permet de lire le format physique des disquettes MS-DOS (double densité, organisation des pistes à la norme MS-DOS), et un gestionnaire qui interprète l'organisation de ces mêmes disquettes (système de File Allocation Table de MS-DOS). La liste de montage fournie implémente plusieurs périphériques qui permettent de lire soit des disquettes au format physique MS-DOS avec l'organisation des fichiers Amiga, soit des disquettes au format Amiga avec une organisation des fichiers MS-DOS, tout ceci simplement en changeant les entrées "handler=" et "device=" de la liste de montage. C'est à mon avis une pure merveille. Cette flexibilité est rendue possible par la dos.library. En effet, un gestionnaire ne doit en aucun cas ouvrir lui-même le périphérique logique qu'il utilise : lors de l'initialisation, DOS lui fournit un pointeur sur le périphérique logique utilisé. Les exemples précédents étaient plutôt des cas d'école. Il est tout à fait envisageable d'utiliser une partition PC sur un disque dur et de la lire du côté Amiga. Plus généralement, prenez un disque optique SCSI. Si vous possédez une interface SCSI sur votre machine et un scsi.device, créez une entrée dans la liste de montage dans laquelle vous associez un gestionnaire de votre choix (FastFileSystem par exemple), faîtes un "Mount" et vous avez ajouté votre périphérique dans le système (en principe...). Cela permet à l'utilisateur averti mais non programmeur de jouer avec les différents formats avec une facilité déconcertante. Il est à remarquer que cet ajout de périphériques physiques n'a nécessité aucune modification ni du noyau, ni de la dos.library et qu'il suit une procédure standardisée. De plus, si le périphérique est connecté physiquement, il peut être ajouté et enlevé logiquement du système à tout moment. Ceci dénote une forte ouverture du système d'exploitation Amiga dans un environnement hétérogène. Pour finir avec les périphériques disques, il faut ajouter que Commodore a standardisé une partie de l'organisation des disques durs en créant le Rigid Disk Block (RDB). Il s'agit d'un secteur du disque dur qui contient des informations sur le partitionnement et les caractéristiques du périphérique physique. Il s'agit de faciliter la programmation en cas de disque autodémarable et automontable et d'éviter d'avoir à modifier le gestionnaire et le périphérique logique en cas de changement de disque physique. En effet, sur la plupart des cartes contrôleur modernes, ceux-ci se trouvent en ROM (pour toutes précisions, examiner le fichier include "device/hardblock.h"). Quelques éléments concernant les périphériques réseau Le point faible de l'Amiga est son côté réseau. En partie par manque de standardisation de l'interface avec le système d'exploitation. Quelques produits existent mais ils définissent leurs propres gestionnaires/périphériques logiques pour proposer leurs services. Par exemple, un périphérique LSR: pour accéder à l'imprimante mise en réseau ou NET: pour accéder aux disques d'une machine distante (cas de ParNET). Ces services, bien qu'efficaces restent disparates et les gestionnaires/périphériques logiques correspondants ne sont pas interchangeables comme dans le cas des disques. Quelques éléments cependant laissent à penser qu'une intégration plus poussée des réseaux dans le système d'exploitation de l'Amiga est prévue pour bientôt : Commodore a publié récemment dans des nouvelles Usenet les spécifications d'un nouveau standard nommé SANA-II pour les périphériques logiques chargés de piloter les périphériques réseau. ![]() Architecture supposée du système en environnement réseau comparaison avec le modèle de référence OSI La situation dans d'autres systèmes L'Amiga n'est pas la seule machine sur laquelle ces concepts ont été implémentés. En fait, sur toute machine un tant soit peu sérieuse, on a essayé de mettre à disposition un système d'entrées-sorties indépendant du matériel sous-jacent. Unix est le premier système qui a popularisé l'idée des périphériques vu comme des fichiers. Tous les périphériques sont en effet représentés par des fichiers spéciaux placés dans le répertoire /dev. Unix distingue dans son traitement les périphériques de type blocs et les périphériques de type caractères. Ces fichiers sont gérés par des pilotes qui possèdent des points d'entrées standardisés (fonctions) et Unix possède un tableau qui contient des pointeurs sur ces fonctions. A chaque pilote correspond un nombre ("major number") qui permet de déterminer l'élément du tableau qui doit être utilisé et détermine ainsi la fonction à appeler pour effectuer une opération donnée. On constate que la division gestionnaire/périphérique logique n'existe pas ici et que le pilote Unix prend tout en charge. De plus, le code du pilote doit déjà se trouver dans le noyau ou être chargé selon un protocole propre à la machine. Ce système est donc théoriquement moins souple. MS-DOS a ici plagié Unix avec quelques différences. Là encore, on a un unique pilote par périphérique qui communique avec la tâche appelante par appel direct de fonction. Ceux-ci sont rangés dans une liste chaînée et le code proprement dit est précédé par une structure qui contient entre autres les points d'entrées. La tâche du pilote MS-DOS est grandement facilitée par le fait qu'il n'a pas à gérer les conflits d'accès propres à un environnement multitâche. L'amélioration réside dans le fait que MS-DOS possède l'équivalent de notre liste de montage à savoir le fichier texte "CONFIG.SYS" qui contient des entrées du type <nom de périphérique logique> = <fichier driver>. Cette fois, les pilotes se trouvent à l'extérieur du système ce qui facilite l'intégration d'éléments extérieurs. VMS propose également un accès unifié aux périphériques. Ces services sont regroupés sous le nom de QI0. Il s'agit d'un appel système qui permet d'effectuer les deux opérations de base : lecture et écriture. Un processus séparé appelé "driver" est chargé d'adresser le périphérique physique directement. Il communique avec le système grâce à une "mailbox" (un peu l'équivalent de nos ports de messages) ce qui permet une sérialisation naturelle des appels à ce périphérique. Quand la gestion d'une hiérarchie de fichiers est nécessaire, un intermédiaire, l'ACP (Ancilliary Control Process), met à la disposition des services supplémentaires tels que : créer un répertoire, naviguer dans l'arborescence, détruire un répertoire, etc. Contrairement à AmigaDOS, c'est le "driver" qui se charge de gérer la structure logique du disque. En fait, l'ACP est attaché à un périphérique donné. Les possibilités de VMS sont beaucoup plus étendues mais ceci suffit à exposer le principe de base. Bibliographie et sources d'informations
|