Une introduction aux processus d’amorçage et de démarrage de Linux
Comprendre les processus d’amorçage et de démarrage de Linux est important pour pouvoir à la fois configurer Linux et résoudre les problèmes de démarrage. Cet article présente un aperçu de la séquence de démarrage à l’aide du chargeur d’amorçage GRUB2 et de la séquence de démarrage telle qu’elle est exécutée par le système d’initialisation systemd.
En réalité, deux séquences d’événements sont nécessaires pour démarrer un ordinateur Linux et le rendre utilisable : le démarrage et le démarrage. La séquence de démarrage commence lorsque l’ordinateur est allumé, et se termine lorsque le noyau est initialisé et que systemd est lancé. Le processus de démarrage prend alors le relais et termine la tâche de mettre l’ordinateur Linux dans un état opérationnel.
Dans l’ensemble, le processus de démarrage et d’amorçage de Linux est assez simple à comprendre. Il comprend les étapes suivantes qui seront décrites plus en détail dans les sections suivantes.
- POST du BIOS
- Chargeur de démarrage (GRUB2)
- Initialisation du noyau
- Démarrer systemd, le parent de tous les processus.
Notez que cet article couvre GRUB2 et systemd parce qu’ils sont le chargeur de démarrage et le logiciel d’initialisation actuels pour la plupart des principales distributions. D’autres options logicielles ont été utilisées historiquement et se trouvent encore dans certaines distributions.
Le processus d’amorçage
Le processus d’amorçage peut être initié de l’une des deux façons suivantes. Tout d’abord, si l’alimentation est coupée, la mise sous tension de l’ordinateur lancera le processus de démarrage. Si l’ordinateur exécute déjà un utilisateur local, y compris root ou un utilisateur non privilégié, l’utilisateur peut lancer de manière programmatique la séquence de démarrage en utilisant l’interface graphique ou la ligne de commande pour lancer un redémarrage. Un redémarrage fera d’abord un arrêt puis redémarrera l’ordinateur.
POSBIOS
La première étape du processus de démarrage de Linux n’a vraiment rien à voir avec Linux. Il s’agit de la partie matérielle du processus de démarrage et elle est la même pour tout système d’exploitation. Lorsque l’ordinateur est mis sous tension pour la première fois, il exécute le POST (Power On Self Test) qui fait partie du BIOS (Basic I/O System).
Lorsqu’IBM a conçu le premier PC en 1981, le BIOS a été conçu pour initialiser les composants matériels. POST est la partie du BIOS dont la tâche est de s’assurer que le matériel de l’ordinateur a fonctionné correctement. Si POST échoue, l’ordinateur peut ne pas être utilisable et le processus d’amorçage ne se poursuit donc pas.
Le POST du BIOS vérifie l’opérabilité de base du matériel, puis il émet une interruption BIOS, INT 13H, qui localise les secteurs d’amorçage sur tout périphérique amorçable connecté. Le premier secteur d’amorçage qu’il trouve et qui contient un enregistrement d’amorçage valide est chargé en RAM et le contrôle est ensuite transféré au code qui a été chargé à partir du secteur d’amorçage.
Le secteur d’amorçage est en réalité la première étape du chargeur d’amorçage. Il existe trois chargeurs d’amorçage utilisés par la plupart des distributions Linux, GRUB, GRUB2 et LILO. GRUB2 est le plus récent et est utilisé beaucoup plus fréquemment de nos jours que les autres options plus anciennes.
GRUB2
GRUB2 signifie » GRand Unified Bootloader, version 2 » et c’est maintenant le chargeur d’amorçage principal de la plupart des distributions Linux actuelles. GRUB2 est le programme qui rend l’ordinateur juste assez intelligent pour trouver le noyau du système d’exploitation et le charger en mémoire. Parce qu’il est plus facile d’écrire et de dire GRUB que GRUB2, je peux utiliser le terme GRUB dans ce document mais je ferai référence à GRUB2 sauf indication contraire.
GRUB a été conçu pour être compatible avec la spécification multiboot qui permet à GRUB de démarrer de nombreuses versions de Linux et d’autres systèmes d’exploitation libres ; il peut également charger en chaîne l’enregistrement de démarrage de systèmes d’exploitation propriétaires.
GRUB peut également permettre à l’utilisateur de choisir de démarrer parmi plusieurs noyaux différents pour toute distribution Linux donnée. Cela offre la possibilité de démarrer sur une version précédente du noyau si un noyau mis à jour échoue d’une manière ou d’une autre ou est incompatible avec un logiciel important. GRUB peut être configuré à l’aide du fichier /boot/grub/grub.conf.
GRUB1 est maintenant considéré comme un héritage et a été remplacé dans la plupart des distributions modernes par GRUB2, qui est une réécriture de GRUB1. Les distros basées sur Red Hat ont effectué une mise à niveau vers GRUB2 autour de Fedora 15 et CentOS/RHEL 7. GRUB2 fournit la même fonctionnalité de démarrage que GRUB1, mais GRUB2 est également un environnement de pré-système d’exploitation basé sur des commandes de type mainframe et permet plus de flexibilité pendant la phase de pré-système d’exploitation. GRUB2 est configuré avec /boot/grub2/grub.cfg.
La fonction principale de l’un ou l’autre des GRUB est d’obtenir le noyau Linux chargé en mémoire et de le faire fonctionner. Les deux versions de GRUB fonctionnent essentiellement de la même manière et ont les mêmes trois étapes, mais je vais utiliser GRUB2 pour cette discussion sur la façon dont GRUB fait son travail. La configuration de GRUB ou GRUB2 et l’utilisation des commandes GRUB2 sortent du cadre de cet article.
Bien que GRUB2 n’utilise pas officiellement la notation des étapes pour les trois étapes de GRUB2, il est pratique de s’y référer de cette façon, donc je le ferai dans cet article.
Étape 1
Comme mentionné dans la section POST du BIOS, à la fin du POST, le BIOS recherche sur les disques attachés un enregistrement de démarrage, généralement situé dans le Master Boot Record (MBR), il charge le premier qu’il trouve en mémoire et commence ensuite l’exécution de l’enregistrement de démarrage. Le code d’amorçage, c’est-à-dire GRUB2 stage 1, est très petit car il doit tenir dans le premier secteur de 512 octets du disque dur avec la table de partition. L’espace total alloué au code d’amorçage réel dans un MBR générique classique est de 446 octets. Le fichier de 446 octets de l’étape 1 est nommé boot.img et ne contient pas la table de partition qui est ajoutée à l’enregistrement de démarrage séparément.
Parce que l’enregistrement de démarrage doit être si petit, il n’est pas non plus très intelligent et ne comprend pas les structures des systèmes de fichiers. Par conséquent, le seul but de l’étape 1 est de localiser et de charger l’étape 1.5. Pour ce faire, l’étape 1.5 de GRUB doit être située dans l’espace entre l’enregistrement de démarrage lui-même et la première partition du disque. Après avoir chargé l’étape 1.5 de GRUB dans la RAM, l’étape 1 passe le contrôle à l’étape 1.5.
Etape 1.5
Comme mentionné ci-dessus, l’étape 1.5 de GRUB doit être située dans l’espace entre l’enregistrement de démarrage lui-même et la première partition du disque. Cet espace a été laissé inutilisé historiquement pour des raisons techniques. La première partition du disque dur commence au secteur 63 et avec le MBR dans le secteur 0, cela laisse 62 secteurs de 512 octets – 31 744 octets – dans lesquels stocker le fichier core.img qui est l’étape 1.5 de GRUB. Le fichier core.img fait 25 389 octets, il y a donc beaucoup d’espace disponible entre le MBR et la première partition du disque dans lequel le stocker.
En raison de la plus grande quantité de code qui peut être accueillie pour l’étape 1.5, il peut avoir suffisamment de code pour contenir quelques pilotes de système de fichiers communs, tels que le système de fichiers standard EXT et d’autres systèmes de fichiers Linux, FAT et NTFS. Le core.img de GRUB2 est beaucoup plus complexe et performant que l’ancienne étape 1.5 de GRUB1. Cela signifie que l’étape 2 de GRUB2 peut être située sur un système de fichiers EXT standard mais pas sur un volume logique. Donc, l’emplacement standard pour les fichiers de l’étape 2 est dans le système de fichiers /boot, plus précisément /boot/grub2.
Notez que le répertoire /boot doit être situé sur un système de fichiers qui est pris en charge par GRUB. Tous les systèmes de fichiers ne le sont pas. La fonction de l’étape 1.5 est de commencer l’exécution avec les pilotes du système de fichiers nécessaires pour localiser les fichiers de l’étape 2 dans le système de fichiers /boot et charger les pilotes nécessaires.
Etape 2
Tous les fichiers de l’étape 2 de GRUB sont situés dans le répertoire /boot/grub2 et plusieurs sous-répertoires. GRUB2 ne dispose pas d’un fichier image comme les étapes 1 et 2. Au lieu de cela, il se compose principalement de modules de noyau d’exécution qui sont chargés selon les besoins à partir du répertoire /boot/grub2/i386-pc.
La fonction de l’étape 2 de GRUB2 est de localiser et de charger un noyau Linux dans la RAM et de remettre le contrôle de l’ordinateur au noyau. Le noyau et ses fichiers associés sont situés dans le répertoire /boot. Les fichiers du noyau sont identifiables car ils sont tous nommés en commençant par vmlinuz. Vous pouvez lister le contenu du répertoire /boot pour voir les noyaux actuellement installés sur votre système.
GRUB2, comme GRUB1, prend en charge le démarrage à partir d’une sélection de noyaux Linux. Le gestionnaire de paquets Red Hat, DNF, prend en charge la conservation de plusieurs versions du noyau afin que, si un problème survient avec la plus récente, une version plus ancienne du noyau puisse être démarrée. Par défaut, GRUB fournit un menu de pré-démarrage des noyaux installés, y compris une option de secours et, si elle est configurée, une option de récupération.
L’étape 2 de GRUB2 charge le noyau sélectionné en mémoire et confie le contrôle de l’ordinateur au noyau.
Noyau
Tous les noyaux sont dans un format auto-extractible et compressé pour économiser de l’espace. Les noyaux sont situés dans le répertoire /boot, avec une image initiale du disque RAM et les cartes de périphériques des disques durs.
Après que le noyau sélectionné soit chargé en mémoire et commence à s’exécuter, il doit d’abord s’extraire de la version compressée du fichier avant de pouvoir effectuer tout travail utile. Une fois que le noyau s’est extrait, il charge systemd, qui est le remplacement de l’ancien programme d’init SysV, et lui transmet le contrôle.
C’est la fin du processus de démarrage. À ce stade, le noyau Linux et systemd sont en cours d’exécution mais ne sont pas en mesure d’effectuer des tâches productives pour l’utilisateur final parce que rien d’autre n’est en cours d’exécution.
Le processus de démarrage
Le processus de démarrage suit le processus d’amorçage et amène l’ordinateur Linux à un état opérationnel dans lequel il est utilisable pour un travail productif.
systemd
systemd est la mère de tous les processus et il est responsable d’amener l’hôte Linux à un état dans lequel un travail productif peut être effectué. Certaines de ses fonctions, qui sont bien plus étendues que l’ancien programme init, consistent à gérer de nombreux aspects d’un hôte Linux en fonctionnement, notamment le montage des systèmes de fichiers, ainsi que le démarrage et la gestion des services système nécessaires pour avoir un hôte Linux productif. Toutes les tâches de systemd qui ne sont pas liées à la séquence de démarrage sortent du cadre de cet article.
D’abord, systemd monte les systèmes de fichiers tels que définis par /etc/fstab, y compris les fichiers ou partitions d’échange. À ce stade, il peut accéder aux fichiers de configuration situés dans /etc, y compris les siens. Il utilise son fichier de configuration, /etc/systemd/system/default.target, pour déterminer l’état ou la cible dans lequel il doit démarrer l’hôte. Le fichier default.target n’est qu’un lien symbolique vers le véritable fichier cible. Pour une station de travail de bureau, il s’agit généralement du fichier graphical.target, qui équivaut au niveau d’exécution 5 dans l’ancien init de SystemV. Pour un serveur, le défaut est plus susceptible d’être le multi-user.target qui est comme le runlevel 3 dans SystemV. Le emergency.target est similaire au mode mono-utilisateur.
Notez que les cibles et les services sont des unités systemd.
Le tableau 1, ci-dessous, est une comparaison des cibles systemd avec les anciens niveaux d’exécution du démarrage de SystemV. Les alias de cibles systemd sont fournis par systemd pour une compatibilité ascendante. Les alias de cible permettent aux scripts – et à de nombreux administrateurs système comme moi – d’utiliser les commandes SystemV comme init 3 pour modifier les niveaux d’exécution. Of course, the SystemV commands are forwarded to systemd for interpretation and execution.
SystemV Runlevel | systemd target | systemd target aliases | Description |
halt.target | Halts the system without powering it down. | ||
0 | poweroff.target | runlevel0.target | Halts the system and turns the power off. |
S | emergency.target | Single user mode. No services are running; filesystems are not mounted. This is the most basic level of operation with only an emergency shell running on the main console for the user to interact with the system. | |
1 | rescue.target | runlevel1.target | A base system including mounting the filesystems with only the most basic services running and a rescue shell on the main console. |
2 | runlevel2.target | Multiuser, without NFS but all other non-GUI services running. | |
3 | multi-user.target | runlevel3.target | All services running but command line interface (CLI) only. |
4 | runlevel4.target | Unused. | |
5 | graphical.target | runlevel5.target | multi-user with a GUI. |
6 | reboot.target | runlevel6.target | Reboot |
default.target | This target is always aliased with a symbolic link to either multi-user.target or graphical.target. systemd always uses the default.target to start the system. La cible default.target ne doit jamais être aliasée à halt.target, poweroff.target ou reboot.target. |
Tableau 1 : Comparaison des niveaux d’exécution de SystemV avec les cibles de systemd et certains alias de cible.
Chaque cible possède un ensemble de dépendances décrites dans son fichier de configuration. systemd démarre les dépendances requises. Ces dépendances sont les services requis pour exécuter l’hôte Linux à un niveau de fonctionnalité spécifique. Lorsque toutes les dépendances énumérées dans les fichiers de configuration de la cible sont chargées et fonctionnent, le système s’exécute à ce niveau de cible.
Systemd examine également les répertoires d’init SystemV hérités pour voir si des fichiers de démarrage y existent. Si c’est le cas, systemd les a utilisés comme fichiers de configuration pour démarrer les services décrits par les fichiers. Le service réseau déprécié est un bon exemple de l’un de ceux qui utilisent encore des fichiers de démarrage SystemV dans Fedora.
La figure 1, ci-dessous, est copiée directement de la page de manuel bootup. Elle montre la séquence générale des événements pendant le démarrage de systemd et les exigences d’ordonnancement de base pour assurer un démarrage réussi.
Les cibles sysinit.target et basic.target peuvent être considérées comme des points de contrôle dans le processus de démarrage. Bien que l’un des objectifs de conception de systemd soit de démarrer les services système en parallèle, il existe toujours certains services et cibles fonctionnelles qui doivent être démarrés avant que d’autres services et cibles puissent être démarrés. Ces points de contrôle ne peuvent pas être passés tant que tous les services et cibles requis par ce point de contrôle ne sont pas remplis.
Ainsi, la cible sysinit.est atteinte lorsque toutes les unités dont elle dépend sont terminées. Toutes ces unités, le montage des systèmes de fichiers, la configuration des fichiers d’échange, le démarrage de udev, la configuration de la graine du générateur aléatoire, l’initiation des services de bas niveau et la configuration des services cryptographiques si un ou plusieurs systèmes de fichiers sont cryptés, doivent être achevées, mais au sein de la cible sysinit.target, ces tâches peuvent être effectuées en parallèle.
La cible sysinit.target démarre tous les services et unités de bas niveau nécessaires pour que le système soit marginalement fonctionnel et qui sont nécessaires pour permettre de passer à la basic.target.
local-fs-pre.target
|
v
(various mounts and (various swap (various cryptsetup
fsck services...) devices...) devices...) (various low-level (various low-level
| | | services: udevd, API VFS mounts:
v v v tmpfiles, random mqueue, configfs,
local-fs.target swap.target cryptsetup.target seed, sysctl, ...) debugfs, ...)
| | | | |
\__________________|_________________ | ___________________|____________________/
\|/
v
sysinit.target
|
____________________________________/|\________________________________________
/ | | | \
| | | | |
v v | v v
(various (various | (various rescue.service
timers...) paths...) | sockets...) |
| | | | v
v v | v rescue.target
timers.target paths.target | sockets.target
| | | |
v \_________________ | ___________________/
\|/
v
basic.target
|
____________________________________/| emergency.service
/ | | |
| | | v
v v v emergency.target
display- (various system (various system
manager.service services services)
| required for |
| graphical UIs) v
| | multi-user.target
| | |
\_________________ | _________________/
\|/
v
graphical.target
Figure 1 : La carte de démarrage de systemd.
Après avoir rempli la sysinit.target, systemd démarre ensuite la basic.target, en démarrant toutes les unités nécessaires pour la remplir. La cible de base fournit quelques fonctionnalités supplémentaires en démarrant les unités qui re requises pour la cible suivante. Celles-ci comprennent la mise en place de choses comme les chemins vers divers répertoires exécutables, les sockets de communication et les minuteurs.
Enfin, les cibles de niveau utilisateur, multi-user.target ou graphical.target peuvent être initialisées. Remarquez que la cible multi-user.target doit être atteinte avant que les dépendances de la cible graphique puissent être satisfaites.
Les cibles soulignées dans la figure 1, sont les cibles habituelles de démarrage. Lorsqu’une de ces cibles est atteinte, alors le démarrage est terminé. Si la cible multi-user.target est la cible par défaut, alors vous devriez voir un login en mode texte sur la console. Si graphical.target est la valeur par défaut, alors vous devriez voir un login graphique ; l’écran de login GUI spécifique que vous voyez dépendra du gestionnaire d’affichage par défaut que vous utilisez.
Issues
J’ai récemment eu besoin de changer le noyau de démarrage par défaut sur un ordinateur Linux qui utilisait GRUB2. J’ai constaté que certaines des commandes ne semblaient pas fonctionner correctement pour moi, ou que je ne les utilisais pas correctement. Je ne suis pas encore certain de ce qui était le cas, et je dois faire quelques recherches supplémentaires.
La commande grub2-set-default n’a pas correctement défini l’index du noyau par défaut pour moi dans le fichier /etc/default/grub, de sorte que le noyau alternatif souhaité n’a pas démarré. J’ai donc modifié manuellement le fichier /etc/default/grub GRUB_DEFAULT=saved en GRUB_DEFAULT=2 où 2 est l’index du noyau installé que je voulais faire démarrer. Puis j’ai exécuté la commande grub2-mkconfig > /boot/grub2/grub.cfg pour créer le nouveau fichier de configuration de grub. Ce contournement a fonctionné comme prévu et a permis de démarrer sur le noyau alternatif.
Conclusions
GRUB2 et le système init systemd sont les composants clés des phases de démarrage et d’amorçage de la plupart des distributions Linux modernes. Malgré le fait qu’il y ait eu des controverses autour de systemd en particulier, ces deux composants travaillent ensemble sans heurts pour charger d’abord le noyau et ensuite pour démarrer tous les services système nécessaires pour produire un système Linux fonctionnel.
Bien que je trouve à la fois GRUB2 et systemd plus complexes que leurs prédécesseurs, ils sont également tout aussi faciles à apprendre et à gérer. Les pages de manuel ont beaucoup d’informations sur systemd, et freedesktop.org a l’ensemble complet des pages de manuel de systemd en ligne. Reportez-vous aux ressources, ci-dessous, pour plus de liens.