4 points par GN⁺ 2025-10-27 | 1 commentaires | Partager sur WhatsApp
  • 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 virt de 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’initramfs et 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 init portant le PID 1
    • init devient 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 init constitue 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.xz depuis kernel.org, puis exécuter make ARCH=riscv CROSS_COMPILE=riscv64-linux-gnu- defconfig
  • menuconfig permet de modifier visuellement la configuration du noyau
  • Après une compilation parallèle avec make -j16, le fichier arch/riscv/boot/Image est 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
  • Un système de fichiers peut être constitué non seulement sur disque, mais aussi en mémoire vive (initramfs)
  • L’initramfs est empaqueté au format cpio et 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
  • Au lancement dans QEMU, « Hello world » s’affiche, puis l’arrêt de init provoque à nouveau une panic du noyau
    • Solution : ajouter une boucle infinie pour empêcher init de se terminer

Ajouter un shell simple écrit en Go

  • init exécute /little_shell via fork et execl
  • little_shell.go est 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
  • init et little_shell partagent 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
  • 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 : init et 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-root inclut 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-root génère automatiquement l’initramfs
    • Le fichier /tmp/initramfs.linux_riscv64.cpio peut ensuite être exécuté dans QEMU
  • 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

Exercice de connexion réseau

  • Ajouter à QEMU les périphériques virtio-net-device et virtio-rng-pci
    • Utiliser les options -device virtio-net-device,netdev=usernet -netdev user,id=usernet
  • Avec dhclient de u-root, une IP est attribuée automatiquement via DHCP
    • Exemple : 10.0.2.15/24 attribué à eth0
  • Avec wget http://google.com, l’accès au réseau externe réussit, et le téléchargement de index.html est 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
  • init n’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 init dans u-root permet d’observer les différentes étapes de configuration des périphériques (/dev)

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 initramfs et de reproduire l’exercice

1 commentaires

 
GN⁺ 2025-10-27
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

    • Moi aussi, en 98, j’ai tenté d’installer Mandrake Linux avec NetBIOS et ISDN, et j’ai dû recommencer des dizaines de fois à cause d’erreurs de checksum
      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

    • Le faire tourner comme image cloud est relativement simple. Il suffit d’avoir les pilotes de base du noyau et d’installer l’image
      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
    • Il suffit de créer une image incluant les pilotes virtio pour le réseau et le stockage, puis de la convertir en qcow2 et de l’enregistrer sur DigitalOcean ou ailleurs
      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

    • Gentoo est certes « compilé depuis les sources », mais le gestionnaire de paquets fait l’essentiel du travail
      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