A la lecture de ce livre, on découvre qu’une grande partie de l’informatique moderne a été créée et pensée dans les laboratoires Bell, à partir du milieu des années 1960. Une des missions du Bell Labs était de développer une compréhension mathématique du fonctionnement des communications. Le résultat le plus important aura été la théorie de l’information de Claude Shannon (mais à côté de quoi, on trouvait également des propositions de résolution à des problèmes de partionnement de graphs [^1]).
Ce qui est drôle (d’une certaine manière et avec un humour particulier), c’est que beaucoup de grands de l’informatique moderne ont travaillé ou approché le Bell Labs:
- Ken Thompson, qui participe à la création d’Unix, mais également aux langages B et Go
- Dennis Ritchie, créateur du langage C et dont la thèse de PhD était à propos des subrecursive hierarchies of functions (donc, pas le dernier de la classe).
- Joe Ossanna (qui participe à l’élaboration de Multics)
- … ou Andrew Tannenbaum dont certains livres sur les réseaux restent encore des références aujourd’hui.
Un des ancêtres de Unix était le CTSS (Compatible Time-Sharing System), qui pouvait sans doute être considéré comme l’un des plus innovants de l’époque. Il avait été créé au MIT en 1964, à l’ère du “batch processing”: les développeurs alimentait des cartes perforées, les donnaient à un opérateur et attendaient le résultat (qui pouvait arriver quelques heures, voire jours, plus tard). A l’opposé de ceci, les développeurs qui utilisaient CTSS dsposaient d’un terminal(-like), connecté directement ou par ligne téléphonique à un seul (gros) ordinateur (type IBM 7094).
CTSS était tellement performant et innovant que des chercheurs du MIT décidèrent de faire encore mieux, et commencèrent à développer un nouveau système appelé Multics - the Multiplexed Information and Computing Service, en collaboration avec le MIT et General Electrics. Multics a cependant été victime du second system effect:
*After a success (like *CTSS*), it's tempting to try to create a new system that fixes all the remaining problems with the original while adding everybody's favorite new features too.
The result is often a system that's too complicated.
--- page 31 - CTSS and Multics
Multics eut finalement sa release, et les personnes qui travaillaient dessus ont dû trouver autre chose à faire [^2]. C’est à ce moment-là que Ken Thompson a pu mettre la main sur un DEC PDP-7, déjà dépassé en 1969 (seulement 16KB de RAM, et fonctionnant avec des mots de 18 bits, mais avec un chouette affichage graphique). Un des soucis du PDP-7 était qu’il était équipé d’un disque à chargement vertical dont la vitesse de lecture était trop rapide pour l’ordinateur qui y était connecté. Ken Thompson écrivit un ordonnanceur pour maximiser l’écriture de données vers n’importe quel périphérique de sortie. Pour tester son algorithme, il avait besoin d’un programme permettant de charger des données en quantité. Il réalise à ce moment-là qu’il lui suffit de développer un éditeur, un assembleur et une surcouche au noyau pour avoir un système d’exploitation fonctionnel.
[^1] Etant donné un ensemble de noeuds connectés par des arêtes, trouvez une manière de séparer/regrouper les noeuds en deux groupes de taille égale, de manière à ce que le nombre d’arêtes qui connecte un groupe à l’autre soit le plus faible possible.
[^2] Bell Labs était organisé de manière à ce que chaque employé soit plus ou moins orienté dans ses recherches, mais ils restaient malgré tout extrêmement libres dans leur travail. Cf. page 16-17: This was standard practice: people were introduced to other people, encouraged to wander around, and left to find their own research topics and collaborators.
Unix #
Les composants principaux de l’élégance d’Unix sont les suivants dont la conception est toujours d’actualité (et ont souvent été copiés, voire émulés). Ceci concerne:
- Le système de fichiers
- Les appels systèmes
- Le shell
- Les pipes
- Les expressions rationnelles (et
grep
) - Le langage
C
- Les outils complémentaires.
Système de fichiers #
Le système de fichiers d’Unix est tiré de l’expérience que Ken Thompson a acquise en développant celui de Multics. La conception de ce système de fichiers est toujours d’actualité, et a été souvent copiée/émulée par d’autres systèmes. Elle permet notamment de ne pas avoir de limites de profondeur des noeuds et considère tout élément comme un inode, qu’il s’agisse d’un dossier ou d’un fichier. Pour simplifier, le système de fichier traite uniquement de bytes, et se fiche un peu de savoir qu’il s’agit d’un montage réseau, d’un disque mécanique ou d’une bande magnétique.
C’est également à cette implémentation-ci que l’on doit les chemins relatifs et fameux .
et ..
.
Appels systèmes #
Les appels systèmes sont des services exposés directement par le système d’exploitation [^3], et qui peuvent être appelés par les différents programmes qui tournent sur ce système. Ceci inclut la possibilité de démarrer ou d’arrêter d’autres programmes, de lire ou d’écrire des informations dans des fichiers, voire d’accéder à des périphériques ou à des connexions réseau.
A l’origine, Unix proposait seulement 30 appels systèmes, dont la moitié était en lien avec le système de fichiers (read
, open
, write
, close
, …).
Pour l’anecdote, la fonction creat
ne prenait pas de e
suite à un choix de Ken Thompson, choix qu’il regrette encore aujourd’hui:
Rob Pike once asked Ken Thompson what he would change if he were to do Unix over again.
His answer ?
"I'd spell `creat` with an `e`.
-- page 64.
Shell #
Le shell, qui est un programme qui appelle d’autres programmes, en autorisant une redirection des entrées et sorties (et en distinguant la sortie classique des erreurs). Un shell ne remplace aucun programmes compilés, mais font partie de la ceinture d’outils du développeur: si on se retrouve à répéter certaines actions plusieurs fois, il convient de prendre du recul et d’automatiser le maximum. Si un script shell venait à devenir lent, il pourrait toujours être réécrit dans un autre langage, plus adapté.
Un des gros plus du shell concerne la possibilité de rediriger des inputs/outputs, pour pouvoir lire un fichier en entrée plutôt que d’attendre une entrée au clavier, pour pouvoir écrire une sortie applicative vers un fichier, voire pour chaîner les deux.
Pipes #
Les pipes, qui permettent simplement de connecter la sortie d’un programme avec l’entrée d’un autre(plus élégant que ça, on ne fait pas). Le seul prérequis à ceci est, que chaque programme utilise du texte comme étant l’interface universelle:
This is the Unix philosophy: Write programs that do one thing and do it well. Write programs to work together. Write programs to handle text streams, because that is a universal interface.
-- Doug McIlroy - The Art of Unix Programming (2003)
L’élégance de la solution fait que it [was] super-trivial [to implement] given that the mechanisms for I/O redirection were already there. […] It is constructed from the very same commands used constantly in simplex fashion. The mental leap needed to see this possibility and to invent the notation is large indeed
Expressions rationnelles (et grep) #
Une “expression rationnelle” (ou régulière) est un mini-langage qui permet de décrire des modèles de texte.
“Doug McIlroy said ‘Wouldn’t if be great if we could look for things in files?”
L’implémentation des expressions rationnelles (et de leur prise en compte un peu partout au niveau système) est une histoire commune dans la construction d’Unix: on part d’un vrai problème communiqué par un utilisateur, on connait la théorie de manière approfondie et une ingénierie effective, une amélioration continue, une bonne expertise du groupe, un environnement ouvert et une culture d’expérimentation de nouvelles idées font que “ça juste marche”.
grep
vient en fait de la commande g/re/p
de l’éditeur ed
qui permettrait d’afficher toutes les lignes qui correspondraient à l’expression rationnelle re
dans la commande.
[^3] Personnellement, les termes de système d’exploitation me hérissent un chouia, et je proposerais bien à l’académie française de basculer vers système d’opération… Parce que certains systèmes nous laissent un peu penser que c’est l’utilisateur qui est exploité.
Le langage C #
Le langage C est un composant primordial du succès d’Unix. De son côté, Multics avait fait le pari d’utiliser un langage de haut-niveau: PL/1. PL/1 est une tentative de combinaison entre Fortran, COBOL et Algol. Le soucis touchait la chaîne de compilation, qui était trop lourde et trop compliquée pour la plupart des développeurs. Après la sortie de Multics, Doug McIlroy et Doug Eastwood créèrent un sous-ensemble de PL/1, BCPL (Basic Combined Programming Language), qui était beaucou plus simple que n’importe quel dialecte de PL/1, tout en étant accessible pour de la programmation système.
A côté de cela, Ken Thompson était persuadé qu’aucun système n’était complet sans Fortran.
Problème (pour le PDP-7): un compilateur Fortran était trop compliqué à porter, à cause des limitations matérielles.
C’est ainsi qu’il créa le langage B
, dont la syntaxe était beaucoup plus proche de BCPL que de Fortran.
Ainsi arriva le langage C
, dérivé de B
, mais auquel une gestion des types de données a été ajoutée (et qui correspondait aux types de données gérés par le PDP-11, successeur du PDP-7 au Bell Labs): bytes, entiers (deux bytes), nombres à virgule flottante (quatre ou huit bytes), …
Le langage C séparait également les notions d’entiers et de pointeurs (là où BCPL et B les traitaient de la même manière).
Jusqu’en 1973, Ken Thompson a essayé de réécrire le noyau en C, mais cela s’est avéré trop difficile, jusqu’à ce que Dennis Ritchie ajoute un mécanisme permettant de définir et de gérer des données imbriquées dans des structures (les struct
en C) au langage.
Les outils complémentaires #
On peut citer ici les outils type diff
, spell
, patch
, join
, … qui sont encore utilisés quotidiennement dans Git et dans beaucoup d’autres grands logiciels.
On verra également arriver Lex et Yacc, qui feront apparaitre de nouveaux langages et DSL, de même que Make, qui permettra l’automatisation de nombreuses tâches, ainsi que sed
et awk
qui compléteront la boite à outils du développeur moderne (sauf qu’ils datent tous de la fin des années ‘70).
On verra aussi tous les outils de préparation de documents (Eqn
, troff
, …), dont LaTeX de Don Knuth sera largement inspiré.
De manière plus générale, tous ces outils représentent très bien la philosophie Unix, qui était de réaliser une tâche (mais bien) et de considérer le texte et les chaînes de caractères comme des citoyens de première classe.
A ce stade, Unix aura évolué du PDP-7, au DEC VAX-11/780, en passant par le PDP-11, et en devenant à présent (presque) indépendamment du matériel sur lequel il sera déployé.
C’est aussi à ce moment que l’on verra apparaitre le Bourne Shell
, qui accompagne la plupart des grandes distributions actuelles (Debian, Ubuntu, Fedora, Arch, …) et qui venait avec ses propres instructions de programmation: if...then...else...fi
, do
, … tout en enrichissant les redirections d’I/O:
prog >file
: redirection destdout
vers un fichier etstderr
vers le terminalprog 2>err
: redirection destdout
vers le terminal etstderr
vers un fichierprog 1>file 2>err
:stdout
vers un fichier,stderr
vers un autreprog >file 2>&1
: fusion destdout
etstderr
vers le même fichier.
Licences #
La distribution d’Unix a aussi ouvert les contributions open-source; à la base, l’acquisition d’Unix était relativement chère pour une université ($20.000 de l’époque; $100 000 de la nôtre), mais ces licences octroyaient par défaut le code source, ainsi qu’une forme de support - Ken Thompson a ainsi passé une année sabatique à Berkeley en 1975 et 1976.
La disponibilité des sources permit à Berkeley de contribuer à la pile réseau, mais également à la création de nouvelles applications (vi
, C-Shell, l’interface des sockets, …).
Conclusions #
C’est top à lire, un peu high-level, un peu personnel, un peu autobiographique. Cela parle de langages (C, Pascal, PL/1, COBOL, …), d’architecture physique, de bits, de bytes, de mots, de RAM, de limitations matérielles, …
Unix a évidemment permis la création de dérivés (Linux, forcément), mais aussi BSD, de part son système de licences, les systèmes V (HP-UX, AIX, Solaris, …), et évidemment macOS.