239 lines
14 KiB
Markdown
239 lines
14 KiB
Markdown
Que pourrions-nous faire de nos dix doigts ?
|
||
Une fois qu'on voudra se lancer dans du code, quelles sont nos possibilités ?
|
||
|
||
Tout ce qui est écrit dans ce fichier parle de ce qu'on fera après avoir lu le livre (en entier ou pas) ou vu les vidéos.
|
||
De même, l'étude des différents systèmes est intéressante peu importe ce qu'on décide de faire par ailleurs.
|
||
Par exemple, Plan9 est conceptuellement le système le plus intéressant et devrait être étudié.
|
||
On plongera occasionnellement dans la doc voire le code (sans forcément y passer trop de temps non plus).
|
||
|
||
# Idées pour la suite
|
||
|
||
1. Se contenter de xv6 pour apprendre le dév bas niveau et s'arrêter là.
|
||
Éventuellement jouer à faire quelques optimisations, ajouter des syscalls, etc.
|
||
Cette option permet d'apprendre sans trop forcer.
|
||
|
||
2. Contribuer à un projet existant, utilisé au-delà de l'aspect pédagogique.
|
||
Cette option peut être complémentaire à une autre (car elle nécessite peu d'engagement selon la tâche à accomplir).
|
||
C'est l'option qui est la plus sociale, notre travail est directement utile à d'autres.
|
||
|
||
3. Tenter de conquérir le monde.
|
||
|
||
# Contribution à un projet existant
|
||
|
||
L'idée serait de ne pas développer tout un OS, mais seulement contribuer à un projet.
|
||
Soit de niche : Minix, DuskOS (c'est du Forth), Plan9, Fuchsia, L4, etc.
|
||
Soit un poil plus utilisé : un BSD, un OS embarqué type Zephyr, Linux, etc.
|
||
|
||
Que faire avec ces systèmes ? Des pistes :
|
||
|
||
- Minix : ajouter des parties manquantes pour le rendre plus proche des fonctionnalités d'un OS moderne.
|
||
Il manque actuellement quelques fonctionnalités assez majeures.
|
||
Exemple : pas de multicœur, USB incomplet (de mémoire), peu de prise en charge matérielle, etc.
|
||
|
||
- Sur OpenBSD :
|
||
|
||
- Une sortie audio HDMI.
|
||
- Du bluetooth.
|
||
- Plus conséquent : un système de fichiers avec un journal (type HAMMER2).
|
||
Si j'en crois des gens sur reddit, c'est un gros travail à cause du VFS qui est un peu simpliste pour un FS sophistiqué.
|
||
|
||
- Plan9 et ses dérivés : améliorer la prise en charge du matériel.
|
||
|
||
- Linux : pledge et unveil.
|
||
Ce sont deux appels systèmes pour restreindre les syscalls et l'accès au système de fichiers sur OpenBSD et ça manque sur Linux.
|
||
Avec ces deux appels système, on rend obsolète la plupart des outils comme AppArmor et selinux, qui sont compliqués à utiliser.
|
||
La complexité de ces outils les rend confidentiels, et les programmes écrits sous Linux ne sont donc pas protégés correctement.
|
||
|
||
# Conquête du monde (en toute humilité)
|
||
|
||
Cette dernière option implique de développer un OS qui n'a encore jamais été fait, pour se lancer un défi.
|
||
Ma proposition serait de faire un OS à micro-noyau minimaliste.
|
||
|
||
Intéressant et divertissant, mais le projet est plus complexe que le reste.
|
||
On en apprendra beaucoup tout en ayant un OS qui pourrait intéresser des gens.
|
||
|
||
Concernant les fonctionnalités qui m'intéressent bien :
|
||
|
||
- Une architecture à micro-noyau
|
||
|
||
- Écriture de pilotes en mode utilisateur.
|
||
Ça se fait déjà sur certains systèmes (comme NetBSD, Fuchsia, etc.), donc ce n'est pas insurmontable.
|
||
La partie (un peu) complexe est de rendre cela rapide, mais ça se fait (voir le papier skybridge-eurosys19 pour un point de départ).
|
||
|
||
Par ailleurs, NetBSD a le concept de "rump kernel", ses pilotes peuvent être inclut dans le noyau NetBSD ou en espace utilisateur (voire sans OS du tout).
|
||
Il serait donc possible de récupérer leurs pilotes assez rapidement.
|
||
|
||
- Mise à jour en live du système, sans redémarrage.
|
||
Une fois que le noyau dans un état stable et qu'il offre les services de base, il ne reçoit plus beaucoup de mises à jour.
|
||
L'ajout de nouveaux pilotes, de nouveaux systèmes de fichiers, la gestion des utilisateurs… peuvent se faire sans toucher au noyau, donc sans (forcément) redémarrer le système.
|
||
|
||
- Un développement unifié de tout le système façon BSD.
|
||
C'est le contraire du développement chaotique côté Linux où tous les programmes sont écrits différemment.
|
||
|
||
- Reprendre masse de concepts de Plan9.
|
||
En particulier, voir le concept de « tout est fichier » et comment cela s'intègre pour des actions complexes sur des périphériques.
|
||
De même, le protocole 9P ou encore la gestion du partage de ressources (namespace) des processus méritent de l'attention.
|
||
|
||
- Reprendre quelques concepts de DuskOS.
|
||
En particulier, DuskOS implémente HAL, une couche d'abstration pour générer des instructions binaires.
|
||
Cette abstraction fournit une API pour que des compilateurs puissent s'y greffer et ne pas eux-même gérer la dernière étape de compilation.
|
||
Le développeur principal a fait un compilateur C et Scheme avec cette abstraction.
|
||
Cette factorisation de la dernière étape des compilateurs rend le code plus concis.
|
||
|
||
- Rendre notre système attractif.
|
||
Plusieurs choses à faire pour cela, dans n'importe quel ordre.
|
||
- Viser une plateforme RISC-V puis amd64.
|
||
Pour faire tourner notre code rapidement sur des machines physiques.
|
||
|
||
- Se rendre compatible virtio.
|
||
Pour avoir de très bonnes perfs dans une machine virtuelle (système de fichiers et réseau).
|
||
|
||
- Ajouter une couche de compatibilité avec les appels système C (et donc les applications BSD et Linux).
|
||
Pour porter des outils et en faire beaucoup plus rapidement un système utilisable « pour de vrai ».
|
||
|
||
Il faut reprendre les bonnes idées.
|
||
Il faut lire le code des systèmes actuels pour apprendre et s'inspirer.
|
||
|
||
À l'inverse, les bootloaders qui existent déjà font bien le travail, en refaire un serait une perte de temps, je pense.
|
||
|
||
# Liens qui pourraient s'avérer importants pour la suite
|
||
|
||
- Running Scheme On Bare Metal (Experience Report):
|
||
https://doc.lagout.org/programmation/Lisp/Scheme/An%20Introduction%20to%20Scheme%20and%20its%20Implementation.pdf
|
||
|
||
- Un papier qui indique comment faire des micro-noyaux rapides :
|
||
https://ipads.se.sjtu.edu.cn/_media/publications/skybridge-eurosys19.pdf
|
||
|
||
L'idée générale est de limiter au maximum les changements de contexte.
|
||
Cela se fait sans mal sur x86 grâce à des instructions spécialisées.
|
||
Certains micro-noyaux sont certes plus lents sans SkyBridge, mais gardent des performances acceptables.
|
||
|
||
Ce papier peut être vu comme un point de départ dans le monde de la recherche dans les micro-noyaux et les IPC.
|
||
|
||
- Introduction à x86 par les gens qui font ffmpeg :
|
||
https://github.com/FFmpeg/asm-lessons
|
||
|
||
- The limine bootloader, pour éviter de réinventer la roue pour un truc aussi peu important qu'un bootloader :
|
||
https://limine-bootloader.org/
|
||
En étant un peu mesquin, on pourrait dire que tout nouveau système est plus ou moins voué à l'oubli et ne sert à rien.
|
||
Sauf qu'un nouveau fonctionnement, plus intéressant conceptuellement et techniquement, peut avoir une certaine valeur.
|
||
Mais c'est pas le cas pour un bootloader, ceux qui existent (dont GRUB, Limine, etc.) font bien le job, aucun intérêt.
|
||
Une fois la machine démarrée, le bootloader n'existe plus, il n'a plus aucune incidence sur le déroulé des événements.
|
||
|
||
- LCC, LISP C COMPILER, une bibliothèque LISP qui permet d'écrire du code C avec une syntaxe LISP.
|
||
https://github.com/saman-pasha/LCC
|
||
|
||
- CRUNCH, une sorte de LCC mais en Chicken Scheme.
|
||
https://wiki.call-cc.org/eggref/6/crunch
|
||
Peut-être plus complexe et moins adapté à ce qu'on voudrait faire que LCC, mais méritait une mention.
|
||
Ici il y a de la vérification de types et autres joyeusetés.
|
||
|
||
- Le concept de "rump kernel" est de faire tourner des pilotes soit dans un noyau monolithique, en espace utilisateur ou sans système du tout.
|
||
https://www.usenix.org/system/files/login/articles/login_1410_03_kantee.pdf
|
||
Concept utilisé dans NetBSD pour simplifier l'écriture et la correction rapide de pilotes.
|
||
Par la même occasion, cela permet d'avoir une très haute portabilité des pilotes sur d'autres systèmes.
|
||
|
||
# NOTES EN VRAC SUR FUCHSIA
|
||
|
||
Le noyau Zircon (de Fuchsia, OS de Google), en quelques mots :
|
||
|
||
- Reprend quelques concepts de Plan9, par exemple le fait qu'un processus enfant n'a pas accès à tout par défaut, seulement à ce que le parent lui donne.
|
||
Un processus est nommé « composant » dans la terminologie de Fuchsia, car le concept s'éloigne un peu de celui de processus.
|
||
Un processus dans le monde d'Unix est fortement corrélé à l'utilisateur qui le lance, et l'utilisateur est le centre de l'attention en ce qui concerne la sécurité.
|
||
Si un utilisateur a les droits sur un répertoire, ses processus peuvent y accéder.
|
||
Dans Fuchsia, les processus ont eux-mêmes des droits particuliers (« capabilities ») et reçoivent un sous-ensemble des droits de l'utilisateur.
|
||
|
||
NOTE : à mon faible niveau de connaissances sur Plan9, ça ressemble quand même fortement à ce que fait Google dans Fuchsia.
|
||
Plan9 ne se complexifie pas la vie autant que Fuchsia puisque pour Plan9 tout est fichier.
|
||
Plan9 conserve donc la palme de l'OS le plus simple (et de très loin).
|
||
|
||
- Tout n'est pas « fichiers » mais plutôt « handles » c-à-d un objet qui représente ce qu'on peut faire avec.
|
||
En gros, ça va plus loin que simplement ouvrir/fermer/lire/écrire.
|
||
D'un point de vue de l'utilisateur, c'est bien entendu une petite complexité supplémentaire.
|
||
|
||
- Utilise un mécanisme d'IPC où tous les messages ont une signature précise.
|
||
La structure des messages que les processus s'échangent est finement définie, via le langage FIDL.
|
||
Cela remplace une partie des appels système Unix par des échanges de messages structurés (pas de simples tableaux d'octets).
|
||
|
||
- Vidéo youtube qui présente certains aspects de Fuchsia :
|
||
"An IPC Language For The Whole Operating System" by Ian McKellar (Strange Loop 2022)
|
||
https://www.youtube.com/watch?v=ApHpmA1k73k
|
||
|
||
NOTE : dans les commentaires, il y a un gars qui a visiblement bossé sur L4.
|
||
Il se dit content que finalement quelqu'un ait regardé la doc de L4.
|
||
Je suppose que L4 implique également des capabilities, handles, une sorte de FIDL, etc.
|
||
En gros, Fuchsia n'a rien inventé.
|
||
|
||
# BONUS pour notre micro-noyau
|
||
|
||
Attention, ici on est là pour obtenir tous les points de style peu importe la quantité de jus de cerveau à cramer.
|
||
|
||
- Avoir le code noyau en Scheme.
|
||
(Ou du Forth, mais dans ce cas ce sera sans doute avec DuskOS car c'est déjà là et activement développé.)
|
||
|
||
(Le Scheme peut arriver après une première implémentation en C.)
|
||
|
||
Le Scheme est très intéressant de par sa simplicité (S-expressions) et son extensibilité (macros).
|
||
Le langage peut évoluer en DSL pour au final se débarasser entièrement de tout autre langage dans les sources.
|
||
|
||
Prenons un exemple.
|
||
Il est possible d'écrire un programme qui génère du C.
|
||
/!\ Je ne parle pas de compiler un programme, mais d'écrire un programme qui écrit du C.
|
||
Par exemple, LCC est une sorte de Lisp pour écrire du C : https://github.com/saman-pasha/LCC
|
||
On pourrait prendre LCC puis, plus tard si ça nous dit, faire notre version qui irait un peu plus loin.
|
||
Notre version pourrait écrire du C pour profiter des optimisations des compilateurs C, puis dans un second temps de l'assembleur pour éviter toute dépendance au C.
|
||
Les macros Scheme permettent de créer des DSL facilement, on pourrait par exemple en faire un pour générer à la fois du C, des includes automatiques, un fichier d'en-tête, un makefile et des instructions au linker.
|
||
|
||
Inconvénients :
|
||
|
||
- Étape supplémentaire.
|
||
Au lieu d'écrire du code C, on écrit du Scheme qui écrit du C.
|
||
Cela peut introduire des erreurs au moins en théorie, en pratique c'est plus discutable.
|
||
|
||
- Du Scheme sans être du Scheme.
|
||
Aucun environnement d'introspection (habituel avec Scheme) n'est présent à l'exécution.
|
||
On ne gagne (ni ne perd) rien à l'exécution par rapport à du code C.
|
||
Le code aura la syntaxe Scheme et les macros sont dispos à la compilation, pas après.
|
||
|
||
Avantages :
|
||
|
||
- Code plus simple qu'en C et donc plus lisible.
|
||
Certains pièges du C sont évités.
|
||
Pas besoin de jouer avec le préprocesseur C et sa syntaxe inélégante.
|
||
|
||
- Le code noyau profite entièrement de l'environnement du langage hôte.
|
||
On pourrait ajouter des vérifications de type si on le souhaite (le code est simple donc ce n'est pas une priorité).
|
||
|
||
- Performances optimales.
|
||
Le code noyau en Scheme n'est qu'une surcouche au C.
|
||
Le noyau ne continent que le code dont il a besoin.
|
||
Dans un second temps, notre bibliothèque pourrait même générer directement de l'assembleur.
|
||
|
||
- Ce principe pourrait être réutilisé dans du code beaucoup plus complexe, comme les pilotes des périphériques.
|
||
|
||
Le code dont nous avons besoin pour un noyau est finalement limité en terme d'instructions différentes.
|
||
Les actions d'un noyau se limitent à peu de choses.
|
||
- Des instructions arithmétiques simples (+ - / *) sur des entiers de différentes tailles.
|
||
- Beaucoup plus rarement, quelques opérations sur des nombres flottants.
|
||
- Manipuler la mémoire via des instructions rudimentaires.
|
||
(Instructions à partir desquels on construit des fonctions plus complètes par la suite.)
|
||
- Quelques instructions processeur spécialisées qui ne font pas partie du standard C.
|
||
(Et donc, qu'il faut de toute façon écrire à la main dans le code.)
|
||
- Des algorithmes simples nécessitant des structures de données simples.
|
||
Et dont il faudra gérer correctement l'alignement en mémoire, rien d'insurmontable.
|
||
Le C a notamment des sommes de types (struct) et des unions (structures ou types imbriqués en mémoire).
|
||
|
||
- Rendre ce code auto-hébergé (self-hosted).
|
||
Ne plus dépendre du C, puis d'un assembleur, puis d'un compilateur LISP/Scheme autre que le nôtre.
|
||
|
||
- Un interpréteur pourra éventuellement être implémenté dans un second temps.
|
||
Stade ultime de l'auto-hébergement, on n'a même plus besoin d'un OS hôte.
|
||
L'idée serait d'améliorer le noyau pendant qu'il tourne, permettre des opérations à cœur ouvert.
|
||
L'implémentation peut fortement s'inspirer des implémentations de Forth (qui font ça depuis toujours).
|
||
|
||
- L'interpréteur sera un compilateur interactif : on passe des expressions à compiler, il les ajoute au code noyau.
|
||
Les fonctions sont compilées, les macros sont gardées pour être réutilisées plus tard, c'est pas bien dur.
|
||
|
||
- Cet interpréteur n'implémentera que ce qui est nécessaire pour un noyau, inutile de dégainer R7RS.
|
||
Un noyau n'a pas besoin d'optimisations poussées.
|
||
De même, le ramasse-miettes peut être simpliste, un micro-noyau effectue peu d'actions.
|