Outils pour utilisateurs

Outils du site


expert:recompilation_noyau

Compilation du noyau Linux

Ce tutoriel a pour but de donner des informations générales sur la compilation d'un noyau Linux. De nombreuses distributions disposent d'outils spécifiques pour cette tâche dont il serait dommage de se priver, cependant la méthode générique présente l'avantage de fonctionner quelque soit votre environnement.

Le noyaux Linux est au cœur des distributions GNU-Linux, il agit comme le métronome du système, sert d'interface entre la partie logiciel et le matériel, et prend en charge des fonctions aussi importantes que le temps processeur ou la quantité de mémoire vive alloués à chaque programme, le contrôle de l'activité réseau, le chargement des pilotes (on parle de “modules”) pour assurer le fonctionnement du matériel.

Pour avoir une perspective historique sur la création et l'évolution du noyau Linux, ainsi que son mode de développement actuel, vous pouvez vous référer à la page dédiée de Wikipedia.

Un signe $ précède les commandes qui ne nécessitent pas de droits administrateur ; un signe # précède celles qui nécessitent des droits administrateur (ces signes ne font PAS partie des commandes). Les lignes qui ne commencent pas par un signe $ ou # correspondent au résultat de la commande précédente.
Le vocabulaire minimum
  • kernel est le mot anglais pour noyau, vous le rencontrerez souvent dans des articles ou tutoriels même francophones, il est souvent utilisé de manière interchangeable avec “noyau”.
  • Les sources sont le code du noyau (ou de tout autre logiciel) avant sa compilation sous forme binaire destiné à être exécuté. Le noyau Linux est écrit en différents langages de programmation (majoritairement “C”), et les deux programmes chargés de compiler le code source sous Linux sont généralement “make” et “gcc”. Cette opération de compilation est tout l'objet de cet article, elle aboutira à la création d'une image binaire du noyau, adaptée à votre matériel. L'accès au code source, ainsi que la possibilité de le distribuer, l'utiliser et le modifier sont des libertés au cœur du logiciel libre. Voyez le site de l'association April ou la Free Software Foundation pour plus de détails sur cette fantastique liberté qui nous est offerte par le logiciel libre, et les moyens de la préserver.
  • compiler est l'action de transformer le code source “brute” d'un programme en une image binaire adaptée et personnalisée qui sera exécutée au sein de votre système GNU-Linux. Un fichier souvent nommé “makefile” agit comme une super recette, il est utilisé par le programme “make” qui va réunir et lier les différents éléments nécessaires à la réalisation finale (le programme prêt à être utilisé) à partir du code source “brute”. Pour y parvenir “make” va faire appel à un compilateur qui sur un système GNU-Linux est généralement “gcc”.
  • module est parfois utilisé de manière interchangeable avec “pilote” (“driver” en anglais). Un module peut être un élément qui interface un matériel, le noyau, et les applications (c'est le cas des modules regroupés sous “kernel/drivers/” dans le répertoire des modules), mais de nombreux modules ne sont pas directement des “pilotes” de matériel et ce sens est extrêmement réducteur de la diversité des modules. Quelques exemples avec des modules pilotant un matériel comme “uvcvideo” (webcam) ou “ath5k” (carte réseau), en revanche “ext4” gère un type de système de fichier et non pas le disque dur sur lequel il repose (“kernel/fs”), “blowfish” est une méthode d'encryptage de données (“kernel/crypto”), et les modules sous “kernel/net/ipv4/netfilter/” correspondent à des fonctionnalités du pare-feu “netfilter” présent dans le noyau.
  • initrd ou initramfs est un système de fichier initial temporaire, chargé en mémoire vive par le chargeur d'amorçage (par exemple grub) à partir duquel le système de fichier racine définitif pourra être monté. Le rôle de l'initrd ne se borne pas à monter le système de fichier racine et à passer la main au noyau, il peut également inclure les modules nécessaires à initialiser les cartes réseau (partition racine sur nfs par exemple), permettre l'initialisation de la carte vidéo pour afficher un écran de démarrage graphique, proposer un environnement shell minimal, initialiser les couches d'abstraction nécessaires pour monter la partition racine (md/raid, lvm) …etc.

Pourquoi compiler son noyau ?

Toutes les distributions fournissent un noyau déjà compilé et prêt à l'emploi, alors pourquoi se compliquer la vie et compiler sois même un noyau ? Cela permet de mieux comprendre cet élément central de votre système, et surtout c'est parfois nécessaire pour activer/désactiver une fonction particulière, un “pilote”, etc… Compiler votre noyau vous permet de bénéficier des avancées de la dernière version, de choisir le mode de compilation des pilotes (en module ou à l'intérieur du noyau), ou encore de créer un système sans disque initial de démarre (initrd). Cela présente également des risques, par exemple la dernière version sortie du noyau a été moins testée que la version choisie par votre distribution, elle peut présenter des bogues sur des nouvelles fonctions, ou des régressions (perte de performances et/ou de fonctions) sur de plus anciennes. Nouveau ne veut pas forcément dire meilleur ou plus performant. Faire un mauvais choix dans les options de compilation, particulièrement dans le cas d'un démarrage sans disque initial, peut facilement se traduire par l'impossibilité de démarrer votre système. Il est donc impératif de conserver installé un noyau dont le bon fonctionnement est avéré, celui par défaut de votre distribution par exemple.
Si la principale raison de compiler votre noyau est d'obtenir un gain de performance, vous risquez d'être déçu par le rapport entre le temps passé à la compilation, et le gain pratique de performance. Il est possible d'optimiser à la marge la réactivité de son système par des options de compilation, mais l'investissement en temps risque bien d'annuler tout gain de productivité qui en découlerait. Enfin n'oubliez pas que lorsque vous gérez vous même votre noyau vous ne bénéficiez plus des mises à jour de sécurité de votre distribution pour ce noyau. C'est à vous qu'il revient de suivre le développement du noyau, et de recompiler à chaque fois que de nouvelles sources incluant des mises à jour de sécurité sont disponibles.
Finalement la meilleur raison sera sans doute pour certains : “parce que c'est possible !”

Du côté des mauvaises raisons on peut citer le besoin de compiler un module externe, pour cela il suffira d'installer les “headers” ou éventuellement les sources du noyau fourni par votre distribution, et de lire la documentation livrée avec les sources du module que vous désirez compiler.
Penser que le dernier-nouveau-tout-neuf noyau sera nécessairement mieux (plus “rapide”) que le précédent est une erreur commune. C'est le plus souvent faux, voir plus haut au sujet des possibles bugs ou régressions.
“Ma distribution “xy_stable” a un vieux noyau”. Ce type de raisonnement a toutes les chances de mener à la catastrophe, le noyau est un élément central de la distribution, si celle-ci est orientée vers la stabilité maximum il y a de fortes chances pour qu'elle applique des patchs soigneusement élaborés à ses noyaux, et au besoin les distributions peuvent “rétroporter” (“backport” en anglais) des éléments ou correctifs introduits dans une version plus récente du noyau. Si vous compilez votre noyau vous renoncez à ce travail méticuleux et à la sécurité qu'il apporte.
“Le nouveau système de fichier “extbrtfxfs” est trop cool, je le veux”. Compiler une nouvelle version du noyau pour bénéficier d'une nouveauté est une chose, mais il faut également s'assurer que les autres éléments de la distributions soient en phase avec ces nouveautés. Si vous utilisez un nouveau système de fichier mais que ni les utilitaires de disque, ni le chargeur de démarrage de votre distribution n'ont été mis à jour pour l'utiliser, vous courrez à la catastrophe.

Travail préliminaire : RTFM (lisez la documentation) !

Avant de se lancer tête baissée dans la compilation proprement dite un minimum de préparation s'impose. Documentez-vous au sujet des choix techniques de votre distribution :

  • Votre distribution utilise-t-elle un disque initial de démarrage (“initrd” ou “initramfs”, c'est le cas de l'écrasante majorité des distributions), ou tous les modules sont-ils compilés à l'intérieur du noyau ?
  • Quel est le système de fichier utilisé ? (ext2/3/4, reiserfs, etc…)
  • Quels sont les modules nécessaires au fonctionnement de votre matériel ? Le type de votre processeur (Intel, AMD, autre), son architecture (x86 ou x86_64, ppc ou ia64 peut-être) ? Autant de questions auxquelles vous devez pouvoir répondre pour éviter de vous retrouver dans une impasse.

De nombreuses distributions proposent également une méthode spécifique de compilation du noyau, il est en général plus facile et plus sûr de l'utiliser. Vous devez également choisir entre utiliser les sources officielles et “brutes” du noyau disponible sur www.kernel.org (on parle de sources “vanilla”), ou utiliser les sources fournies par votre distribution comprenant souvent de nombreux patchs (correctifs). Il est également possible de récupérer certains de ces patchs et de les appliquer sur les sources “vanilla”, mais la compatibilité avec une version différente de noyau n'est pas du tout garantie.

Dans les sources du noyau sont également disponibles de la documentation générale, ou des documentations spécifiques à un module ou une fonction. Pour avoir un aperçu rapide de ce qui pourrait vous intéresser regardez le fichier “README” dans le répertoire des sources, et faites un tour dans le sous répertoire “Documentation”.

Récupérer les sources

Pour compiler un noyau vous devez disposer de ses sources, la version de référence, dépourvue des patchs spécifiques aux distributions et parfois appelées “vanilla” est disponible sur le site kernel.org.
Vous pouvez également utiliser les sources fournies par votre distribution, avec ou sans patchs. Par exemple la distribution Debian fournit pour tous ses noyaux un paquet source, il faut pour celà avoir ajouté les dépôts de paquets sources à son fichier “sources.list” (voir cette page sur la gestion des paquets Debian). Fedora propose de manière similaire les sources de ses noyaux, mais également des sources “vanilla” nommées “kernel-linus-*”.

En plus de ces sources vous pouvez utiliser des versions particulières, par exemple les version “rt” (“real Time”) qui correspondent à des noyaux optimisés pour les stations de travail multimédia. Ce type de noyau limite les problèmes de latence dans la capture, le traitement ou la diffusion en temps réel de musique ou de vidéo. Les modifications sont disponibles sous forme de patchs à appliquer aux sources (voir plus bas “Appliquer un patch”), certaines distributions spécialisées proposent directement des noyaux “temps réel”. Ces patchs sont également disponibles dans un espace dédié sur kernel.org.

Il existe deux familles du noyau Linux actives à ce jour, la 2.6.* et 3.* Celle qui vous intéresse est sans aucun doute la 3.*.
Ensuite vous devrez choisir une version particulière, désignée par le troisième chiffre, par exemple le dernier noyau stable à ce jour est le 3.16.1, soit la première version de maintenance de la 16ème version de la famille 3.*.
Voyez archives des sources du noyau sur kernel.org pour une vue panoramique des versions présentes et passées.

  • Fichiers en “.sign” : somme de contrôle pour vérifier l'intégrité de l'archive correspondante.
  • Fichiers “.tar.xz” : sources du noyau compressées au format “tar” et “xz”.
  • Fichiers “.tar.bz2” : format de compression des sources alternatif.
  • Fichiers “patch-” : patch applicable à la révision précédente (et aucune autre).

Capture d'écran de la page d'accueil de kernel.org :

Si le noyau fourni par votre distribution a une numérotation “bizarre” (3.12-12.xy.x86_64 par exemple) c'est simplement parce que sont ajoutés des suffixes qui correspondent au cycle de développement du noyau interne à la distribution, en raison de l'application de patchs, du rétroportage de code, de la présence de différents types de noyaux précompilés dans les dépôts de la distribution (“server”, “generic”, “pae”, “-rt”, “-xen”) …etc).
Les sources “vanilla” de kernel.org qui portent un suffixe “-rc” (pour “Release Candidate”,exemple “3.17-rc3”) sont des sources de noyaux en cours de développement. Ces noyaux peuvent être instables, présenter des bugs ou des régressions importants, ils sont destinés aux tests et au développement, pas à un usage normal.

Installer un environnement de compilation

Compiler un noyau nécessite comme toute compilation de disposer d'un certain nombre d'outils, en premier lieu un compilateur (gcc), le programme make, éventuellement le programme patch si vous désirez appliquer des patchs. Certaines distributions fournissent un paquet générique qui installe tout le nécessaire, comme “build-essential” sur Debian et Ubuntu.
Des dépendances supplémentaires peuvent être nécessaires pour utiliser des interfaces de configuration conviviales “menuconfig” ou mieux “nconfig” basées sur “ncurses” (paquets de développement de libncurses), “xconfig” basé sur “Qt” (libqt3-mt-dev) ou “gnomeconfig” basé sur “gtk” (libglib2.0-dev, libglade2-dev, libgtk2.0-dev). Les noms des paquets nécessaires peuvent varier en fonction de votre distribution, cherchez les paquets de développement correspondant aux librairies utilisées par l'interface (ncurses, Qt ou GTK).

Où compiler

Les sources du noyau installé résident généralement dans /usr/src/ (ou /usr/src/kernels), de même que d'autres fichiers de développement du noyau qui peuvent être présents sur votre système (“headers”). Pour garder ce répertoire dans un état consistant il est déconseillé de l'utiliser pour effectuer une compilation personnelle, il est préférable de créer un répertoire de travail sur lequel vous avez des droits d'écriture sans nécessiter de droits root. Une possibilité pourra être de créer un répertoire /tmp/kernel_perso par exemple (attention, /tmp est vidé à chaque redémarrage sur de nombreuses distributions), ou dans votre répertoire personnel ~/kernel_perso. De cette manière vous ne devrez utiliser les droits root que pour l'installation.

$ mkdir ~/kernel_perso
$ cd ~/kernel_perso

Mise en place des sources

Vous pouvez récupérer les sources par divers moyens, si vous installez un paquet source de votre distribution vous trouverez sans doute les sources dans /usr/src, d'où vous pourrez les déplacer. Si vous souhaitez utiliser d'autres sources comme celles de kernel.org il suffit de les télécharger, puis de décompresser l'archive récupérée. Si vous avez remarqué que votre distribution propose des noyaux de différents types (“amd64”, “i686”, “server”, etc…) vous serez peut-être étonné de ne trouver qu'un seul type de source. Tous les types de noyaux sont dérivés des mêmes sources au départ, et se différencient par les options de configuration et les patchs appliqués. Pour l'exemple nous téléchargerons en ligne de commande avec l'utilitaire “wget” les sources du dernier noyau en date (3.16.1) sur kernel.org, avant de les décompresser avec “tar”. Par habitude je renomme enfin le répertoire des sources en ajoutant le suffixe “-perso” afin de le différencier clairement des éventuelles autres sources présentes sur le système :

$ wget ftp://ftp.kernel.org/pub/linux/kernel/v3.x/linux-3.16.1.tar.xz
$ tar xJf linux-3.16.1.tar.xz
$ mv linux-3.16.1 linux-3.16.1-perso
Vous utiliserez “tar xJf” pour des sources compressées au format “.tar.xz”, et “tar xjf” si les sources récupérées sont au format “.tar.gz2”. Voir la commande “man tar” pour plus de détails.

Configuration

Cette étape est la plus importante, elle implique des choix qui vont déterminer la réussite de votre compilation, c'est à cette étape que vous devrez choisir de compiler les pilotes nécessaires à votre matériel à l'intérieur du noyau ou comme modules (ce qui implique l'usage d'un disque initial de démarrage par la suite), que vous pourrez choisir des options d'optimisation spécifique à votre matériel (type de processeur etc…). On ne détaillera pas ici les options de compilation disponibles, elles sont trop nombreuses et changent trop rapidement. Pour obtenir des informations précises et à jour reportez-vous sur la documentation du noyau (présente dans les sources), ou sur des sites spécialisés qui suivent l'actualité du développement du noyau de près (voir la section “liens” en bas de page).
Une bonne façon de ne pas se perdre dans les options est d'utiliser une configuration de départ dont on sait qu'elle fonctionne, par exemple celle du noyau de votre distribution. Lors de l'installation d'un noyau un fichier “config” est créé, par exemple sur un système Debian fonctionnant avec le noyau “3.14.23-amd64” vous trouverez un fichier /boot/config-3.14.23-amd64. La version du noyau en cours d'utilisation est renvoyée par la commande :

$ uname -r

On utilise cette commande pour identifier et copier le fichier de configuration du noyau en cours d'utilisation, qui sera donc le fichier “/boot/config-$(uname -r)”.

Ici nous allons copier ce fichier et l'utiliser comme base pour notre nouveau noyau :

$ cp /boot/config-$(uname -r) .config
$ make oldconfig

Remarquez bien que la première commande est effectuée à l'intérieur du répertoire des sources du noyau, ensuite remarquez que le fichier de configuration copié est renommé en “.config”, c'est à dire qu'il s'agit d'un fichier “caché” (commençant par un point “.”). Pour le voir apparaître lorsque vous listez le contenu du répertoire courant, utilisez :

$ ls -la | grep config

Voir cette page sur la commande "ls" pour plus de détails.

La commande “make oldconfig” vous présentera un dialogue pour chaque nouvelle option, c'est à dire celles qui n'existaient pas dans la version d'origine du fichier de configuration, et utilisera le choix du fichier d'origine pour toutes les options communes aux deux versions.
La capture d'écran suivante montre ce dialogue dans la rubrique des options liées aux capteurs matériels présents sur certains composants. Remarquez en fin de ligne les choix possibles entre crochets (par exemple [M/n/y] ou [Y/n/m]). Le premier choix est écrit en majuscule, c'est celui qui sera retenu par défaut si vous pressez simplement la touche entrée. Pour utiliser un des autres choix vous devez écrire la lettre correspondante avant de valider : M ou m (Module) pour compiler en module, Y ou y (Yes) pour compiler à l'intérieur du noyau (on dit parfois “en dur” ou “en statique”), et enfin N ou n (No) pour laisser l'option non configurée.

Un extrait d'un dialogue “make oldconfig” (cliquez l'image pour agrandir).

#
# CPU Frequency scaling
#
CONFIG_CPU_FREQ=y
CONFIG_CPU_FREQ_TABLE=y
# CONFIG_CPU_FREQ_DEBUG is not set
CONFIG_CPU_FREQ_STAT=m
# CONFIG_CPU_FREQ_STAT_DETAILS is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE is not set
# CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE is not set
CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
# CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE is not set
CONFIG_CPU_FREQ_GOV_PERFORMANCE=y
CONFIG_CPU_FREQ_GOV_POWERSAVE=m
CONFIG_CPU_FREQ_GOV_USERSPACE=m
CONFIG_CPU_FREQ_GOV_ONDEMAND=y
CONFIG_CPU_FREQ_GOV_CONSERVATIVE=m

Extrait d'un fichier de configuration.

Certaines options peuvent présenter une information supplémentaire en fonction de leur état de développement (et de stabilité) : (NEW) pour les options nouvelles (donc peu testées) mais qui ne devraient pas poser de problèmes, (EXPERIMENTAL) pour les options en cours de développement et qui ne devraient être utilisées que par des développeurs ou un public de testeurs conscients des risques encourus. Enfin certaines options portent le label explicite (DANGEROUS), on s'en tiendra à l'écart à moins d'avoir un intérêt particulier à les tester, ces options peuvent parfois présenter des risques d'endommagement du matériel.
Un mot sur les options sous la rubrique “kernel hacking” (et idem pour ce qui concerne “development”, “experimental”, ou les outils de débogage “CONFIG_DEBUG_*”), tout ce qui s'y trouve concerne le développement du noyau, vous n'en avez normalement pas l'utilité et certaines options peuvent pénaliser fortement les performances du noyau, voir sa stabilité. Passez votre chemin donc, sauf si la configuration par défaut de votre distribution inclue des options de cette section, vous pouvez les conserver pour préserver la compatibilité avec certains programmes (traceurs, statistiques de performances, etc…).

Les différentes interfaces de configuration Le choix d'une interface de configuration n'a pas d'implication technique, cela ne changera rien au résultat final que vous utilisiez l'une ou l'autre, c'est une simple question de confort et d'habitude. Il est tout à fait possible de configurer le noyau en modifiant avec un éditeur de texte le fichier “.config”, ou à peine plus élaboré avec “make config”. Nettement plus confortable sans nécessiter de nombreuses dépendances “make nconfig” apportent l'intégration de l'aide et de la recherche, et une navigation rapide. Les fonctions de base de cette interface sont détaillées plus bas dans la page. “xconfig” et “gnomeconfig” nécessitent plus de dépendances et ne fonctionnent qu'au sein d'un environnement de bureau tel que KDE, Gnome, Xfce ou autre.

Quelques exemples d'interfaces de configuration (cliquez une image pour agrandir) :

nconfig” offre une navigation fluide, des panneaux d'aide et d'information en superposition, le support de la transparence et quelques autres raffinements sans nécessiter de dépendance supplémentaire :

Il existe des options de configuration rapide qui peuvent être pratiques :

  • make listnewconfig permet de voir une liste de toutes les nouvelles options, et qui ne sont donc pas encore configurées dans le fichier de configuration.
  • make oldnoconfig configure toutes les nouvelles options (voir ci-dessus) à “N” (no), pratique si vous recherchez la stabilité avant tout et que votre configuration actuelle est éprouvée.
  • make localconfig ne configure que les modules nécessaires à votre système, il faut parfois ajouter des modules pour les appareils connectés ponctuellement. C'est un bon point de départ pour un noyau minimal.


Identifier son noyau avec "EXTRAVERSION"

Si vous désirez différencier clairement votre noyau vous pouvez lui assigner un suffixe personnalisé via la variable “EXTRAVERSION”. Ouvrez le fichier Makefile présent à la racine des sources du noyau, et modifiez la valeur de la variable (au tout début du fichier). Un exemple :

VERSION = 3
PATCHLEVEL = 16
SUBLEVEL = 1
EXTRAVERSION = -perso
NAME = Museum of Fishiegoodies

À noter que cet exemple est tiré d'un noyau réel (3.16.1), la variable “NAME” ayant la valeur donnée par les développeurs du noyau :-). La partie ajoutée est ici “-perso”.

Identifier son matériel

Pour choisir les options de configurations vous aurez besoin de connaître votre matériel, pour cela il y quelques commandes de base qu'il est utile de connaître :

# update-pciids
$ lspci -nnv

La première commande met à jour la base de données des identifiants pci, la seconde liste avec des informations détaillées les périphériques pci présents.

# update-usbids
$ lsusb -v

Comme précédemment mais pour les périphériques usb cette fois.

$ cat /proc/cpuinfo

Vous renseigne sur votre processeur, son modèle et ses capacités (“flags”) comme par exemple le support du mode 64bits (flag “lm”), ou de la virtualisation (flags “vtx” Intel ou “svm” AMD).

Le programme le plus polyvalent est peut-être “hwinfo” (à installer si la commande est inconnue sur votre système). On peut soit invoquer la commande sans option, ou passer en option un type de matériel particulier, par exemple :

# hwinfo --netcard

vous renseignera de manière détaillé sur les périphériques réseaux présent sur votre machine. Pour connaître le liste des options lancez “hwinfo” avec l'option “--help”.

Voyez cette page pour plus de conseils sur le sujet et quelques autres commandes utiles comme “dmidecode” ou “free”.

Ces informations sont surtout importantes si vous souhaitez compiler un noyau minimal, avec uniquement les modules nécessaires à votre matériel et rien de plus. En dehors de cette approche vous compilerez sûrement bien plus que nécessaire sous forme de modules, laissant au noyau le soin de charger le nécessaire. Il y a plusieurs raisons à vouloir limiter le nombre de modules au strict nécessaire, celà conduit à minimiser la taille du noyau ainsi que son empreinte mémoire, ça peut faire partie d'impératifs de sécurisation du poste en empêchant le chargement de modules nécessaires à la prise en charge de certains matériels (par exemple bloquer l'utilisation d'une interface réseau, ou empêcher l'utilisation de clés de stockage usb, de ports d'extention), etc… En dehors de ces cas particuliers il y a peu de bénéfices à procéder de cette façon, et beaucoup de contraintes car les erreurs entraîneront l'impossibilité d'utiliser le matériel, nécessiteront une recompilation du noyau pour corriger le problème, et un tel noyau minimal est “rigide” au niveau du support matériel. Si par exemple vous subissez une panne matériel et devez changer de carte mère, il y a des risques que votre noyau ne vous permette pas de démarrer sur la nouvelle (non reconnaissance d'un contrôleur de disque par exemple).

Initrd (initramfs) ou pas ?

Les mêmes contraintes s'appliquent à un démarrage sans disque intial (initrd), dans ce cas vous aurez compilé les modules nécessaires au démarrage “en dur” au sein du noyau (choix “y” lors de la configuration), et non sous forme de modules. Si le matériel change de manière importante (carte mère,…etc) il faudra recompiler un nouveau noyau pour l'adapter.
Les distributions ont en général une démarche opposée, un nombre maximum de pilotes sont compilés en modules, et seront chargés à la demande, et un disque initial assure le démarrage avec une grande souplesse quant à la prise en charge du matériel (l'initrd embarque un grand nombre de modules, ceux-ci étant adaptés en fonction du matériel détecté lors de la création/mise à jour de l'initrd). Étant donné qu'aujourd'hui la place est rarement un problème sur les disques modernes (sauf à utiliser une partition /boot séparée trop petite), et que la mémoire vive est présente en quantité confortable, cette approche est la plus souple.
Un exemple de choix déterminant en fonction de l'utilisation ou non d'un disque initial de démarrage, le pilote destiné à gérer le système de fichier (exemple “ext3”) de votre partition racine (“/”) doit être compilé en module si vous utilisez un “initrd” (option CONFIG_EXT3_FS=m dans votre fichier de configuration), mais si vous n'en utilisez pas il doit être compilé au sein du noyau (option CONFIG_EXT3_FS=y dans votre fichier de configuration).

Un mot sur l'espace disque nécessaire, si vous testez et installez de nombreuses versions de noyaux simultanément il faut surveiller la place disponible sur /boot ou /. Une image de noyau typique “pèse” quelques Mo (plus si vous avez configuré en “y” de nombreuses options), environ le double pour un disque initial “initrd” car des modules sont inclus dans l'image. Un répertoire des modules peut avoisiner les 100Mo si on a quasiment tout configuré en modules. Le vrai problème vient donc des sources qui une fois compilées (après le “make”) peuvent occuper plusieurs gigaoctets, plus de l'espace temporaire nécessaire à la compilation elle-même. Pour gagner de la place soyez organisé, supprimez les “restes” de compilation, effacer les répertoires de modules et de source qui traînent après désinstallation d'un noyau, exécutez un “make clean” (conserve le fichier de configuration) ou un “make mrproper” (supprime le fichier de configuration) si vous n'avez pas besoin de conserver l'intégralité des sources compilées.

La compilation

Si votre configuration est faite, vous pouvez passer à la compilation. Une simple commande suffit :

$ make

Ensuite il faut un peu de patience, d'autant plus que votre ordinateur est peu puissant. Si vous possédez un ordinateur avec processeur(s) multi-cœurs il est possible d'accélérer la compilation en passant l'option “-j” (--jobs) suivi du nombre de “jobs” (processus) souhaités. Le nombre de processus n'est pas forcément en lien avec le nombre de cœurs/cpu disponibles, il faut parfois tester pour trouver la bonne valeur, comme point de départ “-j 4” réduira le temps de compilation sans trop charger la machine. Si vous constatez que le processeur est encore sous-utilisé augmentez la valeur, si au contraire le système devient très lent, voir quasiment “gelé” pendant la compilation utilisez une valeur plus basse.
Attention, par défaut “make” ne fixe pas de limite à la charge imposée au système, une utilisation un peu optimiste de l'option “-j” (ou en oubliant de mettre une valeur, ce qui équivaux à “nombre de processus illimités”) peut imposer une charge très importante à votre système, entraînant des difficultées à exécuter n'importe quelle autre tâche pendant le “make”, voir entraîner des redémarrages intempestifs ou des pannes matériels par surchauffe (sur des ordinateurs portables en particulier). Pour limiter la charge système maximum voyez l'option “-l” (--load-average) dans le manuel de “make”.

Installation

Votre noyau est prêt à être mis en place, l'idée est de copier l'image du noyau “vmlinuz-version” dans le répertoire /boot (avec son fichier “System.map-version”), de mettre en place les modules dans /lib/modules et d'en créer une “carte” pour le système (commande “depmod”). Ensuite il reste à créer un disque initial de démarrage si nécessaire (avec “mkinitrd” ou “mkinitramfs” selon les distributions), vérifier que les liens symboliques éventuellement présents sont bien à jour : liens “/vmlinuz” ou “/boot/vmlinuz”, “/initrd[.img]” ou “/boot/initrd[.img]” qui pointent respectivement vers le dernier noyau et disque de démarrage initial installés ; liens “build” et “source” dans /lib/modules qui pointent vers le répertoire des sources, et enfin mettre à jour le chargeur d'amorçage (Grub, Grub2, Lilo).
Heureusement il y a un script pour simplifier tout ça, il suffit de passer les commandes :

# make modules_install && make install

Vous devez utiliser des droits root pour cette étape, la seule du processus qui les nécessite. Un mot sur l'emplacement des sources avant de passer cette commande, les liens relatif au sources (“build” et “source”) dans /lib/modules/$(uname -r) pointeront sur le répertoire des sources au moment de l'installation, et seront brisés si par la suite celles-ci sont déplacées. Donc mieux vaut choisir où vous désirez stocker les sources avant d'installer le noyau, le standard est /usr/src/ ou /usr/src/kernels/ en fontion de votre distribution mais il n'y a pas d'inconvénient à différencier l'emplacement de vos sources “maison”. Pour éviter d'éventuels problèmes avec des scripts lors de compilations futures vous pouvez simplement créer un lien symbolique dans /usr/src/(kernels) pointant vers l'emplacement réel.

Appliquer un patch

“patcher” le noyau consiste à intégrer au code source de celui-ci des ajouts provenant d'un fichier appelé “patch”. Celui-ci est un fichier contenant les “différences” (on parle de “delta”) entre deux versions, créé avec le programme “diff”. Le patch est un fichier texte et peut être lu avec n'importe quel éditeur de texte. Pour lire un fichier de patch au format compressé “.bz2” ou “.gz” vous pourrez utiliser respectivement :

$ bzcat patch-version_du_patch.bz2 | less
$ zcat patch-version_du_patch.gz | joe

Ici on utilise une redirection “|” vers un programme permettant une lecture confortable, par exemple “less” ou “joe”.

Un patch peut simplement avoir pour but de passer d'une révision (ou version) de noyau à la suivante, dans ce cas il évite de télécharger l'intégralité des sources à chaque nouvelle révision. D'autres patchs peuvent ajouter des fonctionnalités au noyau, comme pour les patch “rt” (“Real Time”) destiné à compiler des noyaux optimisés pour les travaux en temps réel (très faible latence de réponse).

Appliquer un patch n'a rien de difficile, mais il faut s'assurer que l'on applique la bonne version du patch à la version des sources auxquelles il est destiné, et se souvenir qu'un patch s'applique AVANT la configuration et la compilation des sources. En règle général un patch n'est fait que pour une révision (ou version) du noyau Linux, et ne s'appliquera pas sur une différente. Voyons quelques exemples :

Pour passer à la version 2.6.34 du noyau on appliquera au sources original de la version précédente (2.6.33) le patch “patch-2.6.34.[gz|bz2]” :

Pour un patch compressé en “.gz” :

$ gzip -cd ../patch-2.6.34.bz2 | patch -p1

ou pour un patch compressé en “.bz2” :

$ bzip2 -dc ../patch-2.6.34.bz2 | patch -p1

L'option “-d” force une décompression (sans celle-ci “gzip” et “bzip2” effectuent une compression), et l'option “-c” indique comme destination du fichier décompressé la sortie standard (la console, ce qui permet de rediriger le résultat vers la commande “patch” avec une redirection “|”).

La commande est à effectuer à l'intérieur du répertoire des sources 2.6.33, on suppose que l'archive du patch se situe dans le répertoire de niveau supérieur (../), si vous êtes perdu et que la commande “cd” ne vous dise rien voyez cette page pour savoir se situer et se déplacer en mode console.

Donc de manière générale un patch 2.6.xx s'applique sur des sources 2.6.xx moins un, ce type de patch est parfois appelé “patch de version stable” (“base stable” en Anglais).Si vous n'avez qu'une version 2.6.xx.y vous devez avant tout annuler les patchs précédents. Par exemple si vous possédez des sources 2.6.33.1 vous devez télécharger le patch “patch-2.6.33.1.[gz|)bz2) et le retirer (“to reverse” en Anglais). Pour cela on utilise l'option “-R” :

$ bzip2 -dc ../patch-2.6.33.1.bz2 | patch -R -p1

À la fin du processus vous obtiendrez des sources 2.6.33 prêtes à recevoir un patch de version vers 2.6.34.

Attention à ne pas oublier de modifier le nom du répertoire des sources pour refléter la version après application d'un patch, sinon vous vous retrouverez vite dans un bazar inextricable. Si vous venez d'appliquer un patch 2.6.34 sur des sources 2.6.33, renommer immédiatement après votre répertoire de sources pour refléter la version réelle.

Comme souvent dans le monde GNU-Linux il y a plusieurs façons de faire la même chose, voici quelques autres possibilités pour appliquer un patch :

  • Si le patch n'est pas compressé :
$ patch -p1 < ../patch-2.6.33.4
  • Comme alternative à “gzip -cd” on peut utiliser “gunzip -c” ou “zcat”.
  • Comme alternative à “bzip2 -cd” on peut utiliser “bunzip2 -c” ou “bzcat”.

Un autre type de patch disponible est le patch de révision stable (“mainline stable” en Anglais) qui permet de passer à une révision particulière, par exemple 2.6.33.4. Ce type de patch s'applique sur les sources de la version de base, ici les sources 2.6.33. Une erreur commune est de partir de la révision précédente (ici sources 2.6.33.3), si vous souhaitez partir de sources 2.6.33.3 vous devez d'abord “désappliquer” le patch “patch-2.6.33.3”, avant d'appliquer le patch “patch-2.6.33.4”. C'est clair ? Pour le reste tout se passe exactement comme pour le type précédent, voir ci-dessus pour les commandes.

Enfin on trouve les patchs “incrémentaux” (“incremental mainline”) qui eux s'appliquent à la dernière révision disponible, par exemple le patch “patch-2.6.33.3-4” fera passer une révision 2.6.33.3 à celle 2.6.33.4. Ces patchs incrémentaux se trouve sur une archive dédiée de kernel.org. Leur utilisation est exactement la même que pour les deux versions précédentes. Pour ceux qui auraient râté un épisode, pour appliquer un patch incrémental “patch-2.6.33.3-4.bz2” à des sources “linux-2.6.33.3” on fera (à l'intérieur du répertoire des sources) :

$ bzcat ../patch-2.6.33.3-4.bz2 | patch -p1
$ cd ../
$ mv linux-2.6.33.3/ linux-2.6.33.4/

Les deux lignes qui suivent l'application du patch servent à remonter d'un niveau dans le répertoire qui contient les sources (”../“), puis à renommer le répertoire des sources pour refléter sa révision réelle une fois patché. :!: N'oubliez pas cette étape.

Un dernier exemple avec un patch ”-rt“ pour créer un noyau à très faible latence “temps réel” (“real time” en Anglais). On suppose que vous disposez des sources du noyau 2.6.33.4, et que vous avez téléchargé sur l'archive des patchs "-rt" le patch “patch-2.6.33.4-rt20.bz2”. Vous vous placez dans le répertoire des sources, le patch se trouvant dans le répertoire de niveau supérieur (”../“) :

$ bzcat ../patch-2.6.33.4-rt20.bz2 | patch -p1

Cela ne suffit pas à avoir un noyau ”-rt“, des choix correctes doivent être fait lors de la configuration, mais ça n'est pas l'objet de cet article.

Des options pratiques, des erreurs

“patch” possède quelques options pratique, par exemple :

  • --dry-run” qui permet de simuler l'application d'un patch.
  • -s” (silent) permet de n'avoir que les éventuels messages d'erreur au lieu de la liste complète des opérations effectuées par “patch”. Ça évite de passer à côté d'une erreur au milieu du flot des modification effectuées.
  • –verbose” à l'inverse indique à “patch” de détailler l'intégralité des opérations effectuées. Vu le volume d'informations renvoyées on a intérêt à rediriger la sortie standard vers un pager (“less”, “most”) ou un fichier texte.
  • -R” (revert) permet d'annuler les effets d'un patch.

Pour les patcheurs en série les développeurs ont préparé un script qui permet d'appliquer à la suite une série de patchs présents dans le même répertoire, , en suivant les numéros de versions (plusieurs patchs incrémentaux par exemple). Le script est inclus dans les sources du noyau sous /scripts/patch-kernel. La commande s'utilise en indiquant d'abord le répertoire des sources, ensuite le répertoire où se trouvent les patchs. Par exemple si vous êtes dans le répertoire des sources, et que les patchs se trouvent dans le répertoire de niveau supérieur cela donne :

$ scripts/patch-kernel . ..

Le premier point “.” désigne le répertoire actuel comme celui des sources, les deux points suivant “..” désigne le répertoire de niveau supérieur comme contenant les patchs. Le script sait gérer les différents formats d'archive courant utilisés pour compresser les patchs. Le script lui-même inclus de la documentation en commentaires, ouvrez le dans un éditeur de texte pour en savoir plus.

L'application d'un patch doit se faire sans renvoyer d'erreur, si ça n'est pas le cas soit vous avez fait une bourde (mauvaise concordance entre version de patch et version de source, mauvaise commande), soit l'archive est corrompue, soit le créateur du patch a commis une bévue. La commande “patch” ne possède quasiment pas de mécanismes de correction d'erreurs, seuls de légers problèmes de numérotation de lignes peuvent être outrepassés (on parle de “fuzz” pour désigner ces erreurs minimes). Si l'application d'un patch renvoie des erreurs n'allez pas plus loin, vérifiez tous le processus méticuleusement, puis tournez vous vers le créateur du patch, ou vers une liste de diffusion/un forum pour demander de l'aide.

Si vous avez déjà appliqué un patch, ou que vous cherchiez à l'appliquer sur une mauvaise version des sources vous obtiendrez ce type de message :

Reversed (or previously applied) patch detected!  Assume -R? [n]

Cela signifie que les modifications que le patch doit effectuer ont été détectées comme déjà présentes dans les sources, dans ce cas le comportement par défaut est de passer en mode “revert” (patch -R), et de désappliquer le patch au lieu de l'appliquer.

Si vous avez déjà utilisé les sources pour une compilation, assurez vous de repartir d'un état propre en appliquant la commande :

$ make mrproper

En cas d'erreur “patch” crée un fichier “de rejet” qui contient le détail des erreurs rencontrées, ce fichier a une extention en ”.rej“, par exemple “Makefile.rej”. Lire ce fichier peut aider à comprendre l'origine de l'erreur.

À venir

kernel panic - not syncing
no init found
attempted to kill init!
waiting for root fs ...
unable to mount root fs

Un petit aperçu de ce à quoi on s'expose en compilant son noyau, quelques messages cryptiques au démarrage sur un écran noir, et rien de plus…

Diagnostiquer les messages d'erreurs courants (“kernel panic”, “waiting for root filesystem”, “you must load a kernel first”, “you are so screwed”, …)

Liens



Retour à la page "Expert"

Envoyer un message au mainteneur de cette page

expert/recompilation_noyau.txt · Dernière modification: 2014/09/04 20:08 par idiotein30