C'est une question sur les applications de l'espace utilisateur, mais écoutez-moi!
Pour ainsi dire, trois "applications" sont nécessaires pour démarrer une distribution fonctionnelle de Linux:
Bootloader - Pour les applications intégrées, il s'agit généralement de U-Boot, mais ce n'est pas une exigence difficile.
Noyau - C'est assez simple.
Système de fichiers racine - ne peut pas démarrer sans un shell. Contient le système de fichiers vers lequel le noyau démarre et où
init
est appelé formulaire.
Ma question concerne le numéro 3. Si quelqu'un voulait construire un rootfs extrêmement minimal (pour cette question, disons pas d'interface graphique, shell uniquement), quels fichiers / programmes sont nécessaires pour démarrer sur un shell?
linux
embedded
startup
architecture
root-filesystem
MDMoore313
la source
la source
Réponses:
Cela dépend entièrement des services que vous souhaitez avoir sur votre appareil.
Programmes
Vous pouvez faire démarrer Linux directement dans un shell . Ce n'est pas très utile en production - qui voudrait juste avoir un shell assis là - mais c'est utile comme mécanisme d'intervention lorsque vous avez un chargeur de démarrage interactif: passez
init=/bin/sh
à la ligne de commande du noyau. Tous les systèmes Linux (et tous les systèmes Unix) ont un shell de style Bourne / POSIX/bin/sh
.Vous aurez besoin d'un ensemble d' utilitaires shell . BusyBox est un choix très courant; il contient un shell et des utilitaires communs pour la manipulation de fichiers et le texte (
cp
,grep
, ...), la configuration du réseau (ping
,ifconfig
, ...), la manipulation des processus (ps
,nice
, ...), et divers autres outils système (fdisk
,mount
,syslogd
, ...). BusyBox est extrêmement configurable: vous pouvez sélectionner les outils que vous souhaitez et même les fonctionnalités individuelles au moment de la compilation, pour obtenir le bon compromis taille / fonctionnalité pour votre application. Mis à partsh
, le strict minimum que vous ne pouvez pas vraiment faire quoi que ce soit sans estmount
,umount
ethalt
, mais ce serait atypique de ne pas avoir aussicat
,cp
,mv
,rm
,mkdir
,rmdir
,ps
,sync
Et quelques autres. BusyBox s'installe comme un seul binaire appelébusybox
, avec un lien symbolique pour chaque utilitaire.Le premier processus sur un système Unix normal est appelé
init
. Son travail consiste à démarrer d'autres services. BusyBox contient un système d'initialisation. En plus duinit
binaire (généralement situé dans/sbin
), vous aurez besoin de ses fichiers de configuration (généralement appelés/etc/inittab
- certains remplacements d'init modernes suppriment ce fichier mais vous ne les trouverez pas sur un petit système intégré) qui indiquent les services à démarrer et quand. Pour BusyBox,/etc/inittab
est facultatif; s'il est manquant, vous obtenez un shell racine sur la console et le script/etc/init.d/rcS
(emplacement par défaut) est exécuté au démarrage.C'est tout ce dont vous avez besoin, au-delà bien sûr des programmes qui font que votre appareil fait quelque chose d'utile. Par exemple, sur mon routeur domestique exécutant une variante OpenWrt , les seuls programmes sont BusyBox
nvram
(pour lire et modifier les paramètres dans NVRAM) et les utilitaires de mise en réseau.À moins que tous vos exécutables ne soient liés statiquement, vous aurez besoin du chargeur dynamique (
ld.so
, qui peut être appelé par des noms différents selon le choix de libc et des architectures de processeur) et de toutes les bibliothèques dynamiques (/lib/lib*.so
, peut-être certaines d'entre elles/usr/lib
) requises par ces exécutables.Structure du répertoire
La norme de hiérarchie du système de fichiers décrit la structure de répertoires commune des systèmes Linux. Il est orienté vers les installations de postes de travail et de serveurs: une grande partie peut être omise sur un système embarqué. Voici un minimum typique.
/bin
: programmes exécutables (certains peuvent être à la/usr/bin
place)./dev
: nœuds de périphérique (voir ci-dessous)/etc
: fichiers de configuration/lib
: bibliothèques partagées, y compris le chargeur dynamique (sauf si tous les exécutables sont liés statiquement)/proc
: point de montage pour le système de fichiers proc/sbin
: programmes exécutables. La distinction avec/bin
est/sbin
pour les programmes qui ne sont utiles qu'à l'administrateur système, mais cette distinction n'a pas de sens sur les périphériques intégrés. Vous pouvez créer/sbin
un lien symbolique vers/bin
./mnt
: pratique à avoir sur les systèmes de fichiers racine en lecture seule comme point de montage scratch pendant la maintenance/sys
: point de montage pour le système de fichiers sysfs/tmp
: emplacement pour les fichiers temporaires (souvent untmpfs
montage)/usr
: contient des sousbin
- répertoireslib
etsbin
./usr
existe pour les fichiers supplémentaires qui ne sont pas sur le système de fichiers racine. Si vous n'en avez pas, vous pouvez créer/usr
un lien symbolique vers le répertoire racine.Fichiers de périphérique
Voici quelques entrées typiques dans un minimum
/dev
:console
full
(y écrire signale toujours «plus d'espace sur l'appareil»)log
(un socket que les programmes utilisent pour envoyer des entrées de journal), si vous avez unsyslogd
démon (tel que BusyBox) qui le litnull
(agit comme un fichier toujours vide)ptmx
et unpts
répertoire , si vous souhaitez utiliser des pseudo-terminaux (c'est -à- dire tout terminal autre que la console) - par exemple, si le périphérique est en réseau et que vous souhaitez telnet ou ssh dansrandom
(retourne des octets aléatoires, risque de blocage)tty
(désigne toujours le terminal du programme)urandom
(retourne des octets aléatoires, ne bloque jamais mais peut être non aléatoire sur un appareil fraîchement démarré)zero
(contient une séquence infinie d'octets nuls)Au-delà, vous aurez besoin d'entrées pour votre matériel (à l'exception des interfaces réseau, celles-ci ne sont pas entrées
/dev
): ports série, stockage, etc.Pour les périphériques intégrés, vous devez normalement créer les entrées de périphérique directement sur le système de fichiers racine. Les systèmes haut de gamme ont un script appelé
MAKEDEV
pour créer des/dev
entrées, mais sur un système intégré, le script n'est souvent pas intégré à l'image. Si certains matériels peuvent être branchés à chaud (par exemple si le périphérique a un port hôte USB), alors ils/dev
devraient être gérés par udev (vous pouvez toujours avoir un ensemble minimal sur le système de fichiers racine).Actions au démarrage
Au-delà du système de fichiers racine, vous devez en monter quelques autres pour un fonctionnement normal:
/proc
(assez indispensable)/sys
(à peu près indispensable)tmpfs
système de fichiers activé/tmp
(pour permettre aux programmes de créer des fichiers temporaires qui seront en RAM, plutôt que sur le système de fichiers racine qui peut être en flash ou en lecture seule)/dev
si dynamique (voir udev dans «Fichiers de périphérique» ci-dessus)/dev/pts
si vous voulez utiliser [pseudo-terminaux (voir la remarque au sujetpts
ci - dessus)Vous pouvez créer un
/etc/fstab
fichier et appelermount -a
ou exécutermount
manuellement.Démarrez un démon syslog (ainsi que
klogd
pour les journaux du noyau, si lesyslogd
programme ne s'en occupe pas), si vous avez un endroit où écrire des journaux.Après cela, l'appareil est prêt à démarrer des services spécifiques à l'application.
Comment créer un système de fichiers racine
C'est une histoire longue et diversifiée, donc tout ce que je vais faire ici est de donner quelques conseils.
Le système de fichiers racine peut être conservé dans la RAM (chargé à partir d'une image (généralement compressée) dans la ROM ou le flash), ou sur un système de fichiers sur disque (stocké dans la ROM ou le flash), ou chargé à partir du réseau (souvent via TFTP ) le cas échéant . Si le système de fichiers racine est en RAM, faites-en l' initramfs - un système de fichiers RAM dont le contenu est créé au démarrage.
Il existe de nombreux frameworks pour assembler des images racine pour les systèmes embarqués. Il y a quelques pointeurs dans la FAQ BusyBox . Buildroot est populaire, vous permettant de construire une image racine entière avec une configuration similaire au noyau Linux et BusyBox. OpenEmbedded est un autre tel cadre.
Wikipedia a une liste (incomplète) de distributions Linux embarquées populaires . Un exemple de Linux embarqué que vous pouvez avoir près de chez vous est la famille de systèmes d'exploitation OpenWrt pour les appliances réseau (populaire sur les routeurs domestiques des bricoleurs). Si vous voulez apprendre par expérience, vous pouvez essayer Linux from Scratch , mais il est orienté vers les systèmes de bureau pour les amateurs plutôt que vers les appareils intégrés.
Une note sur Linux vs noyau Linux
Le seul comportement intégré au noyau Linux est le premier programme lancé au démarrage. (Je n'entrerai pas dans les subtilités initrd et initramfs ici.) Ce programme, traditionnellement appelé init , a l'ID de processus 1 et a certains privilèges (immunité aux signaux KILL ) et responsabilités (récolter des orphelins ). Vous pouvez exécuter un système avec un noyau Linux et démarrer tout ce que vous voulez comme premier processus, mais ce que vous avez est un système d'exploitation basé sur le noyau Linux, et non pas ce qui est normalement appelé «Linux» - Linux , dans le sens commun du terme, est un système d' exploitation de type Unix dont le noyau est le noyau Linux. Par exemple, Android est un système d'exploitation qui n'est pas de type Unix mais basé sur le noyau Linux.
la source
Tout ce dont vous avez besoin est un exécutable lié statiquement, placé sur le système de fichiers, de manière isolée. Vous n'avez pas besoin d'autres fichiers. Cet exécutable est le processus init. Il peut s'agir de busybox. Cela vous donne un shell et une foule d'autres utilitaires, en soi. Vous pouvez accéder à un système pleinement fonctionnel simplement en exécutant manuellement des commandes dans la boîte occupée pour monter le système de fichiers racine en lecture-écriture, créer des nœuds / dev, exécuter real init, etc.
la source
Si vous n'avez besoin d'aucun utilitaire shell, un
mksh
binaire lié statiquement (par exemple contre klibc - 130K sous Linux / i386) fera l'affaire. Vous avez besoin d'un script/linuxrc
ou/init
ou/sbin/init
qui appelle simplementmksh -l -T!/dev/tty1
en boucle:L'
-T!$tty
option est un ajout récentmksh
qui lui indique de générer un nouveau shell sur le terminal donné et de l'attendre. (Avant cela, il n'y avait qu'à-T-
démoniser un programme et-T$tty
à apparaître sur un terminal mais pas l'attendre. Ce n'était pas si gentil.) L'-l
option lui dit simplement d'exécuter un shell de connexion (qui lit/etc/profile
,~/.profile
et~/.mkshrc
).Cela suppose que votre terminal est de
/dev/tty1
remplacement. (Avec plus de magie, le terminal peut être découvert automatiquement./dev/console
Ne vous donnera pas le contrôle total du travail.)Vous avez besoin de quelques fichiers
/dev
pour que cela fonctionne:Le démarrage avec l'option du noyau
devtmpfs.mount=1
élimine le besoin d'un/dev
répertoire rempli , laissez-le simplement être un répertoire vide (adapté à une utilisation comme point de montage).Vous voudrez normalement avoir certains utilitaires (de klibc, busybox, beastiebox, toybox ou toolbox), mais ils ne sont pas vraiment nécessaires.
Vous souhaiterez peut-être ajouter un
~/.mkshrc
fichier, qui configure $ PS1 et certains alias et fonctions de base du shell.J'ai fait une fois un initrd compressé 171K (371K non compressé) pour Linux / m68k en utilisant mksh (et son exemple de fichier mkshrc) et klibc-utils uniquement. (C'était avant que -T! Ne soit ajouté au shell, cependant, il a généré le shell de connexion à la
/dev/tty2
place et a envoyé un message à la console indiquant à l'utilisateur de changer de terminal.) Cela fonctionne très bien.Il s'agit d'une configuration minimale vraiment nue . Les autres réponses fournissent d'excellents conseils pour des systèmes un peu plus détaillés. C'est un vrai cas spécial.
Avertissement: je suis le développeur mksh.
la source
mksh
.Petit programme init hello world étape par étape
Compilez un monde bonjour sans aucune dépendance qui se termine par une boucle infinie.
init.S
:On ne peut pas utiliser
sys_exit
, sinon la panique du noyau.Alors:
Cela crée un système de fichiers avec notre monde bonjour
/init
, qui est le premier programme de l'espace utilisateur sur lequel le noyau s'exécutera. Nous aurions également pu ajouter plus de fichiersd/
et ils seraient accessibles depuis le/init
programme lors de l'exécution du noyau.Ensuite,
cd
dans l'arborescence du noyau Linux, la construction est comme d'habitude et exécutez-la dans QEMU:Et vous devriez voir une ligne:
sur l'écran de l'émulateur! Notez que ce n'est pas la dernière ligne, vous devez donc regarder un peu plus haut.
Vous pouvez également utiliser des programmes C si vous les liez statiquement:
avec:
Vous pouvez exécuter sur du matériel réel avec une clé USB
/dev/sdX
et:Excellente source sur ce sujet: http://landley.net/writing/rootfs-howto.html Il explique également comment utiliser
gen_initramfs_list.sh
, qui est un script de l'arborescence des sources du noyau Linux pour aider à automatiser le processus.Étape suivante: configurez BusyBox pour pouvoir interagir avec le système: https://github.com/cirosantilli/runlinux
Testé sur Ubuntu 16.10, QEMU 2.6.1.
la source