Objectifs du chapitre
- Composants du Kernel (noyau linux).
- Compilation et installation du Kernel.
- Patch Kernel.
- Personnalisation, build et installation de modules Kernel.
- Gestion du Kernel et des modules Kernel lors de l’exécution.
1. Définition
Le kernel (noyau) est le programme qui constitue le cœur du système d’exploitation, le pont entre le software et le hardware.
- Il interagit rarement avec l’utilisateur : il interagit avec le Shell et d’autres programmes d’un côté, et avec le Hardware (CPU, mémoire, disques durs…) de l’autre.
- C’est le premier programme du système d’exploitation chargé en mémoire durant la séquence de démarrage, et il y réside pendant toute la durée de la session.
Le noyau entoure le matériel, la bibliothèque C (glibc) l’entoure à son tour, puis viennent les applications. Une application peut aussi faire des appels directs en assembleur.
2. Noyau modulaire et monolithique
Un noyau modulaire est un ensemble de modules et de pilotes compilés que le noyau peut charger et supprimer à la demande (tous les modules chargeables sont représentés par un fichier objet dans /lib/modules).
Un noyau monolithique a tous ses modules embarqués dans le noyau et supporte un grand nombre de configurations matérielles, de technologies réseau et de systèmes de fichiers.
| Noyau | Avantages |
|---|---|
| Modulaire | Charge et décharge des modules à la demande (économie de mémoire). Pas besoin d’arrêter le système pour ajouter un pilote. |
| Monolithique | Haute disponibilité. Support d’un grand nombre de configurations matérielles. |
3. Fonctions du kernel et appels système
Le kernel offre à tous les éléments du système d’exploitation des services de base :
- Gestion de la mémoire
- Gestion des processus
- Gestion du système de fichiers
- Gestion des E/S
- Communication interprocessus
- Gestion de l’accès aux périphériques
- Gestion des protocoles réseaux
Toute communication avec ces services passe par des appels système, fournis par une interface appelée « system call interface ».
| Mode | Accès et rôle | Crash |
|---|---|---|
| Kernel mode (kernel space) | Accès complet et sans restriction à la couche hardware : le code peut exécuter n’importe quelle instruction CPU, agir sur la mémoire, etc. Réservé aux fonctions bas niveau les plus « trusted ». | Catastrophique, cause souvent l’arrêt de la machine. |
| User mode (user space) | Pas d’accès direct au hardware : le code délègue si besoin des tâches à la system call interface. | Récupérable : cette isolation offre une bonne protection. |
4. Composants du Kernel
| Le cœur du Kernel | Les modules du Kernel | |
|---|---|---|
| Nature | Partie irréductible du noyau, chargée intégralement en mémoire par le bootloader. | Fichiers portant l’extension .ko, chargés lors du démarrage. Peuvent être chargés et déchargés à volonté après le chargement du Kernel. |
| Emplacement | Un fichier dans /boot, dont la taille est de quelques Mo. | /lib/modules/linux-version/ |
| Contenu | zImage, bzImage | Sous-répertoires drivers/, net/, sound/, fs/… |
5. Manipulation des modules
| Commande | Fonctionnalité |
|---|---|
lsmod | Affichage des modules chargés en mémoire |
rmmod nom_module ou modprobe -r nom_module | Retrait d’un module chargé en mémoire |
insmod fichier_module ou modprobe nom_module | Chargement d’un module en mémoire |
modprobe -v | Affiche les dépendances des modules |
# modinfo vfat
# insmod /lib/modules/$(uname -r)/kernel/fs/fat/vfat.ko
# lsmod | grep vfat
# rmmod vfat
# modprobe vfat
# modprobe -r vfat
modprobe lit les dépendances des modules dans modules.dep, un fichier généré après l’installation des modules ou par la commande depmod -a.
Chargement forcé d’un module
Les modules sont en principe chargés au démarrage en fonction de la détection du matériel présent. Il est toutefois possible de forcer le chargement d’un module en alimentant un fichier de configuration.
- Red Hat 7 : tout module mentionné dans le répertoire
/etc/sysconfig/moduleset/ou dans/etc/nom_modules.modulesest chargé inconditionnellement au démarrage. - Red Hat 7 et 8 : le démon
systemd-modules-load.servicecharge les modules listés dans un fichierprogram.confcréé dans/etc/modules-load.d/.
Exemple pour charger le module virtio-net.ko : créer /etc/modules-load.d/virtio-net.conf contenant le nom du module.
virtio-net
Le ramdisk et la configuration des modules
Au démarrage, le gestionnaire d’amorçage charge le noyau et les modules correspondant à la configuration matérielle. Pour accélérer la détection du matériel et le chargement des modules associés, la plupart des systèmes modernes exploitent un ramdisk contenant l’ensemble des modules. Il est généré après la compilation du noyau et appelé directement par le gestionnaire de démarrage.
Le fichier utilisé par modprobe pour charger les modules est /etc/modules.conf ou /etc/modprobe.conf (sous OpenSUSE : /etc/modprobe.conf/nom_module.conf). Il contient la manière de charger les modules, les alias, les paramètres à utiliser et les commandes à exécuter.
6. Versioning et version du noyau
La version du noyau Linux s’écrit X.Y.Z.a :
| X | Y | Z | a |
|---|---|---|---|
| major | minor | revision | release |
La commande uname [options] affiche la version du noyau :
| Option | Affichage |
|---|---|
-r | La version du noyau |
-s | Le nom du système d’exploitation |
-p | Le type de processeur |
[root@test /]# uname -s
Linux
[root@test /]# uname -r
2.6.3-7mdk
[root@test /]# uname -a
Linux linux 2.6.3-7mdk #1 Wed Mar 27 13:57:05 UTC 2002 i686 unknown
7. Procédure de compilation et installation du noyau
Deux façons d’obtenir un noyau :
- Installer un Kernel précompilé offert par la distribution à l’aide de l’outil de gestion de paquets (Apt, Yum).
- Télécharger le code source du Kernel, le compiler puis le charger dans le système (très utile pour personnaliser son Kernel).
La procédure de compilation doit toujours être consultée dans le fichier README présent avec les sources du noyau. Les éléments spécifiques du noyau sont documentés dans le répertoire Documentation fourni avec les sources.
1. Récupération des sources
Le code source est téléchargeable librement depuis http://www.kernel.org, sous forme d’une archive tar.gz, tar.bz2 ou tar.xz qu’il faut d’abord décompresser.
2. Génération du fichier de réponse
La configuration et la compilation se font avec l’outil make, qui appelle le compilateur en appliquant les indications du fichier Makefile. La compilation s’effectue en fonction du fichier .config, à la racine du répertoire des sources (généralement /usr/src/linux-version, mais /usr/src/kernels/linux-version sous CentOS).
Le fichier .config indique pour chaque élément du noyau s’il doit être présent dans le cœur du noyau, présent sous forme de module, ou absent du noyau compilé.
| Commande | Effet |
|---|---|
make mrproper | Supprime l’ancienne configuration du kernel (.config) |
make config | Pose la question à l’utilisateur pour chacun des modules |
make menuconfig | Interface texte améliorée, utilisable sur ssh (paquetage libncurses-dev requis) |
make xconfig | Interface graphique basée sur QT, à partir du noyau 2.6 (paquetage libqt3-mt-dev et compilateur g++ requis) |
make gconfig | Interface graphique basée sur GTK, noyau 2.6 (paquetages libgtk2.0-dev, libglade2-dev, libglib2.0-dev requis) |
make defconfig | Génère un .config en s’appuyant sur des valeurs par défaut |
make oldconfig | Génère un fichier de réponse en s’appuyant sur le .config déjà utilisé pour une version plus ancienne |
3. Compilation du noyau et des modules
La compilation se réalise en tapant make depuis le répertoire racine des sources. Elle appelle aussi la commande depmod, qui génère le fichier modules.dep. Parfois on n’a besoin que de l’image du kernel, ou de compiler seulement des modules.
| Commande | Effet |
|---|---|
make bzImage ou make zImage | Compiler seulement le kernel |
make modules | Compiler seulement les modules |
4. Installation du noyau et des modules
Manuellement : copier l’image du kernel compilé et le fichier system.map sous /boot, puis copier les modules compilés sous /lib/modules. On peut aussi recourir à make :
| Commande | Effet |
|---|---|
make install | Installer l’image du kernel et les modules sous /boot |
make modules_install | Installer les modules : ils sont copiés dans /lib/modules, sous un répertoire correspondant à la version du noyau |
5. Création du ramdisk des modules
Il faut mettre à la disposition du noyau un ramdisk contenant l’ensemble des modules compilés pour la nouvelle version. Ce ramdisk nécessite un fichier image (archive cpio compressée au format gzip), construit avec mkinitrd (la commande historique, qui tend à disparaître) ou mkinitramfs, selon la génération du système.
# mkinitrd /boot/initrd-linux-version.img linux-version
# mkinitramfs -o /boot/initramfs-linux-version.img linux-version
linux-version correspond au répertoire des modules situés dans /lib/modules.
6. Configuration du gestionnaire de démarrage
Il ne suffit pas d’avoir compilé le noyau et de l’avoir placé au bon endroit : le gestionnaire de démarrage doit être configuré pour charger ce noyau, en y ajoutant une entrée en conséquence. Il ne faut rien retirer à la configuration existante : on ne touche pas à ce qui marche déjà.
8. Modification dynamique des paramètres du noyau
Le noyau peut être ajusté dynamiquement à travers des paramètres du système, accessibles et modifiables dans les fichiers du répertoire /proc/sys.
# echo 32768 > /proc/sys/fs/file-max
# echo 20 > /proc/sys/kernel/panic
La première commande modifie le nombre maximal de fichiers que le système peut ouvrir simultanément. La seconde demande au noyau de ne pas boucler sur une panique mais de redémarrer automatiquement après 20 secondes.
Pour mémoriser les paramètres à appliquer au démarrage, on utilise le fichier /etc/sysctl.conf. En cours d’exécution, les paramètres peuvent aussi être modifiés par la commande sysctl ou directement dans /proc/sys.
# fichier /etc/sysctl.conf
net.ipv4.ip_forward = 0
# sysctl -w net.ipv4.ip_forward=1
# echo 1 > /proc/sys/net/ipv4/ip_forward
9. Identifier le matériel : lspci, lsusb, lsdev
| Commande | Rôle |
|---|---|
lspci | Affiche des informations sur tous les bus PCI du système et tous les périphériques qui y sont connectés. lspci -s 00:03.0 -v affiche le détail du périphérique réseau. |
lsusb | Semblable à lspci, pour les bus USB et leurs périphériques. Le noyau doit prendre en charge l’interface /proc/bus/usb (Linux 2.3.15 ou plus récent). lsusb -v fournit des informations détaillées. |
lsdev | Affiche des informations sur le matériel installé, rassemblées depuis les interruptions, les fichiers DMA et /proc. Donne un aperçu rapide du périphérique qui utilise les adresses d’E/S et les canaux IRQ/DMA. |
Fichiers utilisés par lsdev : /proc/interrupts, /proc/ioports, /proc/dma.
10. udev
udev est un gestionnaire de périphériques remplaçant devfs dans le noyau Linux depuis la version 2.6, dont la fonction principale est de gérer les périphériques du répertoire /dev.
- Il s’exécute en mode utilisateur et écoute le socket
netlinkpour communiquer avec le noyau. - Il se compose d’un démon utilisateur (
udevd) qui reçoit des « uevents » du noyau. - La communication entre l’espace utilisateur et le noyau se fait via le pseudo système de fichiers
sysfs. - Une règle udev associe par exemple l’adresse MAC de chaque interface à un nom (
eth0,eth1).
Fichiers de configuration
Le répertoire /etc/udev/ contient la configuration et les fichiers de règles d’udev, udev.conf étant le principal fichier de configuration. Les règles sont lues à partir des fichiers du répertoire par défaut /lib/udev/rules.d/.
Exemple de règle :
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:21:86:9e:c2:c4", ATTR{type}=="1", KERNEL=="eth*", NAME="eth0"
udevadm control --reload-rules && udevadm trigger
udevadm info -a -p $(udevadm info -q path -n /dev/namedevice)
udevadm info -q all -p /sys/class/net/*
Systemd et udev
cat /usr/lib/systemd/network/99-default.link
[Link]
NamePolicy=kernel database onboard slot path
MACAddressPolicy=persistent
Si le noyau utilise le mode persistant, udev ne renomme pas l’interface. Sinon, udev la renomme avec le nom fourni par la base de données matérielle d’udev.
On peut changer le nom d’un périphérique via systemd en éditant /etc/systemd/network/70-custom-ifnames.link, puis en redémarrant (reboot).
[Match]
MACAddress=00:0c:29:9c:00:76
[Link]
Name=eth0
11. Patch du noyau
Pour bénéficier d’un noyau récent, on peut télécharger les sources du noyau, les compiler et les installer en tant que nouveau noyau. Une méthode alternative consiste à utiliser les sources de l’ancien noyau et à les patcher avant de les recompiler.
- On ne peut appliquer que le patch de la version qui suit EXACTEMENT la version actuelle du kernel.
- Les patchs se téléchargent sur http://www.kernel.org.
- Le patch s’applique en général avec la commande
patch, ou avec le scriptpatch-kernellivré dans le répertoirescriptsdes sources du noyau. - Un fichier de patch est le résultat d’une commande
diffappliquée à deux arborescences de sources différentes : il contient une référence à chacun des fichiers qui doivent être modifiés. - Si le niveau hiérarchique des fichiers décrits dans le patch ne correspond pas à celui des sources à modifier, le paramètre
-ppermet de décaler cette hiérarchie.
| Action | Commande |
|---|---|
| Ajout de patch | patch -pn < fichier_patch |
| Retrait de patch | patch -pn -R < fichier_patch |
-pn dépend de la conception du fichier de patchs et remonte de n niveaux hiérarchiques dans le chemin des fichiers. -R retire le patch au lieu de l’appliquer. fichier_patch est le fichier contenant les patchs.