Site WWW de Laurent Bloch
Slogan du site

ISSN 2271-3905
Cliquez ici si vous voulez visiter mon autre site, orienté vers des sujets moins techniques.

Pour recevoir (au plus une fois par semaine) les nouveautés de ce site, indiquez ici votre adresse électronique :

Mémoire virtuelle, persistance : faut-il des fichiers ?
Article mis en ligne le 28 février 2014
dernière modification le 11 mars 2014

par Laurent Bloch
logo imprimer
Licence : CC by

Un article récent et brillant de Baptiste Mélès organise la philosophie de la pratique informatique entre deux concepts, les processus et les fichiers. Le raisonnement est profond, mais ce sont les fichiers qui me gênent : ils me semblent peu aptes à la conceptualisation, mal définis, inventés pour des raisons circonstancielles, et la mémoire me semblerait plus appropriée. En voici donc une critique.

Ce texte est issu (et adapté) de mon livre Systèmes d’exploitation des ordinateurs : histoire, fonctionnement, enjeux, disponible librement en ligne ici.

 La question des fichiers

La notion de fichier pose un problème, qui me fait hésiter à l’ériger en concept, et si je me représente bien pourquoi les concepteurs d’Unix l’ont mise au centre de leur système, je me demande si le nom est bien choisi.

Au début était la mémoire. Comme sa capacité était trop limitée, par héritage de la mécanographie, on a inventé le fichier. Mais ne serait-il pas plus élégant d’en rester à la mémoire, organisée de telle sorte que certaines de ses régions soient persistantes ? Ainsi (c’est Christian Queinnec qui m’en a donné la formule) il y aurait dans la mémoire des objets, dont certains seraient dotés de l’attribut « persistant », ce qui voudrait dire qu’avant l’extinction du processus qui les a créés, ils seraient munis d’un nom unique, et déplacés dans une région persistante de la mémoire (un disque par exemple). Il y a déjà longtemps, c’est ainsi que Multics envisageait les choses. Des systèmes plus récents en ont repris l’idée.

Bien sûr, les auteurs initiaux d’Unix n’étaient pas sans avis polémique sur Multics, trop lourd pour les matériels de l’époque, mais j’ai toujours pensé qu’un malentendu s’était placé là.

 Critique des fichiers ; systèmes persistants

Si nous pensons au système de mémoire virtuelle présenté ici et que nous le comparons à la description du système de fichiers donnée là, nous ne pouvons manquer d’être frappés par leur redondance mutuelle. L’un et l’autre systèmes ont pour fonction d’assurer la persistance de données qui étaient dans la mémoire centrale pour y subir un traitement, qui cessent d’y résider pour une raison ou une autre, et que l’on souhaite néanmoins conserver pour un usage ultérieur. La différence entre les deux réside finalement dans les circonstances qui dans l’un et l’autre cas amènent les données à cesser de résider en mémoire, et c’est cette différence qui est à l’origine de réalisations techniques dont la ressemblance ne saute pas aux yeux. Mais au fond, la mémoire virtuelle et le système de fichiers font la même chose, avec des différences d’interface plus que de fonctionnement, et l’on peut dire que si la mémoire virtuelle était venue plus tôt les fichiers n’auraient sans doute pas vu le jour.

 Précurseurs

D’ailleurs, des précurseurs ont choisi de s’en passer. Dans Multics, évoqué ici et aussi là, la mémoire virtuelle est découpée en segments de taille variable. C’est une structure de mémoire virtuelle plus complexe que celle que nous avons décrite, mais elle remplit les mêmes fonctions. Eh bien, pour Multics on dit simplement que certains segments sont persistants et résident de façon permanente sur disque. C’est un attribut d’un segment : la persistance ! Et pour savoir quels segments sont présents à tel ou tel emplacement de la mémoire persistante, on utilise une commande de liste des segments, en abrégé ls, que les Unixiens reconnaîtront.

Nous avons déjà mentionné le système Pick et celui de l’IBM AS400, construits autour d’une base de données. Le choix est surtout clair avec Pick : chaque donnée individuelle porte un nom utilisable dans l’ensemble du système, et ce système de nommage est unifié. Par exemple, si le système est utilisé pour une application de paie dans un organisme public, il y a une variable et une seule pour donner la valeur du point d’indice des fonctionnaires. Cette variable a un propriétaire (sans doute le Secrétaire d’État à la Fonction Publique), qui dispose seul du droit d’en modifier la valeur. Tous les programmes qui doivent connaître cette valeur peuvent y accéder. Lors de la parution au Journal Officiel d’une modification de la valeur du point d’indice, une seule opération garantit la justesse de tous les calculs.

Incidemment, cette architecture de données procure aux utilisateurs profanes (et aux autres !) une vision considérablement simplifiée de l’ensemble du processus de traitement et de stockage de l’information. Une grande partie de la complexité de ces choses pour le néophyte tient à la difficulté d’avoir une vision d’ensemble d’un système qui réunit et coordonne des objets qui à l’état actif sont en mémoire et qui au repos sont dispersés dans une foule de fichiers aux statuts variés. Avoir un concept unique de mémoire pour tous les objets, persistants ou non, et une désignation unique pour tout objet quels que soient son état et son activité, ce sont des améliorations intellectuelles considérables. Le corporatisme informatique en a eu raison, provisoirement souhaitons-le.

La recherche sur les systèmes persistants continue, même si elle reste assez confidentielle. L’augmentation des performances des processeurs et des mémoires devrait l’encourager en abolissant les obstacles de cet ordre qui ont eu raison des précurseurs.

 Principe de persistance orthogonale

Le principe de persistance orthogonale est apparu à la fin des années 1970, dans le domaine des langages de programmation. Il proclame que toute donnée doit être habilitée à persister pendant un délai aussi long qu’il est utile, et que la méthode d’accès à une donnée doit être indépendante de la nature de sa persistance. Dans les systèmes classiques il en va tout autrement : les données volatiles en mémoire centrale sont invoquées par leur nom, les données persistantes sur mémoire externe sont accueillies en mémoire centrale comme le résultat de l’invocation d’une commande d’entrée-sortie. Un système persistant reléguera ces différences techniques dans les couches basses du système et présentera une interface uniforme d’accès aux données.

Les tentatives pour implanter la persistance orthogonale dans les langages ou les bases de données utilisées dans le contexte de systèmes d’exploitation classique comme Unix n’ont pas donné de très bons résultats, parce que le problème de l’accès aux données est trop fondamental pour être résolu de façon totalement différente par un programme d’application d’une part, par son environnement d’autre part. L’auteur de système persistant est amené à gérer la mémoire de manière parfois subtile et complexe, or dans un système classique tel Unix c’est le noyau qui décide des pages de mémoire virtuelle à garder en mémoire volatile ou à reléguer en mémoire auxiliaire, ce qui aboutit à des contradictions.

 Fiasco des bases de données à objets

L’exemple d’un tel échec est fourni par les bases de données à objets qui avaient soulevé un grand intérêt dans les années 1990 avec leur programme très séduisant, qui consistait à stocker les données sous la même forme en mémoire centrale pendant leur vie « active » et en mémoire auxiliaire pendant leur vie « latente ». Le revers de la médaille était que le format des données dans les bases dépendait alors du langage de programmation et du matériel utilisés : une base de données créée par un programme C++ n’était pas accessible à un programme Java, et si elle avait été créée sur une machine Sun à processeur 32 bits elle n’était pas accessible à un programme exécuté par une machine à processeur Alpha 64 bits, sauf à passer par des programmes de conversion de données qui font perdre tout l’avantage attendu. De surcroît la mémoire persistante était réalisée à base de systèmes de fichiers classiques, totalement inadaptés à une telle fonction. Et enfin il résultait de tout ceci une programmation laborieuse et des performances le plus souvent médiocres. Si je puis mentionner mes modestes expériences personnelles de combat avec un Système de Gestion de Données Objet (SGDO) pourtant réputé très industriel (par opposition aux logiciels libres développés par des chercheurs dans les universités), je ne puis me déprendre d’une impression de bricolage : la trace du système révélait que le SGDO passait le plus clair de son temps à balayer en long, en large et en travers des arborescences de répertoire pour y chercher des données qui étaient tout à fait ailleurs, et à recopier un nombre incalculable de fois la même (grande) portion de fichier en mémoire (au moyen de l’appel système mmap pour les connaisseurs [1]). Il n’y avait bien sûr pour un utilisateur naïf aucun moyen simple d’extraire des données de la base : la seule façon était d’écrire du code C++ bare metal, exercice particulièrement punitif ou pervers. Alors que même si l’on peut reprocher aux Systèmes de Gestion de Bases de Données Relationnelles (SGBDR) tels que PostgreSQL, Oracle ou MySQL une certaine rigidité, ils offrent au moins une méthode d’accès aux données relativement normalisée et relativement simple avec le langage SQL.

La leçon à en tirer semble être qu’il vaut mieux implanter les fonctions de persistance au niveau du système d’exploitation, quitte à ce que ce soit une couche d’interface ajoutée à un système classique sous-jacent. L’implantation de la persistance dans le système garantit une uniformité de vision pour tous les programmes d’application, évite la redondance de fonctions qui alourdissait tellement les bases de données à objets, bref elle assure la cohérence de la sémantique d’accès aux données. C’était ce que faisait à sa façon Pick, et que fait encore en 2014 le système de l’AS400, rebaptisé System i5.

 Projets de recherche

Les principaux projets de recherche en persistance à l’orée des années 2000 étaient les suivants :

- Le projet MONADS a démarré en 1976 à l’Université Monash (Australie). L’abstraction de base est le segment, à la Multics : persistance à gros grain.

- Clouds vient du Georgia Institute of Technology (1988). Les abstractions sont l’objet et l’activité (thread). Repose sur le micro-noyau Ra.

- Eumel et ses successeurs L3 et L4 ont leur origine en 1977 à l’Université de Bielefeld, puis au GMD (Gesellschaft für Mathematik und Datenverarbeitung, équivalent allemand d’Inria), et sont principalement l’œuvre du regretté Jochen Liedtke. Eumel fut le premier système à persistance orthogonale. Il s’agit aussi d’un système à micro-noyau (voir là).

- Grasshoper est un système à persistance orthogonale développé à l’Université de Saint Andrews, Écosse. Les entités persistantes sont des containers, des loci et des capabilities. Dans les systèmes classiques la notion d’espace-adresse est inextricablement mêlée à celle de processus. Les containers et les loci sont des entités analogues mais mieux distinguées (pardon : orthogonales), qui ont vocation à persister. Le noyau du système lui-même est persistant (il y a quand même toujours une partie non persistante, ne serait-ce que pour le boot).

- Charm est le successeur de Grasshoper. Le noyau de Charm n’exporte aucune abstraction pour le support de la persistance, mais uniquement des domaines de protection capable de communiquer avec le noyau.

Charm appartient à une nouvelle tendance parmi les systèmes d’exploitation : au lieu de cacher le matériel derrière des abstractions, il l’expose afin que les stratégies de gestion des ressources soient implémentées en « mode utilisateur ». Cela suppose des dispositions favorables de l’architecture matérielle.

Le motif est de séparer :

les règles de gestion des ressources de bas niveau ;

des mécanismes qui les implémentent.

L’auteur du système de haut niveau est libre d’implémenter règles et mécanismes par une bibliothèque.

Incidemment, on peut signaler qu’il existait un système d’exploitation universellement répandu et qui possédait beaucoup de caractéristiques « persistantes » : PalmOS, qui anime les ordinateurs de poche PalmPilot et Handspring Visor. Chaque programme reste en mémoire dans l’état où l’utilisateur l’abandonne, et où il peut le retrouver lorsqu’il rallume l’engin. Il n’y a pas de vrai système de fichiers. C’est assez surprenant quand on est habitué aux ordinateurs classiques. Les smartphones contemporains ont une interface moins cohérente de ce point de vue.

 Reprise sur point de contrôle

La notion de reprise sur point de contrôle (checkpoint-restart) est bien sûr au cœur de tous ces systèmes. Le problème à résoudre est le suivant : si un programme est interrompu inopinément en cours de traitement, comment reprendre son exécution sans avoir à la recommencer depuis le début ? Idéalement, il faudrait reprendre au point où l’on s’était arrêté, mais il est raisonnablement acceptable de repartir d’un point en amont pas trop éloigné. La difficulté principale réside bien sûr dans la restauration de ce que nous avons appelé le vecteur d’état du programme : valeur des variables, et contenu des fichiers.

Ce problème n’est pas propre aux systèmes persistants, et il a déjà été abordé et résolu. Dès les années 60 l’OS 360 offrait une possibilité de checkpoint-restart pour les programmes utilisateur. Cette possibilité consistait à enregistrer périodiquement sur disque une copie de la mémoire et un relevé de l’état des fichiers ouverts. En cas d’incident le programme repartait automatiquement du dernier point de contrôle. Ce mécanisme entraînait une consommation d’espace disque considérable pour l’époque et surtout une organisation rigoureuse du lancement et de l’exécution des chaînes de programmes, ce qui en restreignait l’usage.

Aujourd’hui une fonction analogue existe pour les ordinateurs portables : une combinaison de touches de commande permet de sauvegarder le contenu de la mémoire sur disque et de mettre l’ordinateur en veille, puis de le réactiver plus tard, ce qui permet par exemple de changer de batterie sans passer par la procédure d’arrêt du système et de redémarrage, elle-même grosse consommatrice de temps et d’électricité.

Les SGBD convenables offrent la possibilité de déclarer des transactions, c’est-à-dire de déclarer un ensemble d’opérations, par exemple une mise à jour complexe de la base, comme une méta-opération atomique. Conformément à l’étymologie une méta-opération atomique est insécable : soit toutes les opérations de la transaction sont accomplies correctement, soit elles sont toutes annulées. Ceci est destiné à éviter de laisser la base dans un état incohérent, voire inconnu. Les transactions sont généralement associées à un dispositif de roll in-roll out qui permet d’entériner une transaction (roll in) ou de ramener la base de données à l’état antérieur à la transaction (roll out).

Depuis les années 1980 sont apparus sur les systèmes en production, issus de la recherche, les systèmes de fichiers journalisés tels Andrew File System de l’Université Carnegie-Mellon, ADVFS dérivé du précédent dans les laboratoires Digital Equipment (DEC), JFS développé par IBM, XFS réalisé par Silicon Graphics (SGI), et plus récemment sous Linux Ext3fs et Reiserfs. Le principe de la journalisation est le suivant : avant toute opération de modification du système de fichiers par une opération d’entrée-sortie, on enregistre dans un fichier spécial (journal, en anglais log) la description de l’opération, et après l’opération on enregistre qu’elle s’est bien passée. Ainsi, après un incident qui aurait corrompu une partie du système de fichiers, il suffit de « rejouer » les opérations enregistrées dans le journal pour restituer un état cohérent, ce qui est infiniment plus sûr et plus rapide que de recourir à un logiciel de contrôle et de restauration de la cohérence interne du système de fichiers tels fsck sous Unix.

Avec les systèmes persistants, le problème est simplifié autant que généralisé. Un système persistant digne de ce nom n’a ni fichiers ni a fortiori système de fichiers. Il est de ce fait indispensable de garantir à tout prix le maintien de la cohérence du contenu de la mémoire virtuelle, seul lieu de conservation des données, et ce quel que soit l’incident, y compris une coupure de l’alimentation électrique. Les systèmes persistants disposent donc d’un système d’enregistrement de points de contrôle, qui permet de sauvegarder périodiquement le contenu de la mémoire, et de reprise sur incident à partir du dernier point de contrôle. Ce mécanisme n’est pas une option comme dans les environnements classiques, mais un fondement du système. Une conséquence amusante de ce type de fonctionnement, qui surprit les auteurs des premiers systèmes persistants, c’est qu’un programme d’application ne peut pas être informé d’un arrêt du système, puisqu’il est reparti automatiquement comme si de rien n’était. On ne sait donc pas qu’il y a eu une coupure de courant dans la nuit, sauf à consulter les journaux.

Notes :

[1mmap est un appel système qui réalise la projection d’un fichier en mémoire, c’est-à-dire son chargement intégral, ce qui permet ensuite d’y accéder au prix d’un accès en mémoire. C’est judicieux si l’on doit effectuer de façon intensive des accès à tout le fichier, mais si l’on veut simplement accéder à une donnée c’est (peut-être) un marteau-pilon pour écraser une mouche. Mais il faut lire ci-dessous la critique de cette analyse par Robert Ehrlich, dans les commentaires de lecteurs. Robert a sûrement raison, il connaît ces choses-là parfaitement.

Forum
Répondre à cet article
Mémoire virtuelle, persistance : faut-il des fichiers ?
Claude Ringer - le 5 avril 2014

Mmm j’admets ne pas avoir tout saisi et survolé ce texte très dense que je relirai, néanmoins déjà une question me vient ; vous écrivez "or dans un système classique tel Unix c’est le noyau qui décide des pages de mémoire virtuelle à garder en mémoire volatile ou à reléguer en mémoire auxiliaire, ce qui aboutit à des contradictions"

Mais je ne comprends pas comment il pourrait en être autrement quel que soit le type de gestion de la mémoire, puisque quel que soit l’OS qui est mis en place un algorithme définit dans le noyau au niveau de l’ordonnanceur ("scheduler") devra gérer l’utilisation de la mémoire par les processus non ?

A moins d’imaginer que le "hardware s’adapte lui même" (et je ne vois pas trop comment ce serait possible).
Merci pour ces textes très intéressants.

Mémoire virtuelle, persistance : faut-il des fichiers ?
Laurent Bloch - le 5 avril 2014

Justement, c’est bien là la question : comme l’allocation de mémoire est décidée en dernier recours par l’OS, toute tentative d’un logiciel, fût-il SGBD, pour avoir sa propre stratégie sera au mieux redondante avec l’OS, et sans doute contrariante. C’est bien pourquoi la gestion de la persistance doit être effectuée au niveau de l’OS, du noyau.

Mémoire virtuelle, persistance : faut-il des fichiers ?
Claude Ringer - le 5 avril 2014

Oui, l’OS doit gérer un ensemble de processus qui demandent des accès simultanés aux ressources. C’est pour çà que Linux est une excellente solution (tous les OS open source en fait) puisqu’on peut réécrire le code source du noyau et par exemple l’optimiser pour la gestion d’un processus en particulier comme un SGBD. Pour le "NoSQL", il semble que le gros intérêt soit de ne pas avoir à gérer toutes les relations entre les tables (comme c’est le cas en SQL avec les multiples JOIN) et donc la grande flexibilité, ce qui est intéressant quand on gère de grandes quantités de données avec beaucoup de modifications. On pourra répondre que les INDEX sont là pour éviter les temps de réponses longs dans les SGBD.

Bien cordialement.

Mémoire virtuelle, persistance : faut-il des fichiers ?
Robert Ehrlich - le 25 mars 2014

Je déterre un peu ce sujet pour quelques remarques sur les systèmes de fichiers journalisés, que je voulais faire tout de suite, mais d’autres occupations ...
I l y a une chose que je n’ai jamais comprise dans ces systèmes journalisés : comment peut-on assurer de revenir à l’état avant ou après transaction sans sauver dans le journal l’un de ces deux états, ce qui fait doubler les opérations d’écriture, donc divise par 2 (ou plus par mise en défaut des optimisations positionnelles) le débit en écriture ?

Une alternative qui me semble préférable et dont on entend peu parler est celle développée par McKusick et son équipe pour le système de fichiers FFS de BSD baptisée "soft update", encore appelée "ordered write", qui consiste à ordonner les écritures de façon à ce que le système de fichiers reste à tout moment dans un éat cohérent, si ce n’est peut être une incohérence entre la description de l’espace libre et ce qui l’est réellement, toujours dans le sens sans danger (ce qui est occupé n’est jamais décrit comme libre, le contraire peut arriver). On perd là aussi un peu en débit puisque l’ordre imposé empêche parfois de réordonner pour faire de l’optimisation positionnelle, et aussi de retarder une écriture en espérant que la copie mémoire du bloc modifié le sera à nouveau prochainement, ce qui regroupe pluieurs écriture en une seule (ce n’est pas interdit, mais les dépendances d’ordre peuvent forcer une écriture parce qu’on a par ailleurs décidé d’en effectuer une autre, qu’on n’aurait pas faite sans cette dépendance), mais on ne rajoute pas d’écriture, et il n’y a pas de journal à rejouer après un crash, il faut seulement faire tourner une version simplifiée de fsck en arrière-plan pour éventuellement récupérer l’espace perdu.

Mémoire virtuelle, persistance : faut-il des fichiers ?
Robert Ehrlich - le 11 mars 2014

Je ne suis pas du tout d’accord avec la description de l’appel-système "mmap". La vision de la totalité du fichier en mémoire qu’il permet passe par le système normal de gestion de la mémoire virtuelle et donc ne devrait, s’il est correctement programmé, ne rien charger du tout du fichier en mémoire mais se contenter d’initialiser quelques descripteurs de pages ou segments du plus haut niveau pour indiquer que ces pages sont absentes de la mémoire centrale et où il faut aller les chercher si le programme y accède. Si tout le fichier arrive en mémoire c’est que le programme l’a demandé, ou du moins a au moins demandé quelque chose dans chacune de ses pages.

Par ailleurs pour moi la différence entre mémoire et fichier n’est pas dans la persistence ou non mais dans le mode d’accès. L’accès à la mémoire se fait par des addresses, l’accès à un fichier se fait par un nom le plus souvent reflètant une structure (quasi) arborescente (le quasi est pour les liens durs Unix qui font que plusieurs chemins peuvent désigner la même chose). D’ailleurs les deux visions peuvent s’échanger : /dev/mem, /dev/kmem et ramdisks permetent de voir la mémoire comme des fichiers, mmap permet de voir un fichier comme de la mémoire. Une même collection de données peut être vue comme fichiers de plusieurs façons différentes : tout un disque ou une partition comme un seul fichier /dev/dsk/xxx ou comme une arborescence montée. Sous Windows leur infâme "base de registre" se trouve répartie dans X fichiers différents de noms NTUSER.DAT ou autres, mais l’émulation cygwin permet de voir ça comme une arborescence standard sous /proc/registry et d’y utiliser les utilitaires standard (find, grep, ...).

Mémoire virtuelle, persistance : faut-il des fichiers ?
Alexandre SALZMANN - le 5 mars 2014

bonjour Laurent,

Pour enrichir le sujet, je voudrais savoir ce que tu penses des nouveaux SGBD NoSQL :
http://fr.wikipedia.org/wiki/NoSQL ?

http://linuxfr.org/news/petit-etat-des-lieux-du-nosql

Amitiés

Alexandre

SGBD NoSQL ?
Laurent Bloch - le 5 mars 2014

Bonjour Alexandre,

Je n’ai pas assez pratiqué ces nouveaux SGBD NoSQL pour avoir une opinion valable.

Ce que je sais, c’est qu’après avoir beaucoup détesté les SGBD SQL, je les ai mieux compris en lisant les articles de Stonebraker (concepteur principal d’Ingres et de PostgreSQL), et j’ai fini par saisir ce qui faisait leur force : ne pas être de vrais langages de programmation. Aussi les extensions récentes me laissent-elles perplexe : c’est comme les compilateurs des années 1980, qui se vantaient de leurs extensions merveilleuses par rapport à la norme, lesquelles détruisaient tout espoir de portabilité.



pucePlan du site puceContact puceMentions légales puceEspace rédacteurs puce

RSS

2004-2017 © Site WWW de Laurent Bloch - Tous droits réservés
Site réalisé sous SPIP
avec le squelette ESCAL-V3
Version : 3.86.17