
Le code initial de l'infrastructure Rust a été fusionné dans l'arbre Git principal de Linux 6.1 le 3octobre par Linus Torvalds. Ce nouveau code initial de 12 500 lignes ne fournit que l'infrastructure de base et une intégration très élémentaire, tandis que les futures demandes d'extraction ajouteront plus d'abstractions de sous-systèmes, divers pilotes écrits en Rust, et plus encore. La construction du noyau Linux avec le support Rust reste facultative.
Dans un message adressé à la communauté du noyau, Torvalds a déclaré : « l'arbre a une base récente, mais est fondamentalement dans linux-next depuis un an et demi. Il a été mis à jour sur la base des retours du Kernel Maintainer's Summit. Miguel est le mainteneur principal, et j'aide quand c'est nécessaire. Notre plan est que l'arbre passe à la pratique standard de non-rebasage une fois que cette série initiale d'infrastructures sera terminée. Le contenu est le minimum absolu pour permettre la construction du code Rust dans le noyau, avec beaucoup plus d'interfaces (et de pilotes - NVMe, 9p, M1 GPU) sur le chemin ».
Selon Jonathan Corbet, aucun système doté d'un noyau 6.1 de production n'exécutera de code Rust, mais ce changement donne aux développeurs du noyau une chance de jouer avec le langage dans le contexte du noyau et de se faire une idée de la façon dont le développement Rust se déroule. La conclusion la plus probable pour la plupart des développeurs est qu'il n'y a pas encore assez de Rust dans le noyau pour faire quoi que ce soit d'intéressant.
Jonathan Corbet a eu son premier aperçu des sources BSD Unix en 1981, lorsqu'un instructeur de l'Université du Colorado l'a laissé « corriger » l'algorithme de pagination. Depuis, il n'a cessé de fouiller dans tous les systèmes sur lesquels il a pu mettre la main, travaillant au passage sur des pilotes pour les systèmes VAX, Sun, Ardent et x86. Il a obtenu son premier système Linux en 1993, et n'a jamais regardé en arrière. Corbet est actuellement cofondateur et rédacteur en chef de Linux Weekly News.
Le travail sur Rust pour le noyau Linux est en cours depuis quelques années, et il a abouti à la création de beaucoup de code de soutien et de quelques pilotes intéressants à regarder. D'autres initiatives sont en cours, notamment l'écriture d'un pilote graphique Apple en langage Rust. Pour la fusion initiale dans le noyau principal, Linus Torvalds a clairement indiqué qu'il fallait inclure le moins de fonctionnalités possibles. Ces pilotes et leur code de support ont donc été supprimés et doivent attendre une future version du noyau. Ce qui est présent est le support nécessaire pour construire un module qui peut être chargé dans le noyau, ainsi qu'un petit module d'exemple.
Pour rappel, le projet Rust for Linux vise à introduire un nouveau langage de programmation système dans le noyau. Rust a une propriété clé qui le rend très intéressant à considérer comme le deuxième langage du noyau : il garantit qu'aucun comportement indéfini n'a lieu (tant que le code non sécurisé est sain). Cela inclut l'absence d'erreurs de type use after-free, double frees, data races, etc. Après 31 ans, un deuxième langage sera donc admis pour le développement du noyau. Les débats y relatifs tournent au tour de la possibilité d’une mise au rebut du C au profit du langage Rust.
Construction du support Rust
« Le premier défi que les développeurs intéressés rencontreront est de construire le support Rust », déclare Jonathan Corbet. Le processus de configuration du noyau recherche les prérequis sur le système de construction et, s'ils ne sont pas présents, désactive silencieusement les options Rust afin qu'elles n'apparaissent même pas dans, par exemple, make menuconfig. Jonathan Corbet, bien qu'ayant installé Rust sur le système en question, s'est heurté à ce problème et a donc été contraint au processus ignominieux de lire la documentation pour comprendre ce qui manquait.
La construction du support Rust nécessite des versions spécifiques du compilateur Rust et de l'utilitaire bindgen - plus précisément, Rust 1.62.0 et bindgen 0.56.0. Si le système cible possède des versions plus récentes, le processus de configuration émettra des avertissements mais se poursuivra quand même. Plus gênant pour quiconque essaie de construire avec la chaîne d'outils Rust fournie par son distributeur, le processus de construction a également besoin de la source de la bibliothèque standard Rust afin de pouvoir construire sa propre version des crates core et alloc.
« Jusqu'à ce que les distributeurs commencent à fournir des paquets "Rust pour le noyau", il sera un peu difficile de placer ce code à un endroit où le processus de construction le trouvera », déclare Jonathan Corbet. « La façon d'obtenir facilement cette dépendance est de jeter l'éponge, d'abandonner la chaîne d'outils du distributeur et d'installer tout depuis les dépôts Rust à la place », poursuit-il.
La page getting started décrit comment le faire ; inévitablement, cela implique une de ces opérations de mise en confiance curl|bash. Le programme d'installation ne s'intéresse absolument pas à l'endroit où l'on souhaite que les éléments Rust soient installés (ils vont dans ~/.cargo) et modifie silencieusement les scripts de démarrage Bash de l'utilisateur pour ajouter le nouveau répertoire dans la variable PATH. Le résultat final fonctionne cependant et permet d'installer facilement les dépendances nécessaires.
Le module d'exemple
Une fois cela fait, le système de configuration du noyau consentira à définir l'option CONFIG_RUST ; une option supplémentaire permettra de construire le module d'exemple. Ce module (samples/rust/rust_minimal.rs) est en effet minimal, mais il est suffisant pour avoir une idée de ce à quoi ressemblera le code du noyau en Rust. Il commence par l'équivalent Rust d'une ligne #include :
use kernel::prelude::*;
Il reprend les déclarations trouvées dans rust/kernel/prelude.rs, en rendant disponibles quelques types, fonctions et macros.
Un module de noyau écrit en C comprend un certain nombre d'appels à des macros comme MODULE_DESCRIPTION() et MODULE_LICENSE() qui stockent des métadonnées sur le module dans une section ELF séparée. Les macros module_init() et module_exit() identifient respectivement les fonctions constructeur et destructeur du module. L'équivalent Rust met une grande partie de ce passe-partout dans un seul appel de macro :
Code : | Sélectionner tout |
1 2 3 4 5 6 7 | module! { type: RustMinimal, name: b"rust_minimal", author: b"Rust for Linux Contributors", description: b"Rust minimal sample", license: b"GPL", } |
Cette macro est exigeante quant à l'ordre des différents champs et se « plaindra » si le développeur se trompe. En plus de rassembler toutes ces informations en un seul appel, la macro module ! inclut une entrée type : qui sera le pointeur vers le code réel du module. Le développeur devra fournir un type qui fait quelque chose d'intéressant. Dans l'exemple de module, ce type ressemble à ceci :
Code : | Sélectionner tout |
1 2 3 | struct RustMinimal { numbers: Vec<i32>, } |
Code : | Sélectionner tout |
1 2 3 4 5 6 7 | impl kernel::Module for RustMinimal { fn init(_module: &'static ThisModule) -> Result<Self> { pr_info!("Rust minimal sample (init)\n"); pr_info!("Am I built-in? {}\n", !cfg!(MODULE)); let mut numbers = Vec::new(); numbers.try_push(72)?; |
La fin de cet article est réservée aux abonnés. Soutenez le Club Developpez.com en prenant un abonnement pour que nous puissions continuer à vous proposer des publications.