«« sommaire »»

III.1 – Ajouter des scripts ou des fichiers de données

Christophe BLAESS - juillet 2024

Le premier type de fichiers que nous allons ajouter au BSP que nous avons produit jusqu’à présent va être assez simple : il s’agira de scripts. L’avantage de ces fichiers est qu’ils ne nécessitent pas de compilation, il suffit de les copier au bon endroit, et avec les bonnes permissions, pour qu’ils soient utilisables sur la cible.

Bien sûr il faut qu’un interpréteur adéquat soit disponible pour les interpréter. Pour les scripts shell cela fait partie de l'environnement de base installé par Yocto, et pour les scripts Python, nous devrons nous assurer de la présence de l'interpréteur et de certains modules supplémentaires.

Système de fichiers en lecture seule

Avant cela, nous allons commencer par sélectionner une feature (fonctionnalité) d’image importante : la mise en lecture seule du système de fichiers. Dans les environnements embarqués, une préoccupation constante est en effet la corruption des données lors d’une coupure impromptue de l’alimentation électrique du système. Lorsqu’elle se produit, cette coupure provoque bien évidemment la perte des données qui étaient en cours d’enregistrement, mais peut engendrer une corruption du système de fichiers lui-même. Il devient alors nécessaire d'exécuter un utilitaire de vérification et de répartion du système de fichiers (par exemple «e2fsck»). Cette action peut être entreprise par des scripts de démarrage qui montent, vérifient, et réparent si besoin le système de fichiers concerné.

Le problème devient critique lorsque c'est le système de fichiers principal (root filesystem, ou rootfs) qui est atteint, car celui-ci est monté directement par le noyau à la fin de la phase de boot, juste avant de lancer le processus «init».

Le noyau n'a pas accès aux outils de vérification et réparation du système de fichiers, puisque justement ils se trouvent sur ce système de fichiers principal.

Ainsi une corruption, même mineure du système de fichiers principal peut conduire à une impossibilité de démarrer, à un système briqué (i.e.: aussi utile qu'une brique pour ce qui concerne le logiciel)

Il faut bien être conscient qu'une partition accessible en lecture-écriture peut toujours être sujette à ce type de corrution en cas de coupure intempestive de l'alimentation électrique, même si nous ne faisons pas d'écriture intentionnelle sur la partition. Il y a des méta-données (dernière heure de consultation d'un fichier par exemple) qui sont inscrites en permanence.

Une manière simple de corriger ce défaut est de demander à Yocto de monter le système de fichiers contenu sur la partition principale en lecture-seulement. Bien sûr on pourra ajouter des partitions supplémentaires en lecture-écriture pour y stocker des données si besoin, en s’arrangeant pour qu’une détection d’incohérence ne soit pas bloquante, nous en reparlerons. L’important est que la partition principale du système soit protégée.

J’édite donc mon fichier d’image pour ajouter la feature adéquate :

[build-qemu]$ nano  ../../layers/meta-my-layer/recipes-custom/images/my-image.bb 
   [...]
   IMAGE_FEATURES += "read-only-rootfs"

Après re-compilation et démarrage, vérifions le comportement :

mybox login: root
Password: (linux)

root@mybox:~# pwd
/home/root

root@mybox:~# echo  HELLO  > my-file.txt 
-sh: my-file.txt: Read-only file system

Notre système de fichiers principal est désormais en lecture seule et il n'y a plus de riques de perte de données sur cette partition en cas de coupure intempestive de l'alimentation.

Pendant la phase de mise au point du système embarqué, il peut être pratique de tester des modifications directement dans le système de fichiers avant de les intégrer dans une recette.

Pour cela, il est possible de remonter temporairement la partition principale en lecture-écriture ainsi :

root@mybox:~# mount  /  -o  remount,rw
 [188.917856] EXT4-fs (vda): re-mounted. Opts: (null)

root@mybox:~# echo  HELLO  > my-file.txt

root@mybox:~# ls
my-file.txt

Puis de revenir en lecture-seule :

root@mybox:~# mount  /  -o  remount,ro
 [260.995398] EXT4-fs (vda): re-mounted. Opts: (null)

root@mybox:~# rm  my-file.txt
rm: cannot remove 'my-file.txt': Read-only file system

Néanmoins ces lignes de commandes sont un peu fastidieuses, aussi je vous propose de réaliser deux petits scripts, que j’appelle traditionnellement «rw» et «ro» pour réaliser ces tâches. Ceci nous donnera l’occasion d’écrire une recette pour les intégrer dans notre image.

Intégration de scripts shells

Commençons par écrire les deux scripts shell dans un répertoire dédié de notre layer. Vous pouvez les télécharger ici : rw et ro.

[build-qemu]$ mkdir  -p  ../../layers/meta-my-layer/recipes-custom/my-scripts/files 

[build-qemu]$ nano  ../../layers/meta-my-layer/recipes-custom/my-scripts/files/rw
#!/bin/sh
mount / -o remount,rw

[build-qemu]$ nano  ../../layers/meta-my-layer/recipes-custom/my-scripts/files/ro 
#!/bin/sh
mount / -o remount,ro

Inutile de les rendre exécutables, nous ne les lancerons pas sur le système de développement, et leurs permissions sur la cible seront indiquées directement dans notre recette. Nous allons créer manuellement le fichier de recette afin d'en analyser la structure. Créons le fichier suivant :

[build-qemu]$ nano  ../../layers/meta-my-layer/recipes-custom/my-scripts/my-scripts.bb

SUMMARY = "Custom scripts for Yocto training"
SECTION = "custom"

LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"

SRC_URI  = "file://ro"
SRC_URI += "file://rw"

do_install() {
     install -d ${D}${sbindir}
     install -m 0755 ${WORKDIR}/ro ${D}${sbindir}
     install -m 0755 ${WORKDIR}/rw ${D}${sbindir}
}

FILES:${PN} += "${sbindir}/ro"
FILES:${PN} += "${sbindir}/rw"

Quelques explications sur la syntaxe de notre première recette complète :

Nous avons utilisé la variable sbindir, il existe toute une liste de variables prédéfinies avec des chemins standards. Voici ci-dessous les plus courantes, pour en savoir plus, se reporter au début du fichier poky/meta/conf/bitbake.conf.

VariableValeur par défaut
bindir/usr/bin
datadir/usr/share
docdir/usr/share/doc
includedir/usr/include
infodir/usr/share/info
libdir/usr/lib
libexecdir/usr/libexec
localedir/usr/lib/locale
localstatedir/var
sbindir/usr/sbin
servicedir/srv
sysconfdir/etc
systemd_unitdir/lib/systemd
systemd_system_unitdir/lib/systemd/system
systemd_user_unitdir/usr/lib/systemd/user

Avant de recompiler l’image, il convient d’inclure notre package dans le fichier d’image :

[build-qemu]$ nano  ../../layers/meta-my-layer/recipes-custom/images/my-image.bb 
  [...]
  IMAGE_INSTALL:append = " my-scripts"

Après compilation et démarrage de la cible, nous vérifions que nos scripts sont bien accessibles et se comportent comme voulu :

My experimental distro 1.0 mybox ttyAMA0

mybox login: root
Password: (linux)

root@mybox:~# ls

root@mybox:~# echo HELLO > my-file
-sh: my-file: Read-only file system

root@mybox:~# rw
[   47.990109] EXT4-fs (vda): re-mounted 38c30722-c384-46e6-9e66-506cdddbc7a4 r/w. Quota mode: disabled.

root@mybox:~# echo HELLO > my-file

root@mybox:~# ls
my-file

root@mybox:~# ro
[   54.424083] EXT4-fs (vda): re-mounted 38c30722-c384-46e6-9e66-506cdddbc7a4 ro. Quota mode: disabled.

root@mybox:~# rm my-file
rm: cannot remove 'my-file': Read-only file system

root@mybox:~#

NB: les messages "EXT4-fs (vda): re-mounted..." ne sont pas des erreurs mais des traces du noyau (nous sommes connectés sur la console principale) lorsqu'une partition est montée ou démontée.

Scripts et modules Python

Nous pouvons facilement ajouter des scripts Python sur notre cible, un interpréteur Python 3 étant déjà présent dans notre image, mais le nombre de modules installés par défaut est assez limité. Nous demanderons, dans notre recette, à disposer de modules supplémentaires. Vérifions la version de python installée :

root@mybox:~# python3  -V
Python 3.12.3

root@mybox:~#

Je rajoute, dans un répertoire meta-my-layer/recipes-custom/python-hello/files/ le petit script python-hello.py suivant :

#!/usr/bin/python3
#
# Christophe BLAESS 2020-2023.
#
# Licence MIT.
#
import socket
import sys
print("Python {} says 'Hello' from {}".format(sys.version[0:3],socket.gethostname()))

Ainsi que la recette python-hello_1.2.bb ci-dessous, dans le répertoire meta-my-layer/recipes-custom/python-hello.

SUMMARY = "Python Hello World for Yocto tutorial"
SECTION = "custom"
LICENSE = "MIT"
LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302"
SRC_URI  = "file://python-hello.py"

RDEPENDS:${PN} += "python3-core"
RDEPENDS:${PN} += "python3-modules"

do_install() {
    install -d ${D}${bindir}
    install -m 0755 ${WORKDIR}/python-hello.py ${D}${bindir}

}

FILES:${PN} += "${bindir}/python-hello.py"

On peut noter la présence des deux lignes centrales, qui renseignent la variable RDEPENDS pour cette recette. Cette variable, abréviation de Runtime Dependencies contient la liste des packages nécessaires pour le fonctionnement de la recette sur la cible. Il faut la distinguer de la variable DEPENDS qui liste les packages nécessaires pour compiler une recette sur la machine de développement.

La dépendance de python3-code et python3-module permet d'inclure automatiquement sur la cible ces éléments. Il n'existe pas de packages python3-code ni python3-module ce sont des listes définies dans la recette de Python.

En ajoutant dans notre image la ligne :

IMAGE_INSTALL:append = " python-hello"

et en recompilant notre système, nous pouvons observer après démarrage :

My experimental distro 1.0 mybox ttyAMA0

mybox login: root
Password: 

root@mybox:~# python-hello.py 
Python 3.1 says 'Hello' from mybox

Conclusion

Nous avons vu dans cette séquence comment ajouter dans une image des fichiers fournis par une recette. Dans le cas d’un script, il faut simplement penser à lui ajouter les permissions d’exécution (ce qui se fait facilement avec la commande install) et éventuellement l’interpréteur nécessaire. Dans la séquence suivante, nous écrirons une recette nécessitant une compilation de code source.

 

Si vous préférez une session de cours interactif, en mode présentiel ou distanciel, n'hésitez pas à vous inscrire à mes formations "Développeur Linux embarqué avec Yocto Project" ou "Yocto Project avancé" .

Ce document est placé sous licence Creative Commons CC BY-NC. Vous pouvez copier son contenu et le réemployer à votre gré pour une utilisation non-commerciale. Vous devez en outre mentionner sa provenance.

Le nom Yocto Project est une marque déposée par la Linux Foundation. Le présent document n'est en aucune façon approuvé par Yocto Project ou la Linux Foundation.

«« sommaire »»