Généralités système Linux

kernel - Compiler son kernel Linux

Cet article a été mis à jour, vous consultez ici une archive de cet article!
Table des matières

linux_logomed





Introduction




Le noyau Linux (ou kernel en anglais) est un noyau de système d'exploitation de type UNIX. Le noyau Linux est un logiciel libre développé essentiellement en langage C par des milliers de bénévoles et salariés communiquant par Internet.

Le noyau est le cœur du système, c'est lui qui s'occupe de fournir aux logiciels une interface pour utiliser le matériel.

C'est lui qui amorce le système d'exploitation.

Il est possible d'avoir plusieurs noyaux et utiliser celui de votre choix. Il est recommandé d'avoir toujours un noyau fonctionnel sur sa machine.

Pourquoi compiler son noyau ? Les noyaux fournis par défaut dans votre distribution GNU/Linux sont des noyaux capables de tourner sur un maximum de machines et de matériels. Ils sont donc souvent plus lourds, mais la différence de rapidité est en général assez faible. En fait les vraies raisons de compiler son propre noyau sont les suivantes :

  • Comprendre comment fonctionne le noyau Linux.
  • Faire fonctionner un matériel ou une fonctionnalité qui n'est pas pris en charge par votre noyau actuel.
  • Vous voulez passer le temps.



Tout au long de la démarche, j'ai utilisé le noyau 3.14.33, le dernier LTS en date.

Adaptez avec la version téléchargée.




Prérequis




Pour compiler son noyau, il est nécessaire d'avoir quelques prérequis :

Matériel




Un bon processeur pour que la compilation soit rapide.

Prévoir 1Go de RAM au moins.

Avoir 10Go de place sur le disque dur (partition /usr/src)

Pour info avec un kernel sur serveur assez épuré :

- 1h avec un Intel(R) Pentium(R) D CPU 2.80GHz

- moins de 15mn avec Intel(R) Core(TM) i7-3610QM CPU @ 3.20GHz




Logiciel




Sur la distribution concernée, on a besoin de quelques logiciels :

  • wget : pour télécharger les sources du noyau (ou un navigateur Internet en graphique)
  • tar : pour extraire l'archive du noyau
  • xz : pour décompresser le noyau
  • ncurses : pour afficher le menu de configuration
  • make : pour lancer le processus de compilation
  • gcc (c++) : le compilateur C
  • dracut : le générateur d'image initramfs



Les paquets se nomment ainsi suivant les distributions:

  • Gentoo / Calculate Linux : net-misc/wget app-arch/tar app-arch/xz-utils sys-libs/ncurses sys-devel/make sys-devel/gcc sys-kernel/dracut
  • Mageia : wget tar xz ncurses-devel make gcc-c++





Mise en oeuvre




Dans un premier temps, il est nécessaire de se connecter en root.

Toutes les commandes doivent être lancées en root.

Récupération des ressources




Depuis le site officiel (base de cet article)




On se positionne dans le dossier /usr/src . C'est le dossier qui contient des fichiers de code source, selon la norme FHS (File Hierarchy Standard)

Code BASH :
cd /usr/src


On récupère ensuite le kernel depuis le site kernel.org (Je prends, en date de la rédaction de cet article le dernier noyau LTS : 3.14.33 )

kernel_org



Code BASH :
wget https://www.kernel.org/pub/linux/kernel/v3.x/linux-3.14.33.tar.xz


On décompresse ensuite l'archive compressée :

Code BASH :
tar -xf linux-3.14.33.tar.xz


Et on se rend dans le dossier précédemment désarchivé

Code BASH :
cd linux-3.14.33




Depuis les sources de la distribution




Gentoo



Par défaut, le paquetage gentoo-source n'installe ni ne compile le kernel. Il s'agit donc des sources directement :)

Code BASH :
emerge -avq gentoo-sources


Se rendre ensuite dans le dossier des sources :

Code BASH :
cd /usr/src


Calculate Linux



Sous Calculate Linux, désactiver les 2 FLAG suivants :

-minimal pour demander à emerge de télécharger les sources complètes ;

-vmlinuz pour éviter la compilation automatique, en faveur de la prise en charge manuelle du noyau.


Puis réinstaller le kernel :

Code BASH :
echo "sys-kernel/calculate-sources -minimal -vmlinuz" >> /etc/portage/package.use/custom
emerge -avq calculate-sources


Se rendre ensuite dans le dossier des sources :

Code BASH :
cd /usr/src




Mageia



Chez Mageia, pour récupérer directement les sources, on peut utiliser le paquet kernel-source-$version ou kernel-source-latest pour la dernière version empaquetée chez Mageia

Code BASH :
urpmi kernel-source-latest


Se rendre ensuite dans le dossier des sources :

Code BASH :
cd /usr/src




Préparation à la compilation




On nettoie le dossier et on le prépare pour la compilation:

Code BASH :
make mrproper


On peut recupérer la config en cours via :

Code BASH :
zcat /proc/config.gz > .config


Si on ne le fait pas, ce sera une config par "défaut" et minimale qui sera appliquée.

Caché :
Ensuite, vu que le kernel à compiler n'est sûrement pas dans la même version, il faut voir s'il y a eu des modifications dans la configuration :

Code BASH :
make oldconfig


Ce mode est interactif sur toutes les nouvelles options.

Caché :
Code TEXT :
  HOSTCC  scripts/basic/fixdep
  HOSTCC  scripts/kconfig/conf.o
  SHIPPED scripts/kconfig/zconf.tab.c
  SHIPPED scripts/kconfig/zconf.lex.c
  SHIPPED scripts/kconfig/zconf.hash.c
  HOSTCC  scripts/kconfig/zconf.tab.o
  HOSTLD  scripts/kconfig/conf
scripts/kconfig/conf --oldconfig Kconfig
#
# using defaults found in /boot/config-3.14.27-calculate
#
#
# configuration written to .config
#
 


Il se peut que des questions soient posées. C'est dans le cas ou les options du kernel à installer sont nouvelles par rapport à celui en cours d'exécution. Laisser les choix par défaut. en validant simplement les questions.

Si on souhaite configurer les nouvelles par défaut, utiliser :

Code BASH :
make silentoldconfig




La personnalisation




Pour régler les options dans le futur noyau, et affiner la configuration, on exécute la commande suivante :

Code BASH :
make menuconfig


On a ensuite une petite interface de type "ncurses" dans la console :

kernel_menuconfig



On navigue dans les menus avec les flèches haut et bas.

Les touches gauche et droite permettent de naviguer dans le menu en dessous et Entrée pour valider le choix.

  • Select permet de sélectionner le menu en surbrillance ou de changer une valeur (un texte)
  • Exit permet de revenir au menu précédent
  • Help permet d'avoir de l'aide sur le menu en cours
  • Save permet de sauvegarder les modifications dans le fichier .config
  • Load permet de restaurer une configuration



On personnalise les options, par exemple, dans "General Setup" puis "Local Version" on peut mettre un suffixe au à la version du noyau, de notre choix :

kernel_menuconfig_personnalisation



On peut appuyer sur "?" pour avoir de l'aide (English of course!) sur l'option en question :

kernel_menuconfig_help



Si on cherche une option particulière, on peut afficher le formulaire de recherche via / (comme pour vi) et taper le terme souhaité. Les différents chemins pour accéder à l'option sont affichées :

METTRE UNE CAPTURE

Il n'existe pas que des menus et des options de type texte.

Par exemple, si on va dans les FileSystems, on voit plusieurs possibilités pour chaque option :

Code TEXT :
< >
< M >
[ * ]


  • < > : Driver non compilé
  • < M > : Driver dynamique appelé module. Un module est compilé mais n'est pas lié au noyau. Un module sera chargé au boot du PC par un service du noyau en fonction des matériels réellement présents dans le PC. On pourra aussi charger manuellement un module si l'on veut (commande insmod).
  • [ * ] : Le driver est compilé et lié de façon statique avec le noyau. On ne peut pas le retirer de la mémoire même si l'on ne s'en sert pas. On voit que si l'on incorpore tous les drivers dans le noyau, celui-ci devient énorme en taille et va contenir tout un tas de drivers inutiles car ne correspondant pas à un matériel présent dans le PC.



Par défaut, les options sont bien réglées.

On garde uniquement les * pour les éléments de base nécessaire au bon fonctionnement.

Le reste, en modules M.

Il est important de mettre de façon statique (*) les systèmes de fichiers (ext4, dev, ...), les pilotes du disque dur (SATA, RAID, ...) pour éviter de se retrouver avec un "kernel panic" au démarrage.

Code TEXT :
Device Drivers --->
  Generic Driver Options --->
    [*] Maintain a devtmpfs filesystem to mount at /dev


Code TEXT :
File systems --->
(Select one or more of the following options as needed by your system)
  <*> Second extended fs support
  <*> Ext3 journalling file system support
  <*> The Extended 4 (ext4) filesystem
  ...
  Pseudo Filesystems --->
    [*] /proc file system support
    [*] Virtual memory file system support (former shm fs)


On peut penser aussi aux processeurs multi-coeurs :

Code TEXT :
Processor type and features  --->
  [*] Symmetric multi-processing support
 


Et aux ports USB :

Code TEXT :
Device Drivers --->
  [*] HID Devices  --->
    <*>   USB Human Interface Device (full HID) support






Les modules ( < M > ) sont chargés à la demande. Si on met tout en drivers intégrés ( [ * ] ), on les charge au démarrage, le noyau est lourd et on ne peut pas les désactiver post-démarrage.

kernel_menuconfig_filesystems



Ensuite au sauvegarde la configuration en allant sur <Save>

kernel_menuconfig_save





La compilation




On lance ensuite la compilation :

Code BASH :
make


On peut lancer plus de processus make pour aller plus vite.

Si on a 8 coeurs sur le CPU, utiliser l'option -j avec nb cœurs + 1 :

Code BASH :
make -j9


Attention, cette étape est très gourmande en CPU !!!!!

kernel_make8



Caché :
Code TEXT :
scripts/kconfig/conf --silentoldconfig Kconfig
  SYSHDR  arch/x86/syscalls/../include/generated/uapi/asm/unistd_32.h
  SYSHDR  arch/x86/syscalls/../include/generated/uapi/asm/unistd_64.h
  SYSHDR  arch/x86/syscalls/../include/generated/uapi/asm/unistd_x32.h
  SYSTBL  arch/x86/syscalls/../include/generated/asm/syscalls_32.h
  SYSHDR  arch/x86/syscalls/../include/generated/asm/unistd_64_x32.h
  SYSHDR  arch/x86/syscalls/../include/generated/asm/unistd_32_ia32.h
  SYSTBL  arch/x86/syscalls/../include/generated/asm/syscalls_64.h
  CHK     include/config/kernel.release
  WRAP    arch/x86/include/generated/asm/clkdev.h
  UPD     include/config/kernel.release
  CHK     include/generated/uapi/linux/version.h
  UPD     include/generated/uapi/linux/version.h
  CHK     include/generated/utsrelease.h
  UPD     include/generated/utsrelease.h
  HOSTCC  scripts/kallsyms
  HOSTCC  scripts/conmakehash
  HOSTCC  scripts/bin2c
  HOSTCC  scripts/sortextable
  CC      scripts/mod/empty.o
  HOSTCC  scripts/mod/mk_elfconfig
  CC      scripts/mod/devicetable-offsets.s
  GEN     scripts/mod/devicetable-offsets.h
[........]
  IHEX    firmware/ti_3410.fw
  IHEX    firmware/ti_5052.fw
  IHEX    firmware/mts_cdma.fw
  H16TOFW firmware/edgeport/boot.fw
  H16TOFW firmware/edgeport/down.fw
  H16TOFW firmware/edgeport/boot2.fw
  IHEX    firmware/mts_edge.fw
  IHEX    firmware/mts_gsm.fw
  H16TOFW firmware/edgeport/down2.fw
  IHEX2FW firmware/whiteheat_loader.fw
  IHEX2FW firmware/keyspan_pda/keyspan_pda.fw
  IHEX2FW firmware/keyspan_pda/xircom_pgs.fw
  IHEX    firmware/cpia2/stv0672_vp4.bin
  IHEX    firmware/edgeport/down3.bin
  IHEX2FW firmware/whiteheat.fw
real    13m58.388s
user    96m55.100s
sys     7m51.510s




L'installation




Une fois la compilation terminée, on installe les modules :

Code BASH :
make modules_install


Caché :
Code TEXT :
  INSTALL arch/x86/crypto/aes-x86_64.ko
  INSTALL arch/x86/crypto/aesni-intel.ko
  INSTALL arch/x86/crypto/camellia-aesni-avx-x86_64.ko
  INSTALL arch/x86/crypto/camellia-aesni-avx2.ko
  INSTALL arch/x86/crypto/camellia-x86_64.ko
  INSTALL arch/x86/crypto/crc32-pclmul.ko
  INSTALL arch/x86/crypto/crct10dif-pclmul.ko
[...]
  INSTALL /lib/firmware/edgeport/down3.bin
  INSTALL /lib/firmware/whiteheat_loader.fw
  INSTALL /lib/firmware/whiteheat.fw
  INSTALL /lib/firmware/keyspan_pda/keyspan_pda.fw
  INSTALL /lib/firmware/keyspan_pda/xircom_pgs.fw
  INSTALL /lib/firmware/cpia2/stv0672_vp4.bin
  DEPMOD  3.14.33


Ils s'installent dans /lib(64)/modules/3.14.33/kernel

Cet ensemble de sous-répertoires contient les drivers pour accéder aux différents matériels présents dans le PC.

On installe ensuite le noyau :

Code BASH :
make install


Caché :
Code :
sh /usr/src/linux-3.14.33/arch/x86/boot/install.sh 3.14.33 arch/x86/boot/bzImage \
        System.map "/boot"


On vérifie que les fichiers se sont bien installés :

Code BASH :
ls /boot/*3.14.33*
/boot/config-3.14.33-adrien  /boot/System.map-3.14.33-adrien  /boot/vmlinuz-3.14.33-adrien


Les fichiers :

  • vmlinuz-3.14.33-adrien : C'est le noyau Linux.
  • System.map-3.14.33-adrien : C'est la table des symboles du noyau. C'est un fichier ASCII qui donne la correspondance entre un symbole du noyau (étiquette, fonction, variable...) et son adresse en mémoire. Cela sert par exemple à débugger le noyau au niveau symbolique.
  • config-3.14.33-adrien : C'est le fichier de configuration de la compilation qui a servi à générer le noyau Linux.



Dans la plupart des cas, cette configuration fonctionne.

Néanmoins, il peut être utile de générer aussi un fichier initramfs.

Générer le initramfs




La commande mkinitrd est contenue dans le paquet dracut pour la plupart des distributions !

Le fichier à générer est initramfs-version.img.

C'est un fichier spécial qui contient un RAM Disk. C'est comme son nom l'indique un système de fichiers minimaliste chargé en RAM au démarrage du noyau qui contient les “drivers” nécessaires au boot du noyau. Ce RAM Disk est bien sûr détruit après boot complet du noyau.

Pour le générer on utilise la commande mkinitrd :

Code BASH :
mkinitrd /boot/initramfs-$version.img $version 


Voici un exemple :

Code BASH :
mkinitrd /boot/initramfs-3.14.33-adrien.img 3.14.33-adrien




Modifier le fichier de GRUB




Il ne reste plus qu'à générer le fichier de GRUB2 pour lister dans le chargeur d'amorçage le nouveau kernel compilé :

(la localisation peut différer suivant les distributions)

Code BASH :
grub-mkconfig -o /boot/grub/grub.cfg 


Voici un exemple de sortie :

Code TEXT :
Création du fichier de configuration GRUB…
Arrière-plan trouvé : /boot/grub/grub-calculate.png
Image Linux trouvée : /boot/vmlinuz-3.14.33-adrien
Image mémoire initiale trouvée : /boot/initramfs-3.14.33-adrien.img
Image Linux trouvée : /boot/vmlinuz-3.14.27-calculate
Image mémoire initiale trouvée : /boot/initramfs-3.14.27-calculate.img
Image Linux trouvée : /boot/vmlinuz-3.14.27-SafeMode-calculate
Image mémoire initiale trouvée : /boot/initramfs-3.14.27-SafeMode-calculate.img
  No volume groups found
fait


Notre noyau est bien trouvé avec son initramfs.



Redémarrage et test




On redémarre et on teste notre nouveau noyau.

A la reconnexion on vérifie la version du kernel :

Code BASH :
uname -a


Dans mon exemple, tout est pris en compte

Code TEXT :
Linux tuto-kernel 3.14.33-adrien #2 SMP Fri Feb 20 18:30:58 CET 2015 x86_64 Intel(R) Core(TM) i7-3610QM CPU @ 2.30GHz GenuineIntel GNU/Linux




Problèmes connus




Aucun module ne se charge




Si aucun module ne veut se charger (par exemple, pour le pilote réseau, modprobe e1000e) et que le message d'erreur est FATAL not found, vérifier

Code BASH :
[*] Enable loadable module support  --->
   [*]   Compress modules on installation
          Compression algorithm (XZ)  --->


Si XZ est actif, vérifier les USE de sys-apps/kmod. Si le USE lzma n'est pas actif, l'activer ou désactiver la compression des modules dans la configuration du kernel.

:magic: