1. Introduction
Cette deuxième partie explique comment récupérer les sources du noyau Linux, comprendre leur organisation et préparer une configuration personnalisée.
Le laboratoire choisi est Ubuntu dans une machine virtuelle Hyper-V. Nous utiliserons GNU Make, Kbuild, Kconfig et les utilitaires de configuration fournis avec le noyau Linux.
Ce cours suppose que le langage C est connu. Il poursuit les exercices de la partie précédente sur les modules, sans imposer de recompiler ni de remplacer immédiatement le noyau exécuté.
Chaque notion s'appuie sur un exemple, l'explication de son utilité et une méthode pour vérifier le résultat. Les exemples sont adaptés aux versions modernes du noyau ; les noms de menus peuvent varier selon la version des sources.
Pour des raisons de sécurité, on expérimente dans une VM avec point de contrôle Hyper-V et copie séparée des fichiers importants. Cette partie ne change ni GRUB ni le noyau de démarrage : la construction complète et l'installation seront abordées dans la partie suivante.
Sommaire des thèmes
- Comprendre les versions mainline, stable, LTS et les branches de développement.
- Récupérer les sources sur kernel.org ou avec Git.
- Explorer les répertoires arch, drivers, kernel, fs, mm et include.
- Lire les fichiers Makefile, Kconfig et .config.
- Comprendre CONFIG_, obj-y, obj-m et la compilation conditionnelle.
- Choisir une configuration adaptée à Ubuntu et à la VM.
- Utiliser defconfig, olddefconfig, localmodconfig et menuconfig.
- Comparer les configurations avec diffconfig.
- Comprendre les types et dépendances du langage Kconfig.
- Ajouter sa propre option de menu et relier celle-ci à un fichier C.
- Réaliser un TP complet, puis répondre aux exercices corrigés.
CHAPITRE 1 - Objectifs et principes du développement du noyau Linux
2. Pourquoi récupérer et configurer le noyau ?
Un driver Linux doit être compilé pour une plateforme, une version et une configuration du noyau cible. Les sources permettent de comprendre les interfaces internes et l'origine des objets qui composent une image ou un module.
Exemple : notre VM possède déjà un noyau Ubuntu. Si nous voulons écrire un petit module logiciel, une reconstruction complète de Linux n'est généralement pas nécessaire. Mais si nous voulons intégrer une fonctionnalité dans les sources, sélectionner des options ou explorer la façon dont un driver est inclus, il faut maîtriser l'arbre source, Kbuild et Kconfig.
À retenir : « télécharger les sources » n'est pas « compiler » ; « compiler » n'est pas « installer » ; « installer » n'est pas « démarrer sur le nouveau noyau ».
3. Distribution et noyau
Ubuntu est une distribution : elle livre le noyau, le shell, les services, les bibliothèques et des outils d'administration. Linux désigne ici le noyau qui arbitre notamment CPU, mémoire, processus, fichiers et périphériques.
Code: Select all
uname -r
cat /etc/os-release
uname -m
4. Objectifs et limites du chapitre
Nous apprendrons à choisir une version déterminée, récupérer son code, localiser des composants, comprendre les fichiers Makefile/Kconfig, préparer « .config », utiliser menuconfig et ajouter une nouvelle option. Nous n'allons pas remplacer le noyau de démarrage, signer des modules pour Secure Boot ni toucher au système principal.
5. Prérequis logiciels
Dans Ubuntu, pour un laboratoire habituel :
Code: Select all
sudo apt update
sudo apt install git build-essential bc flex bison libssl-dev \
libelf-dev libncurses-dev dwarves xz-utils wget ca-certificates
- git : gérer versions et commits ;
- build-essential : GCC, make et outils usuels ;
- bc, flex, bison : outils utilisés par certaines phases du build ;
- libssl-dev et libelf-dev : bibliothèques de développement pour des outils du noyau ;
- libncurses-dev : interface texte menuconfig ;
- dwarves : paquet fournissant notamment pahole pour BTF ;
- xz-utils : archives compressées ;
- wget, ca-certificates : téléchargement HTTPS.
6. Environnement matériel et sécurité
Pour une VM Ubuntu Desktop, 4 vCPU, 6 à 8 Gio de RAM et 50 Gio d'espace disponible offrent du confort. Ce ne sont pas des minima impératifs. La compilation intégrale consomme nettement plus que la simple consultation des sources. Le VHDX dynamique et les points de contrôle peuvent augmenter l'utilisation disque côté Windows.
Créez un point de contrôle Hyper-V avant toute modification importante, et une sauvegarde séparée de votre travail. Même si un snapshot permet de revenir en arrière, il ne remplace pas une sauvegarde indépendante.
CHAPITRE 2 - Les versions et les branches du noyau Linux
7. Lire un numéro de version
Une version upstream peut être 6.12.1 : première composante 6, deuxième 12, troisième 1 (mise à jour corrective de la série). Ce n'est PAS une promesse de compatibilité des interfaces internes, contrairement à l'idée qu'on se fait parfois du versionnement sémantique d'une bibliothèque.
Exemple historique : 5.4 (sortie de série), 5.4.1 (correctif), 5.5-rc1 (première candidate d'une série suivante). Le « 5.x » du livre reflète l'époque de sa rédaction. En 2026, il faut choisir une version volontairement et consulter la documentation de CETTE version, pas suivre aveuglément tous les menus photographiés.
8. Mainline, release candidate, stable, LTS
- mainline : branche principale où convergent les nouvelles évolutions ;
- -rc : préversions destinées à stabiliser la prochaine sortie ;
- stable : mises à jour correctives d'une version publiée ;
- LTS ou longterm : série maintenue plus longtemps, selon des engagements qui peuvent changer ;
- arbres de sous-systèmes : réseaux, pilotes, architectures, etc. ;
- linux-next : intégration anticipée de changements en préparation.
Une LTS n'assure pas que les API internes des modules restent stables. Elle offre surtout une maintenance prolongée dans la série. Pour un laboratoire non consacré aux régressions, choisir une branche stable ou longterm encore maintenue au moment du test.
9. Pourquoi éviter une sélection automatique ?
La toute dernière version peut modifier Kconfig, déplacer des fichiers ou changer une API. À l'inverse, une ancienne version peut manquer de correctifs de sécurité et de compatibilité matérielle. Vérifiez la liste des séries maintenues sur https://www.kernel.org/ et fixez la version du laboratoire dans vos notes.
10. Noyau exécuté contre noyau source
Code: Select all
uname -r
ls -l /lib/modules/"$(uname -r)"/build
Même si vous placez dans ~/kernel-lab les sources d'un autre noyau, « uname -r » ne changera pas. Seul un redémarrage vers une image effectivement installée changerait la version active.
Exercice : télécharger les sources 6.12 alors que la VM lance un noyau Ubuntu différent : est-ce un problème ? Non pour lire et configurer 6.12 ; potentiellement oui pour charger dans Ubuntu un module construit contre 6.12, car l'ABI interne et la configuration peuvent différer.
CHAPITRE 3 - Développement collaboratif, mainteneurs et Git
11. Comment le code évolue-t-il ?
Des contributeurs proposent des correctifs (« patches »). Les mainteneurs et les relecteurs examinent les comportements, la sécurité, les régressions, le style et les tests. Une modification qui compile n'est pas nécessairement acceptable. Les sous-systèmes réunissent leurs évolutions avant l'intégration dans la branche principale.
12. Le fichier MAINTAINERS
Le fichier MAINTAINERS, à la racine des sources, associe des chemins, des domaines et des responsables. Pour retrouver les interlocuteurs d'un composant :
Code: Select all
less MAINTAINERS
./scripts/get_maintainer.pl -f drivers/char/mem.c
13. Dépôt, commit, branche et tag
Un commit identifie un état précis de l'historique avec des métadonnées. Une branche est un pointeur mobile ; un tag tel que v6.12 pointe généralement sur une publication précise. Un clone n'est pas une installation : il copie l'arbre Git, sans modifier le noyau lancé ni GRUB.
Code: Select all
git status
git log -5 --oneline
git tag --list 'v6.12*'
git show --stat --oneline HEAD
- status : modifications locales ;
- log : commits récents ;
- tag : références nommées ;
- show : détails du commit courant (HEAD).
14. Cycle de développement
Après une sortie, la « merge window » permet d'intégrer de nouvelles fonctionnalités. Puis arrivent généralement des versions -rc centrées sur la stabilisation. La version finale est publiée, suivie éventuellement de correctifs dans les branches stable. Cela explique pourquoi deux branches du noyau peuvent diverger momentanément.
CHAPITRE 4 - Récupération et préparation des sources du noyau
15. Archive ou Git ?
Une archive .tar.xz fournit une photographie des sources : plus simple, sans historique. Git permet de comparer les changements et remonter aux commits, au prix d'un téléchargement qui peut devenir important. Une distribution peut aussi fournir des sources PATCHÉES, différentes de l'arbre officiel upstream.
16. Archive officielle : exemple guidé
La version 6.12.1 ci-dessous est choisie seulement pour illustrer une URL concrète. Elle n'est pas recommandée comme noyau de production en 2026. Pour votre vrai travail, vérifiez et remplacez par une version encore maintenue.
Code: Select all
mkdir -p ~/sources-linux
cd ~/sources-linux
KVER=6.12.1
wget "https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-${KVER}.tar.xz"
tar -tf "linux-${KVER}.tar.xz" | head
tar -xf "linux-${KVER}.tar.xz"
cd "linux-${KVER}"
ls
Sécurité : vérifier l'origine et, idéalement, la signature de l'archive avec les mécanismes publiés par kernel.org. Ne recopiez pas une empreinte SHA256 d'une page aléatoire : comparez-la à celle d'une publication fiable et authentifiée.
17. Récupération avec Git
Code: Select all
cd ~
git clone --depth 1 --branch v6.12 \
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git \
kernel-lab
cd kernel-lab
git status
git log -1 --oneline
18. Où travailler ?
Dans le dossier personnel, sans sudo :
Code: Select all
~/kernel-lab/ # sources de travail
~/kernel-build/ # futurs objets construits
~/notes-kernel/ # captures, notes, commandes
19. Contrôler l'extraction
Code: Select all
test -f Makefile && echo "Makefile présent"
test -f init/Kconfig && echo "Kconfig présent"
test -d drivers && echo "drivers présent"
head -n 8 Makefile
CHAPITRE 5 - Comprendre l’arborescence du noyau Linux
20. Où se trouvent les fonctionnalités ?
À la racine : Makefile, Kconfig, README, COPYING, MAINTAINERS et de nombreux répertoires. Il s'agit des fichiers sources, PAS des répertoires installés sur Ubuntu.
Code: Select all
cd ~/kernel-lab
ls -la | head -n 35
find . -maxdepth 1 -type d | sort
Code: Select all
arch/ code spécifique aux architectures CPU
block/ couche des périphériques blocs
crypto/ infrastructure cryptographique
Documentation/ documentation technique
drivers/ nombreux pilotes matériels et virtuels
fs/ systèmes de fichiers et VFS
include/ en-têtes et déclarations
init/ initialisation du noyau
ipc/ communication interprocessus
kernel/ mécanismes centraux, planification, signaux...
lib/ utilitaires internes
mm/ gestion mémoire
net/ piles et protocoles réseau
samples/ exemples de code, selon version
scripts/ outils de configuration et compilation
security/ sécurité, LSM
tools/ outils connexes en espace utilisateur
virt/ virtualisation
21. Le cas de drivers/
Le répertoire drivers/ contient des sous-dossiers par catégories. Un driver n'est pas forcément un pilote de carte PCI physique : un périphérique virtuel ou un module logiciel peut fournir un service au système.
Code: Select all
find drivers -maxdepth 2 -type d | head -n 40
git grep -n 'module_init(' -- drivers/ | head
22. Où trouver les déclarations ?
Les en-têtes sous include/linux/ déclarent des structures et fonctions internes. include/uapi/ concerne les interfaces exposées aux programmes utilisateur. Une déclaration interne n'est pas une ABI stable pour les modules tiers.
Code: Select all
git grep -n 'struct file_operations' -- include/
git grep -n 'module_param(' -- samples/ drivers/ | head
23. Kconfig et Makefiles locaux
Une fonctionnalité possède souvent trois éléments :
- une option dans Kconfig ;
- une règle associée à cette option dans Makefile ;
- un ou plusieurs fichiers source C ou assembleur.
Code: Select all
drivers/
Kconfig
Makefile
char/
Kconfig
Makefile
...
24. Mini-exercice : remonter jusqu'au code
Choisissez CONFIG_TUN si le symbole existe dans votre version :
Code: Select all
git grep -n -w 'config TUN' -- '*Kconfig*'
git grep -n 'CONFIG_TUN' -- '*Makefile*'
CHAPITRE 6 - Make, Makefiles et système de compilation Kbuild
25. Pourquoi Kbuild existe-t-il ?
Le noyau contient des milliers de fichiers, plusieurs architectures et beaucoup de fonctionnalités facultatives. Compiler aveuglément tous les fichiers est inutile et parfois impossible. Kbuild sélectionne les bons objets selon l'architecture et « .config », puis coordonne leurs dépendances.
GNU make est un moteur généraliste lisant des règles. Kbuild est l'infrastructure du noyau autour de Makefiles et de scripts. Kconfig définit les options et les menus, qui sont ensuite résolus en une configuration.
26. Comparaison avec un petit programme C
Code: Select all
/* calcul.c */
int addition(int a, int b)
{
return a + b;
}
/* main.c */
#include <stdio.h>
int addition(int a, int b);
int main(void)
{
printf("%d\n", addition(2, 3));
return 0;
}
Code: Select all
gcc -c calcul.c -o calcul.o
gcc -c main.c -o main.o
gcc main.o calcul.o -o test
./test
27. Chaîne de construction conceptuelle
Code: Select all
Kconfig -> choix utilisateur -> .config
|
v
fichiers générés de config
|
Sources C/ASM + Makefiles Kbuild + compilateur
|
v
Objets .o -> archives internes -> vmlinux / modules .ko
|
v
image de démarrage
28. Trois formes de règles
Code: Select all
obj-y += base.o
obj-m += diagnostic.o
obj-$(CONFIG_EXAMPLE_DRIVER) += example_driver.o
Pourquoi cette syntaxe ? Dans GNU make, « $(NOM) » remplace une variable par sa valeur. Kbuild prépare les symboles CONFIG_ pour permettre cette sélection. Dans un simple Makefile utilisateur non intégré à Kbuild, copier cette ligne ne suffit pas.
29. Module composé de plusieurs sources
Code: Select all
obj-$(CONFIG_EXAMPLE_DRIVER) += example_driver.o
example_driver-y := coeur.o diagnostics.o
30. Module externe et noyau existant
Un module externe peut avoir un Makefile minimal :
Code: Select all
obj-m += demo_externe.o
Code: Select all
make -C /lib/modules/"$(uname -r)"/build M="$PWD" modules
31. Les résultats d'une construction
« vmlinux » est généralement le fichier ELF principal non compressé ; l'image de démarrage x86 peut être « arch/x86/boot/bzImage ». Un « .ko » est un module chargeable. « System.map » aide à examiner des symboles. Dans les noyaux modernes, les objets intégrés passent notamment par des archives « built-in.a ». Les noms exacts des fichiers temporaires changent parfois.
CHAPITRE 7 - CONFIG_, options du noyau et compilation conditionnelle
32. Qu'est-ce qu'un symbole CONFIG_ ?
Kconfig déclare des SYMBOLES comme « TUN », « MODULES » ou « DEBUG_INFO ». Quand une configuration est enregistrée, ils apparaissent sous le préfixe « CONFIG_ », par exemple « CONFIG_TUN=m ». Ces noms relient les menus, les scripts et parfois le code C. Il faut distinguer le nom Kconfig (« TUN ») et sa représentation dans « .config » (« CONFIG_TUN »).
Exemple dans un fichier Kconfig :
Code: Select all
config LAB_TEST
tristate "Exemple pédagogique"
default n
help
Active un exemple de laboratoire.
33. Les trois valeurs
Code: Select all
CONFIG_LAB_TEST=y # intégré à l'image du noyau
CONFIG_LAB_TEST=m # construit comme module chargeable
# CONFIG_LAB_TEST is not set # désactivé
34. Différence fondamentale : intégré et module
Si un pilote nécessaire au démarrage est intégré (« y »), le noyau possède directement son code. S'il est module (« m »), le fichier .ko doit être disponible et chargé au bon moment ; certaines fonctions critiques au démarrage nécessitent alors un initramfs correctement préparé.
Un driver « intégré » et un driver « module » peuvent remplir une fonction équivalente, mais leur cycle de chargement et leur gestion des ressources diffèrent. C'est la même idée générale qu'une liaison statique versus chargement séparé, sans être une équivalence parfaite.
35. Le chemin Kconfig -> Makefile -> fichier C
Code: Select all
# Kconfig
config LAB_TEST
tristate "Mon composant"
default n
# Makefile Kbuild
obj-$(CONFIG_LAB_TEST) += lab_test.o
# Fichier source correspondant : lab_test.c
36. Les macros générées pour le C
Kbuild produit pendant la préparation des fichiers comme « include/generated/autoconf.h » et « include/config/auto.conf » (dans l'arbre des objets si O= est utilisé). Ils traduisent les options en définitions utilisables par les outils de build et le code.
Exemple conceptuel : pour une option booléenne activée, le préprocesseur peut disposer de « CONFIG_LAB_TEST » défini. Pour un symbole tristate réglé sur m, la représentation C peut prendre la forme « CONFIG_LAB_TEST_MODULE ». C'est pourquoi « #ifdef CONFIG_LAB_TEST » ne couvre PAS automatiquement les deux cas y et m.
37. Exemple C : séparer les cas
Code: Select all
#include <linux/kconfig.h>
#include <linux/printk.h>
static void exemple(void)
{
#if IS_ENABLED(CONFIG_LAB_TEST)
pr_info("L'option LAB_TEST est active (y ou m).\n");
#else
pr_info("LAB_TEST n'est pas activée.\n");
#endif
}
Autre exemple simple, uniquement pour une option bool :
Code: Select all
#ifdef CONFIG_LAB_VERBOSE
pr_info("Journalisation détaillée active\n");
#endif
38. Les dépendances ne sont pas décoratives
Une option visible et activable peut dépendre d'une autre : architecture, prise en charge de modules ou infrastructure particulière. Si la dépendance est absente, l'option peut devenir invisible ou être limitée. Modifier « .config » à la main ne contourne pas proprement les règles : un nouvel appel à Kconfig peut corriger ou rejeter la valeur.
Exercice : si CONFIG_LAB_TEST=m, à quoi devient « obj-$(CONFIG_LAB_TEST) » ? Réponse : obj-m. Si le symbole est n ? L'objet n'est pas sélectionné par cette règle.
CHAPITRE 8 - Choisir une configuration initiale pour le noyau
39. Pourquoi éviter une configuration vide ?
Le noyau dépend d'options qui collaborent : systèmes de fichiers, pilotes de stockage, réseau, support de la plateforme et mécanismes du démarrage. Créer un .config à partir de rien peut conduire à un noyau qui compile mais ne démarre pas, ou même à un build impossible.
Pour un PC/serveur Ubuntu dans Hyper-V, le choix pédagogique le plus compréhensible est de partir d'une configuration fonctionnelle de distribution, puis de la réduire ou l'adapter. Pour un système embarqué, on privilégie souvent le defconfig fourni par la plateforme ou le fabricant du BSP.
40. La configuration par défaut
Code: Select all
cd ~/kernel-lab
make defconfig
Pour une autre architecture, un nom comme « make ARCH=arm64 defconfig » peut être approprié, mais la construction ultérieure exigera aussi un compilateur compatible avec l'architecture cible.
41. Réutiliser la configuration d'Ubuntu
Code: Select all
cd ~/kernel-lab
cp "/boot/config-$(uname -r)" .config
make olddefconfig
1) « /boot/config-$(uname -r) » est la configuration sauvegardée par la distribution pour la release en cours, lorsqu'elle est disponible ;
2) « cp » la copie vers les sources (elle n'installe rien) ;
3) « make olddefconfig » adapte le fichier aux options de l'arbre choisi, en conservant les valeurs compatibles et en attribuant des valeurs par défaut aux nouvelles entrées.
ATTENTION : une configuration Ubuntu peut contenir des symboles ajoutés ou renommés par des correctifs de distribution. Une partie de ces options peut disparaître lorsque vous l'appliquez aux sources upstream. Vérifiez les changements, et ne considérez pas que les modules Ubuntu installés correspondent automatiquement au nouveau noyau.
42. oldconfig et olddefconfig
« oldconfig » lit une ancienne configuration et peut poser des questions sur les nouveaux symboles. « olddefconfig » choisit les valeurs par défaut sans demander une réponse à chaque nouveauté. Ce dernier est commode pour automatiser une adaptation, mais il ne remplace pas la vérification des choix importants.
43. Conseil : séparer sources et fichiers générés
La variable « O= » permet de choisir un dossier de build distinct :
Code: Select all
mkdir -p ~/kernel-build
cd ~/kernel-lab
make O="$HOME/kernel-build" defconfig
make O="$HOME/kernel-build" menuconfig
Si vous utilisez O=, réutiliser la configuration Ubuntu ainsi :
Code: Select all
cp "/boot/config-$(uname -r)" ~/kernel-build/.config
make O="$HOME/kernel-build" olddefconfig
CHAPITRE 9 - La configuration par les modules avec localmodconfig
44. La logique de localmodconfig
Une distribution active de nombreuses fonctions pour couvrir beaucoup de configurations matérielles. Notre VM n'en utilise qu'une partie au moment du test. « make localmodconfig » essaie de préparer un « .config » où les modules inutilisés ne sont pas retenus, en s'appuyant sur la liste des modules chargés.
Cette stratégie est un RACCOURCI, pas une détection exhaustive des périphériques. Un module non chargé au moment du relevé pourrait être indispensable plus tard : clé USB, VPN, autre système de fichiers, périphérique ajouté à chaud, fonctionnalité réseau particulière.
45. Ce que montre lsmod
Code: Select all
lsmod
lsmod | head -n 15
46. Sauvegarder un instantané
Code: Select all
lsmod > /tmp/modules-chargees.txt
head /tmp/modules-chargees.txt
47. Générer la configuration
En supposant que ~/kernel-build/.config existe déjà :
Code: Select all
cd ~/kernel-lab
make O="$HOME/kernel-build" \
LSMOD=/tmp/modules-chargees.txt localmodconfig
48. Pourquoi cette approche peut être dangereuse
Scénario : vous n'avez jamais branché de périphérique USB dans la VM. Sa prise en charge peut ne pas figurer dans les modules actifs, puis être écartée. Vous connectez ensuite le périphérique : il ne fonctionne plus dans le noyau personnalisé. Autre scénario : un driver est nécessaire très tôt au démarrage, mais son absence n'est pas visible dans la liste des modules.
Conclusion : pour la première compilation destinée au démarrage, une configuration de distribution validée est souvent plus prudente qu'un localmodconfig agressif. Pour une VM de test que l'on peut restaurer, localmodconfig peut être un excellent exercice de compréhension.
49. Prouver la réduction
Sauvegardez la configuration AVANT la modification :
Code: Select all
cp ~/kernel-build/.config ~/kernel-build/config-avant-localmod
make O="$HOME/kernel-build" \
LSMOD=/tmp/modules-chargees.txt localmodconfig
scripts/diffconfig ~/kernel-build/config-avant-localmod \
~/kernel-build/.config | head -n 40
CHAPITRE 10 - Les commandes de configuration et de nettoyage
50. Lire les objectifs disponibles
Code: Select all
cd ~/kernel-lab
make help
51. Tableau des cibles principales
Code: Select all
make defconfig configuration par défaut de plateforme
make oldconfig adapte l'ancienne config, avec questions
make olddefconfig adapte, valeurs par défaut sans questions
make menuconfig interface texte ncurses
make nconfig autre interface de configuration en texte
make xconfig interface graphique Qt, si dépendances présentes
make localmodconfig réduction selon les modules chargés
make savedefconfig crée une configuration minimale de référence
make help aide et liste des cibles proposées
52. olddefconfig dans la vie réelle
Vous recevez un fichier .config préparé pour une autre version du noyau. Si vous lancez immédiatement « make », les dépendances peuvent imposer de nouvelles valeurs. La bonne pratique est de conserver une copie de référence puis de faire « make olddefconfig » et d'inspecter la différence.
53. Nettoyage : les pièges
- « make clean » enlève de nombreux fichiers générés, sans chercher à effacer la configuration comme le ferait mrproper ;
- « make mrproper » nettoie beaucoup plus, y compris « .config » et d'autres fichiers générés ;
- « make distclean » va encore plus loin pour certains résidus.
Ne lancez pas ces commandes par réflexe lorsque vous essayez simplement de relancer menuconfig. Sauvegardez « .config » AVANT. Avec O=, vérifiez quel arbre d'objets est visé.
54. Pourquoi éviter sudo ?
« make menuconfig » travaille dans un dossier dont vous êtes propriétaire. Si vous avez besoin de sudo pour créer « .config », vérifiez les permissions : vous avez peut-être auparavant exécuté une compilation en root. Corrigez la cause au lieu d'accumuler des commandes privilégiées.
CHAPITRE 11 - Personnaliser le noyau avec menuconfig
55. À quoi sert l'interface ?
menuconfig est une interface en mode texte (généralement ncurses) permettant de parcourir des options Kconfig. Ce n'est pas un IDE, ni un chargeur de modules. Le menu contrôle la configuration du FUTUR build, sans appliquer en direct ces choix au noyau en fonctionnement.
56. Lancer le menu
Code: Select all
cd ~/kernel-lab
make O="$HOME/kernel-build" menuconfig
57. Navigation
- Flèches : choisir une ligne ;
- Entrée : ouvrir un sous-menu ;
- Espace : basculer un choix compatible avec ses dépendances ;
- Y / M / N : demander respectivement intégré / module / désactivé quand autorisé ;
- « ? » : aide de l'entrée ;
- « / » : recherche par symbole ou libellé ;
- Exit / Save : sortir et enregistrer.
Les touches et les libellés peuvent changer légèrement selon la version. Si « M » ne fonctionne pas, demandez-vous si la fonctionnalité accepte les modules ET si ses dépendances sont satisfaites.
58. Comprendre les symboles visuels
Dans les interfaces historiques, « [ ] » évoque une option bool désactivée, « [*] » une option bool active ; « < > », « <M> » et « <*> » désignent généralement les états possibles d'une option tristate. Le rendu exact peut varier. Une option grisée n'est pas forcément un bug : une dépendance peut la rendre non modifiable.
59. Recherche avec la touche /
Tapez le nom du symbole, par exemple « IKCONFIG », sans préfixe « CONFIG_ ». L'écran de recherche permet souvent de voir la localisation, le texte du menu, les dépendances et les symboles associés. C'est plus robuste que d'apprendre l'emplacement d'un menu dans un livre imprimé en 2020.
Exemple : si un symbole dépend de « PROC_FS », et que cette dépendance est n, la possibilité de l'activer peut être limitée. La recherche aide à comprendre pourquoi.
60. Paramètres à ne pas modifier au hasard
Les options liées au système de fichiers racine, aux disques, à l'architecture, à la mémoire et à la sécurité peuvent influer sur le démarrage. Pour cette première exploration, choisissez une fonctionnalité pédagogique non essentielle. Évitez de désactiver des éléments que vous n'avez pas identifiés.
61. Sauvegarde et validation
En sortant, validez « Save » et vérifiez :
Code: Select all
ls -l ~/kernel-build/.config
grep '^CONFIG_IKCONFIG=' ~/kernel-build/.config
Code: Select all
grep 'CONFIG_IKCONFIG' ~/kernel-build/.config
CHAPITRE 12 - Comparer et vérifier les fichiers de configuration
62. Pourquoi comparer ?
Un « .config » peut contenir des milliers de lignes. Après une modification apparemment mineure, Kconfig peut ajuster des options dépendantes. Sans comparaison, on ne sait pas exactement ce qui a changé. Il est utile de disposer d'un état de référence avant toute expérimentation.
63. Préparer deux copies
Code: Select all
cp ~/kernel-build/.config ~/kernel-build/config-avant
make O="$HOME/kernel-build" menuconfig
cp ~/kernel-build/.config ~/kernel-build/config-apres
64. diff et diffconfig
Code: Select all
diff -u ~/kernel-build/config-avant \
~/kernel-build/config-apres | less
cd ~/kernel-lab
scripts/diffconfig ~/kernel-build/config-avant \
~/kernel-build/config-apres
65. Lire les différences
Un changement « n -> y » signifie que le symbole a été activé, « m -> y » que l'élément passe d'un module au noyau intégré. Un changement « m -> n » peut supprimer un driver du build. Toutes les modifications ne sont pas dangereuses, mais chaque suppression dans le chemin de démarrage doit être comprise.
66. Éditer .config : pourquoi la prudence ?
« .config » est du texte, mais il représente le résultat d'une résolution Kconfig. Une modification manuelle de « CONFIG_FOO=n » peut être normalisée par « olddefconfig », ignorée à cause d'une dépendance ou produire un état trompeur. Préférez l'interface ou un outil comme « scripts/config » quand vous savez précisément ce que vous faites.
Exemple d'activation ciblée d'un booléen, si le symbole existe :
Code: Select all
cd ~/kernel-lab
scripts/config --file "$HOME/kernel-build/.config" -e IKCONFIG
make O="$HOME/kernel-build" olddefconfig
CHAPITRE 13 - Comprendre le langage Kconfig
67. Ce qu'est un fichier Kconfig
Kconfig n'est ni du code C ni un Makefile. C'est un langage déclaratif : il annonce des symboles, leur type, leurs dépendances, leurs valeurs proposées et les textes d'aide. Les interfaces « menuconfig » et « nconfig » lisent ces déclarations pour construire leurs menus.
Exemple :
Code: Select all
menu "Fonctionnalités du laboratoire"
config LAB_VERBOSE
bool "Activer les logs supplémentaires"
default n
help
Ajoute des messages pour faciliter le diagnostic.
endmenu
68. Les types disponibles
« bool » : oui/non. « tristate » : y/m/n selon le support des modules. « int » : entier décimal. « hex » : entier hexadécimal. « string » : chaîne. Le type détermine les valeurs admissibles et leur présentation dans l'interface.
Exemple :
Code: Select all
config LAB_LIMIT
int "Limite expérimentale"
range 1 100
default 10
config LAB_LABEL
string "Étiquette de laboratoire"
default "demo"
69. Dépendances et visibilité
Code: Select all
config LAB_BASE
bool "Infrastructure de base"
default n
config LAB_ADVANCED
bool "Fonctionnalité avancée"
depends on LAB_BASE
default n
70. « select » n'est pas « depends on »
« depends on X » impose une contrainte au choix courant. « select X » peut forcer un symbole cible et ne doit pas être employé à la légère : dans certaines situations il contourne ses dépendances habituelles. Le langage Kconfig recommande de réserver « select » surtout à des symboles internes sans dépendances difficiles. « imply X » fournit une recommandation plus faible qu'un « select ».
71. Menus, sous-menus et choix exclusifs
Code: Select all
choice
prompt "Mode de fonctionnement"
default LAB_MODE_SAFE
config LAB_MODE_SAFE
bool "Mode prudent"
config LAB_MODE_FAST
bool "Mode expérimental"
endchoice
72. Inclure d'autres fichiers
Code: Select all
source "drivers/lab/Kconfig"
73. Quelques constructions courantes
Code: Select all
config LAB_EXTRA
tristate "Option supplémentaire"
depends on MODULES
default m
help
Exemple utile pour étudier les contraintes.
CHAPITRE 14 - Ajouter une option personnalisée au noyau
74. Objectif : un module de laboratoire
Nous voulons une option « CONFIG_LAB_DEMO » dont le menu propose y, m ou n. Nous fournirons un petit fichier C qui écrit un message lors de son initialisation. Le but est de comprendre comment une entrée Kconfig sélectionne un objet Kbuild : nous n'allons pas encore charger un nouveau noyau dans la VM.
75. Préparer une modification réversible
Avec un dépôt Git propre :
Code: Select all
cd ~/kernel-lab
git status
cp drivers/misc/Kconfig drivers/misc/Kconfig.avant-lab
cp drivers/misc/Makefile drivers/misc/Makefile.avant-lab
76. Ajouter l'entrée Kconfig
Ouvrez « drivers/misc/Kconfig » et vérifiez sa structure (menus, blocs « if », « endmenu »). Ajoutez la déclaration suivante dans une zone appropriée du menu des périphériques divers, en respectant les structures existantes :
Code: Select all
config LAB_DEMO
tristate "Module pedagogique LAB_DEMO"
default n
help
Ajoute un petit exemple de laboratoire.
Ne pilote aucun materiel.
77. Associer une règle de compilation
Ajoutez dans « drivers/misc/Makefile » :
Code: Select all
obj-$(CONFIG_LAB_DEMO) += lab_demo.o
78. Écrire le code C
Créer « drivers/misc/lab_demo.c » :
Code: Select all
#include <linux/init.h>
#include <linux/module.h>
#include <linux/printk.h>
static int __init lab_demo_init(void)
{
pr_info("lab_demo: initialisation\n");
return 0;
}
static void __exit lab_demo_exit(void)
{
pr_info("lab_demo: retrait\n");
}
module_init(lab_demo_init);
module_exit(lab_demo_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Exemple de configuration Kconfig/Kbuild");
- « linux/init.h » fournit notamment les annotations « __init » et « __exit » ;
- « linux/module.h » fournit les macros de module ;
- « linux/printk.h » permet l'usage de « pr_info » ;
- « static » limite ici la visibilité de la fonction à ce fichier ;
- « __init » marque une fonction d'initialisation, dont le traitement dépend du fait que le code soit intégré ou modulaire ;
- le retour « 0 » signale le succès de l'initialisation ;
- « __exit » concerne le chemin de sortie, notamment lors du retrait d'un module ;
- « module_init » et « module_exit » enregistrent les points d'entrée et de sortie ;
- « MODULE_LICENSE » et « MODULE_DESCRIPTION » fournissent des métadonnées.
Ce programme n'ouvre aucun périphérique, n'alloue aucune mémoire et n'enregistre aucun numéro de device. L'exemple évite volontairement les problèmes de durée de vie et de synchronisation pour isoler le mécanisme de configuration.
79. Vérifier la visibilité dans menuconfig
Code: Select all
cd ~/kernel-lab
make O="$HOME/kernel-build" menuconfig
Code: Select all
grep 'CONFIG_LAB_DEMO' ~/kernel-build/.config
80. D'où viennent les macros C ?
Après préparation de la configuration :
Code: Select all
make O="$HOME/kernel-build" prepare
grep 'LAB_DEMO' ~/kernel-build/include/generated/autoconf.h
81. Valider les modifications
Code: Select all
git diff -- drivers/misc/Kconfig drivers/misc/Makefile
git status --short
Ne chargez PAS le module produit par une autre version du noyau directement dans Ubuntu. La construction, le démarrage de l'image correspondante et le test d'insertion appartiennent au chapitre suivant. Pour apprendre simplement à compiler un module sur le noyau Ubuntu actuel, utilisez plutôt les en-têtes correspondant à « uname -r » et la méthode du module externe présentée au chapitre 6.
CHAPITRE 15 - Travaux pratiques : préparer un noyau personnalisé
82. Préparer le laboratoire
Créez un point de contrôle Hyper-V, lancez Ubuntu, relevez « uname -r » et « uname -m », puis choisissez une version source fixée. Vérifiez le disque disponible avec « df -h » et la RAM avec « free -h ». Pourquoi ? Une configuration peut réussir même si le disque ne suffira pas à la compilation suivante.
83. Télécharger et identifier
Suivez la méthode Git décrite au chapitre 4, puis notez « git rev-parse HEAD ». Vérifiez que « Makefile », « Kconfig », « drivers/ » et « Documentation/ » existent. Ne poursuivez pas si vous êtes dans un mauvais dossier.
84. Créer une base
Code: Select all
mkdir -p ~/kernel-build
cd ~/kernel-lab
cp "/boot/config-$(uname -r)" ~/kernel-build/.config
cp ~/kernel-build/.config ~/kernel-build/config-distribution
make O="$HOME/kernel-build" olddefconfig
Code: Select all
make O="$HOME/kernel-build" defconfig
85. Tester un changement isolé
Code: Select all
cp ~/kernel-build/.config ~/kernel-build/config-reference
make O="$HOME/kernel-build" menuconfig
Code: Select all
scripts/diffconfig ~/kernel-build/config-reference \
~/kernel-build/.config
86. Ajouter LAB_DEMO
Reprenez les trois étapes du chapitre 14 : déclaration Kconfig, règle Makefile et fichier C. Activez « LAB_DEMO=m ». Vérifiez « .config », puis contrôlez les ajouts avec « git diff » et « git status ». Cette étape démontre que Kconfig sélectionne une option et que Kbuild connaît l'objet à construire.
87. Vérifications et limites
Code: Select all
grep 'CONFIG_LAB_DEMO' ~/kernel-build/.config
grep 'CONFIG_LAB_DEMO' drivers/misc/Makefile
test -f drivers/misc/lab_demo.c && echo "Source présente"
88. Revenir à un état propre
Utilisez Git pour examiner précisément les modifications à conserver. Pour abandonner un TP, revenez aux versions sauvegardées des fichiers Kconfig/Makefile et retirez seulement le fichier C que vous avez créé. Ne lancez pas un nettoyage Git destructeur sans lire les fichiers affectés : vos autres travaux pourraient être perdus.
Livrables conseillés pour le forum : la version du noyau, le hash Git, la configuration initiale, les différences après menuconfig, le contenu du petit Kconfig, le Makefile et le C, plus une courte explication de chaque étape.
CHAPITRE 16 - Exercices, questions et corrections
89. Questions de compréhension
- Q1. « uname -r » change-t-il après « git checkout » ?
- Q2. Quelle est la différence entre « CONFIG_FOO=y » et « =m » ?
- Q3. Un Makefile contient « obj-$(CONFIG_FOO) += foo.o ». Si FOO=n, foo.c est-il sélectionné par cette règle ?
- Q4. Pourquoi localmodconfig peut-il rendre un noyau incomplet ?
- Q5. Pourquoi copier un « .config » Ubuntu puis lancer olddefconfig ?
- Q6. Quelle est la différence entre « depends on » et « select » ?
- Q7. Pourquoi comparer les configurations après un changement ?
- Q8. Quelle différence entre « vmlinux », « bzImage » et « .ko » ?
- Q9. Si une option tristate vaut m, pourquoi « #ifdef CONFIG_FOO » n'est-il pas un test universel ?
- Q10. Un module compilé contre les sources 6.12 peut-il forcément être chargé sur une VM Ubuntu dont la release diffère ?
90. Corrections expliquées
- R1. Non. Git modifie la copie de travail, pas le noyau exécuté.
- R2. y sélectionne une inclusion au noyau ; m sélectionne un module, si autorisé. Cela ne garantit ni installation ni chargement.
- R3. Non. Si FOO=m, la règle participe à la génération d'un module ; si y, à la construction intégrée.
- R4. Les modules non chargés lors de l'inventaire ne couvrent pas tous les usages futurs, le matériel ajouté plus tard ou certains besoins de démarrage.
- R5. Récupérer des choix fonctionnels tout en laissant Kconfig adapter les symboles aux sources effectivement utilisées. Il faut ensuite inspecter les changements.
- R6. « depends on » limite la sélection de l'option courante ; « select » force potentiellement un autre symbole et peut contourner certaines de ses contraintes.
- R7. Une option peut modifier des dépendances et déclencher d'autres changements que celui demandé dans l'interface.
- R8. vmlinux est le noyau ELF principal, bzImage est une image de démarrage x86, « .ko » un module chargeable. Leurs usages et formats ne sont pas interchangeables.
- R9. Les symboles « module » peuvent être exposés au C via « CONFIG_FOO_MODULE ». Utilisez les macros Kconfig adaptées (« IS_ENABLED », éventuellement « IS_REACHABLE ») selon le type de code.
- R10. Non. Les interfaces internes, symboles exportés, options et métadonnées de version peuvent être incompatibles.
CHAPITRE 17 - Conclusion et préparation du chapitre suivant
91. Bilan du chapitre et savoir-faire
Ce chapitre a établi le chemin complet du choix technique :
Code: Select all
Version précise -> sources -> Kconfig -> .config
|
v
Kbuild et Makefiles
|
v
sources sélectionnées
|
v
objets et modules lors du futur build
L'essentiel pour un développeur de drivers : savoir où trouver un code, comment il est sélectionné, quand il est intégré ou construit comme module, et pourquoi une option peut être bloquée par des dépendances. Ce sont des compétences directement transférables à la maintenance d'un driver.
Dans le chapitre suivant, nous pourrons aborder le build lui-même, les outils de diagnostic, l'installation dans la VM, l'initramfs et le chargeur de démarrage. Nous vérifierons le fonctionnement avec une procédure de retour arrière. Ne confondez jamais un message « build succeeded » avec la preuve qu'un noyau démarre ou qu'un module est sûr.
Annexes - Références et rappels
Glossaire
- Upstream : sources du projet principal, avant adaptations d'une distribution.
- Kconfig : langage de description des options de configuration.
- Kbuild : mécanismes de compilation et d'assemblage du noyau.
- .config : résultat de la configuration, propre à un arbre/une cible.
- Module .ko : fichier compilé destiné au chargeur de modules du noyau.
- O= : dossier de sortie séparé de l'arbre source.
- Tag : référence Git nommée à un état précis.
- ABI : contrat binaire ; l'ABI interne des modules Linux n'est pas garantie stable entre noyaux.
Dépannage rapide
- « No rule to make target » : mauvais dossier, cible inexistante ou chemin erroné.
- « ncurses ... not found » : dépendances de menuconfig absentes.
- Option introuvable : rechercher son symbole et contrôler les dépendances.
- .config disparu : avez-vous lancé mrproper, ou oublié O= ?
- Module invalide au chargement : vérifier d'abord noyau cible, version, architecture, options et signature requise.
Documentation officielle à consulter
https://www.kernel.org/ — versions et sources officielles
https://docs.kernel.org/kbuild/kconfig-language.html — langage Kconfig
https://docs.kernel.org/kbuild/kconfig.html — outils de configuration
https://docs.kernel.org/kbuild/makefiles.html — règles Kbuild
https://docs.kernel.org/kbuild/modules.html — modules externes
https://docs.kernel.org/process/2.Process.html — processus de développement
