7.3. Compilation du noyau Linux

La compilation du noyau est une spécificité des systèmes libres, qui n'est possible que parce que l'on dispose des sources du noyau. Cependant, même pour certains Unix commerciaux, il est possible d'effectuer une édition de liens, les modules du noyau étant fournis sous la forme de fichiers objets. La compilation ou l'édition de liens du noyau est une opération technique qui peut surprendre un habitué des systèmes fermés que sont par exemple Windows ou OS/2. Cependant, elle permet d'obtenir un noyau très petit, optimisé pour la machine sur laquelle il tourne, et donc à la fois économe en mémoire et performant. Il est donc recommandé d'effectuer cette compilation : pourquoi conserver un monstre capable de gérer des périphériques qui ne sont pas et ne seront jamais installés sur votre système ?

La compilation du noyau de Linux nécessite de disposer des sources du noyau fourni par votre distribution. En effet, la plupart des distributions modifient ces sources pour y ajouter des fonctionnalités ou des correctifs de sécurité, ce qui permet de ne pas prendre le risque d'utiliser la dernière version officielle du noyau, qui peut ne pas être considérée comme stable car trop récente. Parfois même, ce sont des fonctionnalités non encore incluse dans le noyau officiel qui sont utilisée par les distributions, ce qui rend l'utilisation du noyau générique impossible. Rien ne vous empêche d'utiliser pour autant la dernière version officielle du noyau, mais vous vous exposerez au risque d'avoir un système non fonctionnel, ou au moins à diagnostiquer des problèmes encore inconnus ou d'avoir à mettre à jour d'autres composants de votre distribution manuellement en raison des évolutions que ce noyau peut avoir subi.

Le noyau utilise des constructions spécifiques à gcc et ne peut donc être compilé de manière fiable que par ce compilateur (même si d'autres compilateurs compatibles avec GCC sont utilisables moyennant quelques efforts).

Note : La documentation du noyau indique que la version de gcc à utiliser pour le compiler est la version 3.2. La raison en est que les développeurs du noyau eux-mêmes changent rarement de compilateur, afin de ne pas avoir à se préoccuper d'éventuels bogues de celui-ci et ainsi de pouvoir se concentrer sur leur travail. La version 3.2 n'ayant pas de bogues majeurs, elle a été retenue, et les développeurs principaux sont supposés utiliser cette version. Ainsi, le noyau est théoriquement testé avec cette version, c'est la raison pour laquelle elle est recommandée. Toutefois, les versions plus récentes de GCC sont également tout à fait valables de manière générale, et parfois même elles sont nécessaires pour les architectures les plus récentes. Ainsi, les architectures 64 bits requièrent au minimum GCC 3.4... Quoi qu'il en soit, il n'y a généralement aucun problème à compiler le noyau avec les versions récentes de GCC, et en pratique on pourra utiliser la version installée dans le système sans inquiétude.

La compilation du noyau n'est pas très difficile. Elle nécessite cependant de répondre correctement aux questions de configuration. Les erreurs peuvent être multiples, et souvent fatales. Il est donc fortement conseillé de disposer d'une disquette de démarrage afin de réparer le système en cas d'erreur. Par ailleurs, il faut toujours conserver le dernier noyau utilisable en sauvegarde dans le répertoire /boot/. Il faut également ajouter une entrée spécifiant ce noyau dans le programme de démarrage (lilo), afin de pouvoir sélectionner l'ancien noyau en cas d'erreur. Ces opérations seront décrites en détail plus loin.

La compilation du noyau se passe en quatre étapes :

7.3.1. Installation des sources de Linux

Les sources du noyau sont normalement fournies par votre distribution. Vous pouvez toutefois trouver les sources génériques du noyau « officiel » sur le site kernel.org. Il est possible de récupérer les sources complètes, sous la forme d'une archive compressée d'environ 43 Mo. Toutefois, si l'on dispose déjà d'une version complète des fichiers sources, il est envisageable de ne télécharger que les fichiers différentiels de cette version à la version courante (ce que l'on appelle classiquement des « patches »).

Note : Les utilisateurs des distributions Redhat dérivées (telle que la Mandrake par exemple) doivent impérativement utiliser les sources fournies par leur distribution. En effet, les noyaux de ces distributions sont patchés à mort pour utiliser des fonctionnalité non stabilisées de la version de développement du noyau de Linux, et sans lesquelles la plupart des programmes et la bibliothèque C elle-même ne fonctionneraient plus. Je déconseille aux utilisateurs de ces distributions de se lancer dans l'aventure d'une quelconque compilation d'un des composants système.

Il est recommandé d'installer les sources du noyau dans un autre répertoire que celui où se trouvent les fichiers sources de votre distribution, car ceux-ci contiennent les fichiers d'en-tête C qui ont été utilisés pour générer la bibliothèque C du système et sont donc nécessaires à la compilation des programmes. Le remplacement des fichiers sources du noyau imposerait donc, en toute rigueur, de recompiler la bibliothèque C du système. Cette opération est extrêmement technique, risquée et longue, de plus, les fichiers d'en-tête du noyau évoluent souvent et provoquent des incompatibilié avec les programmes qui les utilisent. Les plus motivés trouveront toutefois en annexe la manière de procéder pour recompiler la bibliothèque C.

Généralement, les fichiers sources de Linux sont installés dans le répertoire /usr/src/linux/. Certaines distributions font une copie des fichiers d'en-tête du noyau qui ont servi pour la génération de la bibliothèque C dans les répertoires /usr/include/linux/, /usr/include/asm/ /usr/include/asm-generic. Si ce n'est pas le cas, il faudra éviter d'écraser le contenu du répertoire /usr/src/linux/ lors de l'installation des sources du nouveau noyau. Une solution est par exemple d'installer les fichiers du noyau dans le répertoire /usr/src/linux<version>/ et de ne pas toucher au répertoire des sources originels /usr/src/linux/. Les commandes suivantes permettront d'extraire les sources dans le répertoire dédié au sources de Linux :

cd /usr/src
tar xvfz linux-2.6.13.2.tar.gz

Si l'on dispose déjà d'une version complète des fichiers sources, et que l'on désire appliquer un patch, il faut décompresser le fichier de patch avec la commande suivante :

gunzip fichier.gz
fichier.gz représente le fichier de patch compressé (en supposant qu'il ait été compressé à l'aide de gzip). L'application du patch se fait de la manière suivante :
patch -p1 < fichier

Cette commande doit être lancée à partir du répertoire des sources du noyau (par exemple /usr/src/linux-2.6.13.2/). Dans cette ligne de commande, fichier représente le nom du fichier de patch précédemment décompressé, et l'option -p1 indique au programme patch d'utiliser les noms de répertoires relatifs au répertoire parent (à savoir le répertoire contenant le répertoire des sources du noyau, donc /usr/src/ dans notre cas). Si le patch doit être appliqué depuis un autre répertoire, il faudra éventuellement modifier l'option -px passée en paramètre au programme patch, où x est le nombre de niveaux de répertoires à ignorer pour l'application du patch. Consultez la page de manuel patch pour plus de détails sur cette option.

7.3.2. Choix des options de configuration du noyau

La configuration du noyau peut se faire à l'ancienne avec la commande suivante :

make config

Cette commande pose une série de questions auxquelles il faut pouvoir répondre correctement du premier coup. On n'a pas le droit à l'erreur ici, faute de quoi il faut tout reprendre à zéro.

Il est nettement préférable d'utiliser la version texte, qui fournit les options de configuration sous la forme de menus. Cela peut être réalisé avec la commande suivante :

make menuconfig

Certains préféreront l'une des versions X11 du programme de configuration, que l'on peut obtenir avec les commandes

make xconfig
ou
make gconfig
Sachez cependant que certaines options ne sont toutefois pas correctement proposées dans ce mode, et que la version textuelle du programme de configuration reste recommandée.

Quelle que soit la méthode utilisée, il faut répondre par 'Y' (pour « Yes »), 'N' (pour « No ») ou 'M' (pour « Module ») lorsque c'est possible. 'Y' et 'M' incluent la fonctionnalité courante dans le noyau, 'N' la supprime. 'M' permet d'utiliser la fonctionnalité en tant que module du noyau. En général, l'utilisation des modules permet d'alléger le noyau car les fonctionnalités sont chargées et déchargées dynamiquement. Cependant, les fonctionnalités nécessaires au démarrage de Linux, comme les gestionnaires de disques et systèmes de fichiers par exemple, ne doivent en aucun cas être placées dans des modules, car le système ne pourrait alors pas démarrer.

Le choix des options de configuration est réellement très large, car celles-ci couvrent un ensemble de fonctionnalités très large. La description exhaustive de ces options est à la fois fastidieuse et inutile, car vous n'utiliserez pas tous les gestionnaires de périphériques et toutes les fonctionnalités de Linux avec un même ordinateur. Il s'agit donc de répondre aux questions appropriées pour votre configuration, mais de le faire avec rigueur : la moindre erreur de configuration peut empêcher votre système de fonctionner correctement, voire l'empêcher de démarrer tout simplement. Vous trouverez une description rapide des principales options de configuration dans l'Annexe A. Les options les plus utiles seront également décrites lorsque cela sera nécessaire dans le chapitre de configuration du matériel.

7.3.3. Compilation et installation du noyau

Une fois la configuration du noyau réalisée, la compilation peut être lancée. Pour cela, il suffit de lancer la simple commande make dans le répertoire /usr/src/linux.

Une fois la compilation achevée, il faut installer le nouveau noyau. Cette opération nécessite beaucoup de prudence, car si le noyau nouvellement créé n'est pas bon, le système ne redémarrera pas. C'est pour cela qu'il est conseillé de conserver toujours deux versions du noyau, dont on est sûr que l'une d'entre elle fonctionne parfaitement. En pratique, cela revient à conserver la version originale du noyau installé par votre distribution. Pour cela, il faut en faire une copie de sauvegarde.

En général, le noyau est installé dans le répertoire /boot/ (ou dans le répertoire racine pour les anciennes versions de Linux). Il porte souvent le nom de vmlinuz. Pour le sauvegarder, il suffit donc de taper par exemple la commande suivante :

cp vmlinuz vmlinuz.old

Il faut également indiquer au gestionnaire d'amorçage qu'il faut qu'il donne maintenant la possibilité de démarrer l'ancienne version du noyau sous ce nouveau nom. Pour LILO, il suffit d'éditer le fichier /etc/lilo.conf et d'y ajouter une nouvelle configuration. En pratique, cela revient à dupliquer la configuration du noyau actuel et à changer simplement le nom du noyau à charger (paramètre « image » de la configuration dans /etc/lilo.conf) et le nom de la configuration (paramètre « label »). Vous devrez aussi rajouter l'option « prompt » si elle n'y est pas déjà, afin que LILO vous demande la configuration à lancer à chaque démarrage. Dans notre exemple, le nom du noyau à utiliser pour la configuration de sauvegarde sera vmlinuz.old. De même, si la configuration initiale de Linux porte le nom « linux », vous pouvez utiliser le nom « oldlinux » pour la configuration de sauvegarde.

Une fois le fichier lilo.conf mis à jour, il faut vérifier que l'on peut bien charger l'ancien système. Pour cela, il faut réinstaller LILO et redémarrer la machine. La réinstallation de LILO se fait exactement de la même manière que son installation, simplement en l'invoquant en ligne de commande :

lilo

Si LILO signale une erreur, vous devez corriger immédiatement votre fichier lilo.conf et le réinstaller.

Pour le GRUB, la définition d'une nouvelle configuration se fait également en dupliquant la configuration initiale et en changeant le nom de l'option de menu du GRUB et le chemin sur le fichier du noyau sauvegardé. Veillez également à bien ajouter une option timeout pour avoir la moindre chance de sélectionner la configuration à lancer. Tout cela doit être effectué dans le fichier de configuration /boot/grub/menu.lst. Contrairement à LILO, il n'est pas nécessaire de réinstaller le GRUB pour que les modifications de ce fichier soient prises en compte au démarrage suivant.

Vous pourrez alors redémarrer la machine avec la commande suivante :

reboot

Le gestionnaire d'amorçage utilisé vous propose alors de choisir le système d'exploitation à lancer. Il faut ici sélectionner la configuration de sauvegarde pour vérifier qu'elle est accessible et fonctionne bien. Le système doit alors démarrer en utilisant la copie sauvegardée du noyau. Si cela ne fonctionne pas, on peut toujours utiliser le noyau actuel en sélectionnant le noyau initial et en corrigeant la configuration du gestionnaire d'amorçage.

Lorsque vous vous serez assuré que le système peut démarrer avec la sauvegarde du noyau, vous pourrez installer le nouveau noyau. Son image a été créée par make dans le répertoire /usr/src/linux/arch/i386/boot/, sous le nom bzImage. L'installation se fait donc simplement par une copie dans /boot/ en écrasant le noyau actuel vmlinuz :

cp /usr/src/linux/arch/i386/boot/bzImage /boot/vmlinuz

Il faut également copier le fichier System.map du répertoire /usr/src/linux/ dans le répertoire /boot/ :

cp System.map /boot

Ce fichier contient la liste de tous les symboles du nouveau noyau, il est utilisé par quelques utilitaires systèmes.

Si vous utiliser LILO, il vous faudra le réinstaller à nouveau pour qu'il prennent en compte le nouveau noyau. Cela se fait avec la même commande que celle utilisée précédemment :

lilo

Cette opération n'est en revanche pas nécessaire avec le GRUB.

Encore une fois, il faut redémarrer la machine avec la commande suivante :

reboot

et vérifier que le nouveau noyau fonctionne bien. S'il ne se charge pas correctement, c'est que les options de configuration choisies ne sont pas correctes. Il faut donc utiliser le noyau sauvegardé, vérifier ses choix et tout recommencer. Attention cependant, cette fois, il ne faut pas recommencer la sauvegarde du noyau puisque cette opération écraserait le bon noyau avec un noyau défectueux.

Si le nouveau noyau démarre correctement, il ne reste plus qu'à installer les modules.

7.3.4. Compilation et installation des modules

Si le système a redémarré correctement, on peut installer les modules. Il n'est pas nécessaire de prendre les mêmes précautions pour les modules que pour le noyau. Il suffit donc ici de lancer la commande suivante dans le répertoire /usr/src/linux/ :

make modules_install

Au préalable, il est recommandé de décharger tous les modules présents en mémoire. Cela peut être réalisé à l'aide de la commande modprobe et de son option -r.

Les modules sont installés dans le répertoire /lib/module/version/, où version est le numéro de version du noyau courant. Il est possible que des modules d'autres versions du noyau existent dans leurs répertoires respectifs. Si vous n'en avez plus besoin, vous pouvez les effacer. Attention cependant si vous avez installé des modules additionnels non fournis avec le noyau dans ces répertoires, vous pourriez encore en avoir besoin.

Comme on l'a déjà vu, les modules sont utilisés par le chargeur de module du noyau, grâce à la commande modprobe. Cette commande a besoin de connaître les dépendances entre les modules afin de les charger dans le bon ordre. Il faut donc impérativement mettre à jour le fichier /lib/modules/version/modules.dep à chaque fois que l'on installe les modules, à l'aide de la commande suivante :

depmod -a

Note : La commande depmod -a est exécutée automatiquement lors de l'installation des modules du noyau. Toutefois, elle devra être exécutée manuellement si l'on installe des modules non fournis avec le noyau.