Créer une micro-distribution Linux (2023)
(popovicu.com)- Explique étape par étape comment créer une « micro-distribution Linux » en compilant directement le noyau Linux et en construisant un espace utilisateur minimal
- Présente depuis les bases le rôle du noyau du système d’exploitation, les composants d’une distribution Linux et la relation entre le noyau et l’espace utilisateur
- Utilise l’architecture RISC-V (la machine
riscv64 virtde QEMU) comme exemple, mais les mêmes principes s’appliquent aussi à d’autres architectures comme x86 - Construit un environnement Linux minimal réellement exécutable, comprenant le processus
init, l’initramfset un shell simple écrit en Go - Présente enfin comment créer une micro-distribution réellement utile à l’aide du projet
u-root, et se conclut comme un guide d’introduction aidant à comprendre l’ensemble de l’architecture d’un système Linux
Qu’est-ce que le noyau d’un système d’exploitation ?
- Le noyau est le composant central du système d’exploitation chargé de gérer les ressources matérielles et de contrôler l’exécution des programmes
- Même dans un environnement à cœur unique, il fournit une fonction de gestion du multitâche donnant l’impression que plusieurs programmes s’exécutent simultanément
- Le noyau abstrait le contrôle des périphériques d’entrée/sortie afin que les applications n’aient pas à manipuler directement les adresses matérielles détaillées ou les valeurs des registres
- Par exemple, un programme demande simplement d’« écrire un message sur la sortie standard », et le noyau se charge de l’interaction avec le matériel réel
- Il fournit un interface de système de fichiers offrant un mode d’accès aux données de haut niveau
- Un fichier n’est pas seulement une donnée sur disque, mais fonctionne comme une interface logique pour communiquer avec le noyau
- Le noyau fournit un modèle d’isolation et de communication entre processus, permettant à chaque application de s’exécuter indépendamment ou de coopérer
- Le noyau Linux est open source, peut fonctionner sur de nombreuses architectures et fait partie des noyaux les plus utilisés au monde
Qu’est-ce qu’une distribution Linux ?
- Le noyau Linux seul ne permet pas à l’utilisateur d’exécuter un navigateur web ou des applications GUI ; il faut plusieurs couches d’infrastructure logicielle au-dessus du noyau
- La configuration réseau, l’attribution d’IP ou la gestion d’un VPN relèvent non pas du noyau, mais de programmes de l’espace utilisateur situés à un niveau supérieur
- Une distribution Linux se définit donc comme la combinaison du noyau et de l’infrastructure de l’espace utilisateur
- Une distribution inclut, au-dessus des fonctions de base fournies par le noyau, des paquets, des outils, de la configuration et le processus d’initialisation (
init) - Leur degré de complexité varie, depuis une configuration minimale comme Arch Linux jusqu’à une configuration conviviale comme Ubuntu
L’infrastructure hors noyau : l’espace utilisateur et le processus init
- Une fois le démarrage terminé, le noyau lance d’abord le processus
initportant le PID 1initdevient ensuite l’ancêtre de tous les processus de l’espace utilisateur et exécute successivement les services et outils du système
- L’ensemble des processus et outils exécutés par
initconstitue la substance réelle d’une distribution Linux - Plus une distribution devient complexe, plus elle accumule des fonctions superflues et se voit parfois critiquée comme « bloated »
- À l’inverse, en créant une micro-distribution personnalisée, on peut construire un système léger n’incluant que le strict minimum
Compiler un noyau Linux pour RISC-V
- Depuis un environnement
x86, compiler un noyau pour RISC-V à l’aide d’une chaîne d’outils de cross-compilation- Télécharger les sources
linux-6.5.2.tar.xzdepuiskernel.org, puis exécutermake ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig
- Télécharger les sources
menuconfigpermet de modifier visuellement la configuration du noyau- Après une compilation parallèle avec
make -j16, le fichierarch/riscv/boot/Imageest généré - Démarrer dans QEMU avec
qemu-system-riscv64 -machine virt -kernel arch/riscv/boot/Image- Dans les logs de démarrage, on peut voir des messages indiquant la détection de la couche SBI, l’initialisation de l’UART et l’activation de printk
Premier obstacle : pas de système de fichiers racine
- Pendant le démarrage du noyau, une panic du noyau se produit avec l’erreur
VFS: Unable to mount root fs- Cause : aucun système de fichiers racine (
initramfs) n’est fourni
- Cause : aucun système de fichiers racine (
- Un système de fichiers peut être constitué non seulement sur disque, mais aussi en mémoire vive (
initramfs) - L’
initramfsest empaqueté au formatcpioet peut être chargé dans QEMU avec l’option-initrd
Construire l’initramfs et exécuter « Hello world »
- L’exigence minimale est la présence du binaire
/init- Écrire
init.c, puis le compiler en liaison statique (-static) - L’empaqueter avec
cpio -o -H newc < file_list.txt > initramfs.cpio
- Écrire
- Au lancement dans QEMU, « Hello world » s’affiche, puis l’arrêt de
initprovoque à nouveau une panic du noyau- Solution : ajouter une boucle infinie pour empêcher
initde se terminer
- Solution : ajouter une boucle infinie pour empêcher
Ajouter un shell simple écrit en Go
initexécute/little_shellviaforketexecllittle_shell.goest un shell simple qui reçoit l’entrée utilisateur et réaffiche en écho les commandes- Compilation pour RISC-V avec
GOOS=linux GOARCH=riscv64 go build little_shell.go
- Compilation pour RISC-V avec
initetlittle_shellpartagent tous deux la sortie via l’UART- L’entrée/sortie standard est gérée par des descripteurs de fichiers et héritée lors du
fork
- L’entrée/sortie standard est gérée par des descripteurs de fichiers et héritée lors du
- On obtient ainsi un environnement Linux de base où « Hello from init » et les entrées du shell s’affichent en alternance
Récapitulatif du rôle du noyau
- Abstraction du matériel : les programmes utilisateur peuvent afficher du texte sans connaître les détails de l’UART ou des périphériques
- Fourniture d’interfaces de haut niveau : accès à d’autres binaires (
little_shell) via le système de fichiers - Isolation des processus :
initet le shell s’exécutent dans des espaces mémoire indépendants - Le noyau fournit une base d’exécution stable et hautement portable au-dessus d’un matériel complexe
Définition d’un système d’exploitation
- Certains considèrent que seul le noyau constitue le système d’exploitation, tandis que d’autres considèrent l’ensemble de la distribution comme le système d’exploitation
- L’essentiel est de comprendre la frontière des rôles et la structure d’interaction entre le noyau et l’espace utilisateur
Créer une micro-distribution réellement utile avec u-root
- Le projet u-root fournit un ensemble d’outils d’espace utilisateur basés sur Go
u-rootinclut un chargeur d’amorçage en espace utilisateur et un environnement shell s’exécutant au-dessus du noyau Linux
- Après l’installation, la commande
GOOS=linux GOARCH=riscv64 u-rootgénère automatiquement l’initramfs- Le fichier
/tmp/initramfs.linux_riscv64.cpiopeut ensuite être exécuté dans QEMU
- Le fichier
- Au démarrage, une bannière « Welcome to u-root! » s’affiche avec une invite de shell par défaut
- Prise en charge des commandes de base comme
ls,pwd,echo, avec complétion par tabulation
- Prise en charge des commandes de base comme
Exercice de connexion réseau
- Ajouter à QEMU les périphériques
virtio-net-deviceetvirtio-rng-pci- Utiliser les options
-device virtio-net-device,netdev=usernet -netdev user,id=usernet
- Utiliser les options
- Avec
dhclientdeu-root, une IP est attribuée automatiquement via DHCP- Exemple :
10.0.2.15/24attribué àeth0
- Exemple :
- Avec
wget http://google.com, l’accès au réseau externe réussit, et le téléchargement deindex.htmlest confirmé
L’importance du gestionnaire de paquets et de init
- Les distributions classiques utilisent un gestionnaire de paquets pour installer et mettre à jour dynamiquement les logiciels
- Cet exercice adopte une approche de type embarqué, où il faut reconstruire l’image complète
initn’est pas un simple lanceur de processus, mais un composant central de l’initialisation des périphériques, de la gestion des services et du contrôle du démarrage du système- Le code source de
initdansu-rootpermet d’observer les différentes étapes de configuration des périphériques (/dev)
- Le code source de
Dépôt GitHub
- L’ensemble du code et des exemples de ce guide est disponible dans popovicu/linux-micro-distro
- Il est possible d’y reconstruire l’image
initramfset de reproduire l’exercice
- Il est possible d’y reconstruire l’image
1 commentaires
Avis Hacker News
Cela fait quelques mois que je fabrique moi-même une micro-distribution Linux
L’espace utilisateur est composé d’un unique binaire statique, avec seulement quelques fichiers pour prendre en charge des conteneurs microVM confidentiels
La structure de l’initramfs est particulièrement intéressante. Le processus où le noyau extrait une archive cpio, entre dans un tmpfs et exécute /init ressemble presque à de la magie
On peut aussi concaténer plusieurs archives cpio, chacune pouvant être compressée, puis elles sont superposées dans l’ordre
Cette conception simple mais élégante m’a beaucoup appris en écrivant moi-même le code de décompression
Récemment, qemu a commencé à prendre en charge uftrace sur les principales architectures
C’est exactement la réponse quand des experts demandent : « Comment on débogue ça ? »
Pour en savoir plus, voir ce fil
Je travaille aussi sur un projet similaire — azathos
Il inclut un toy init, un shell et quelques utilitaires maison
J’y ai ajouté GNU coreutils pour le débogage, et je me concentre maintenant sur la capacité à dessiner des fenêtres dans le framebuffer
Ce projet est vraiment génial. Il me rappelle l’époque où, en 98, je faisais une « distribution » sur disquette pour cloner des PC Windows par diffusion UDP
« make bzimage », erreurs dans les scripts init, redémarrages en boucle… que de souvenirs
Il est intéressant de voir que la méthode actuelle n’est pas si différente. Le porter sur Raspberry Pi serait à la fois amusant et pédagogique. Je vais peut-être essayer moi-même
J’ai fini par m’en sortir quand un ami m’a gravé le contenu en sftp sur un CD, mais à l’époque on ne pouvait graver qu’en 2x
Je me demande à quel point il serait difficile de faire tourner ça comme image cloud (par ex. Vultr, DigitalOcean) ou de lancer une interface graphique avec Firefox
Il est aussi possible de démarrer sur une autre distribution puis d’utiliser kexec pour lancer son propre noyau et l’installer en mémoire
Pour un exemple concret d’implémentation, on peut regarder nixos-anywhere
C’est plus simple qu’on ne pourrait le penser
Une version de ce projet ciblant Raspberry Pi serait vraiment très intéressante
Je me demandais pourquoi fabriquer ça soi-même, et si explorer Linux simplement avec Gentoo ne suffirait pas
On peut personnaliser l’espace utilisateur, mais ce n’est pas idéal pour apprendre Linux lui-même
Rien qu’un stage3 tarball correspond déjà à une sorte de « mini-distribution »
Pour apprendre, c’est vraiment excellent, et pour obtenir quelque chose rapidement, buildroot est un très bon choix
Cet article m’a vraiment beaucoup appris. Merci pour ce post très riche en informations