Depuis quelques jours une nouvelle distribution Raspbian est disponible pour le Raspberry Pi : la version Jessie. Il s’agit de l’adaptation de la distribution Debian 8 sortie au printemps.
L’avantage de Debian est de disposer aisément d’un très large éventail d’applications, utilitaires, bibliothèques pré-configurés et faciles à installer. En outre il s’agit en quelque sorte de la distribution de référence lorsqu’on parle d’un système Linux.
L’inconvénient, à mes yeux, de Raspbian est qu’elle est prévue pour une utilisation « desktop » qui convient très bien pour un PC mais pas vraiment pour un système embarqué. Je lui reproche entre autre de ne pas être très robuste vis-à-vis des coupures d’alimentation. Mais rien ne nous empêche de la configurer comme un système embarqué classique. Essayons…
Premier boot, premières impressions
Je démarre la distribution Raspbian Jessie sur un Raspberry Pi modèle 1 B, et j’observe les traces de boot sur la console série.
[ 0.000000] Linux version 4.1.7+ (dc4@dc4-XPS13-9333) (gcc version 4.8.3 20140303 (prerelease) (crosstool-NG linaro-1.13.1+bzr2650 - Linaro GCC 2014.03) ) #817 PREEMPT Sat Sep 19 15:25:36 BST 2015 [ 0.000000] CPU: ARMv6-compatible processor [410fb767] revision 7 (ARMv7), cr=00c5387d [ 0.000000] CPU: PIPT / VIPT nonaliasing data cache, VIPT nonaliasing instruction cache [ 0.000000] Machine model: Raspberry Pi Model B Rev 2
Le modèle est bien identifié (Raspberry Pi Model B), et nous voyons que le noyau est plutôt récent (4.1.7), compilé le 19 septembre 2015. Il s’agit de la 817ème compilation depuis l’extraction des sources.
Je me demande si cette valeur est bien réelle. Le noyau 4.1.7 a été publié sur www.kernel.org le 13 septembre, cela représente donc une moyenne de 136 compilations par jour ce qui est très intensif, même dans le cas, d’un portage sur une nouvelle plate-forme !
Au bout de quelques secondes de boot, nous apercevons la fin des messages :
[ 3.552810] systemd[1]: Starting Forward Password Requests to Wall Directory Watch. [ 3.565385] systemd[1]: Started Forward Password Requests to Wall Directory Watch. [ 3.577346] systemd[1]: Expecting device dev-ttyAMA0.device... [ 3.588483] systemd[1]: Starting Remote File Systems (Pre). [ 3.599047] systemd[1]: Reached target Remote File Systems (Pre). [ 3.607838] systemd[1]: Starting Arbitrary Executable File Formats File System Automount Point. [ 3.624897] systemd[1]: Set up automount Arbitrary Executable File Formats File System Automount Point. [ 3.638953] systemd[1]: Starting Encrypted Volumes. [ 3.649175] systemd[1]: Reached target Encrypted Volumes. [ 3.657151] systemd[1]: Starting Swap. [ 3.666030] systemd[1]: Reached target Swap. [ 3.672566] systemd[1]: Expecting device dev-mmcblk0p1.device... [ 3.683667] systemd[1]: Starting Root Slice. [ 3.692723] systemd[1]: Created slice Root Slice. [ 3.699726] systemd[1]: Starting User and Session Slice. [ 3.710168] systemd[1]: Created slice User and Session Slice. [ 3.718224] systemd[1]: Starting /dev/initctl Compatibility Named Pipe. [ 3.730063] systemd[1]: Listening on /dev/initctl Compatibility Named Pipe. [ 3.739330] systemd[1]: Starting Delayed Shutdown Socket. [ 3.749556] systemd[1]: Listening on Delayed Shutdown Socket. [ 3.757494] systemd[1]: Starting Journal Socket (/dev/log). [ 3.767964] systemd[1]: Listening on Journal Socket (/dev/log). [ 3.776167] systemd[1]: Starting udev Control Socket. [ 3.786159] systemd[1]: Listening on udev Control Socket. [ 3.793864] systemd[1]: Starting udev Kernel Socket. [ 3.803610] systemd[1]: Listening on udev Kernel Socket. [ 3.811114] systemd[1]: Starting Journal Socket. [ 3.820696] systemd[1]: Listening on Journal Socket. [ 3.828070] systemd[1]: Starting System Slice. [ 3.837506] systemd[1]: Created slice System Slice. [ 3.844769] systemd[1]: Starting File System Check on Root Device... [ 3.860653] systemd[1]: Starting system-systemd\x2dfsck.slice. [ 3.882537] systemd[1]: Created slice system-systemd\x2dfsck.slice. [ 3.897474] systemd[1]: Starting system-autologin.slice. [ 3.915110] systemd[1]: Created slice system-autologin.slice. [ 3.924527] systemd[1]: Starting system-serial\x2dgetty.slice. [ 3.939584] systemd[1]: Created slice system-serial\x2dgetty.slice. [ 3.949190] systemd[1]: Starting Increase datagram queue length... [ 3.971123] systemd[1]: Starting Restore / save the current clock... [ 4.011520] systemd[1]: Mounting POSIX Message Queue File System... [ 4.045988] systemd[1]: Mounted Huge Pages File System. [ 4.114605] systemd[1]: Mounting Debug File System... [ 4.220232] systemd[1]: Started Set Up Additional Binary Formats. [ 4.279891] systemd[1]: Starting Load Kernel Modules... [ 4.312892] systemd[1]: Starting udev Coldplug all Devices... [ 4.358785] systemd[1]: Starting Create list of required static device nodes for the current kernel... [ 4.403001] fuse init (API version 7.23) [ 4.434562] systemd[1]: Starting Slices. [ 4.462789] systemd[1]: Reached target Slices. [ 4.523991] systemd[1]: Mounted Debug File System. [ 4.545602] systemd[1]: Mounted POSIX Message Queue File System. [ 4.569828] i2c /dev entries driver [ 4.588558] systemd[1]: Started File System Check on Root Device. [ 4.627558] systemd[1]: Started Increase datagram queue length. [ 4.641169] systemd[1]: Started Restore / save the current clock. [ 4.657331] systemd[1]: Started Load Kernel Modules. [ 4.685012] systemd[1]: Started Create list of required static device nodes for the current kernel. [ 4.723014] systemd[1]: Time has been changed [ 4.883663] systemd[1]: Started udev Coldplug all Devices. [ 5.095077] systemd[1]: Starting Create Static Device Nodes in /dev... [ 5.112404] systemd[1]: Starting Apply Kernel Variables... [ 5.146732] systemd[1]: Mounting Configuration File System... [ 5.199784] systemd[1]: Mounting FUSE Control File System...
Clairement, systemd a pris beaucoup d’ampleur dans cette version de la distribution Raspbian. Comme beaucoup de Linux « historiques », je ne suis pas très enthousiaste devant ce système, tout particulièrement dans le domaine de l’embarqué. Je le trouve plutôt complexe et difficile à maîtriser. Pour des systèmes restreints, que l’on doit ajuster précisément pour un besoin particulier, je trouve plus aisé de reposer sur quelques scripts shell, plutôt que sur un enchevêtrement de services imbriqués et peu configurables.
raspberrypi login: pi Password: (raspberry)
Je suis connecté sur la console série du système (sur les broches 8 et 10 du Connecteur P1). Cet accès paraît certainement un peu aride à la plupart des utilisateurs, mais étant habitué à travailler sur des systèmes embarqués restreints, je suis plus à l’aise sur le Raspberry Pi en console texte que dans un terminal graphique qui « rame » un peu sur les modèles 1B et 1B+.
Utilisons quelques commandes d’administration simples pour examiner le système.
$ mount /dev/mmcblk0p2 on / type ext4 (rw,noatime,data=ordered) devtmpfs on /dev type devtmpfs (rw,relatime,size=218252k,nr_inodes=54563,mode=755) sysfs on /sys type sysfs (rw,nosuid,nodev,noexec,relatime) proc on /proc type proc (rw,relatime) tmpfs on /dev/shm type tmpfs (rw,nosuid,nodev) devpts on /dev/pts type devpts (rw,nosuid,noexec,relatime,gid=5,mode=620,ptmxmode=000) tmpfs on /run type tmpfs (rw,nosuid,nodev,mode=755) tmpfs on /run/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,size=5120k) tmpfs on /sys/fs/cgroup type tmpfs (ro,nosuid,nodev,noexec,mode=755) cgroup on /sys/fs/cgroup/systemd type cgroup (rw,nosuid,nodev,noexec,relatime,xattr,release_agent=/lib/systemd/systemd-cgroups-agent,name=systemd) cgroup on /sys/fs/cgroup/cpuset type cgroup (rw,nosuid,nodev,noexec,relatime,cpuset) cgroup on /sys/fs/cgroup/cpu,cpuacct type cgroup (rw,nosuid,nodev,noexec,relatime,cpu,cpuacct) cgroup on /sys/fs/cgroup/blkio type cgroup (rw,nosuid,nodev,noexec,relatime,blkio) cgroup on /sys/fs/cgroup/devices type cgroup (rw,nosuid,nodev,noexec,relatime,devices) cgroup on /sys/fs/cgroup/freezer type cgroup (rw,nosuid,nodev,noexec,relatime,freezer) cgroup on /sys/fs/cgroup/net_cls type cgroup (rw,nosuid,nodev,noexec,relatime,net_cls) systemd-1 on /proc/sys/fs/binfmt_misc type autofs (rw,relatime,fd=22,pgrp=1,timeout=300,minproto=5,maxproto=5,direct) mqueue on /dev/mqueue type mqueue (rw,relatime) debugfs on /sys/kernel/debug type debugfs (rw,relatime) configfs on /sys/kernel/config type configfs (rw,relatime) fusectl on /sys/fs/fuse/connections type fusectl (rw,relatime) /dev/mmcblk0p1 on /boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,errors=remount-ro) tmpfs on /run/user/1000 type tmpfs (rw,nosuid,nodev,relatime,size=44508k,mode=700,uid=1000,gid=1000) gvfsd-fuse on /run/user/1000/gvfs type fuse.gvfsd-fuse (rw,nosuid,nodev,relatime,user_id=1000,group_id=1000) $
Il y a un nombre important de montage de systèmes de fichiers virtuels, notamment dans la hiérarchie des Control Groups. Leur présence sur un système embarqué peut être discutable.
$ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/root 4031552 3197560 609480 84% / devtmpfs 218252 0 218252 0% /dev tmpfs 222520 0 222520 0% /dev/shm tmpfs 222520 4548 217972 3% /run tmpfs 5120 4 5116 1% /run/lock tmpfs 222520 0 222520 0% /sys/fs/cgroup /dev/mmcblk0p1 57288 20232 37056 36% /boot tmpfs 44508 0 44508 0% /run/user/1000
Il reste un peu de place dans le système de fichiers principal. Tant mieux car je ne compte pas l’agrandir pour le moment.
Désactivation du swap
$ free total used free shared buffers cached Mem: 445044 149644 295400 4960 17156 77196 -/+ buffers/cache: 55292 389752 Swap: 102396 0 102396
Horreur ! une zone de swap est réservée sur la carte SD. C’est une mauvaise idée, car dans le cas d’un système saturé on va réaliser un très grand nombre de lectures et d’écritures sur la mémoire Flash, ce qui peut avoir comme effet un vieillissement prématuré. Je conseille très fortement de désactiver ce mécanisme. Pour cela le plus simple, est de désinstaller le package dphys-swapfile
utilisé pour le support du swap intégré dans un système de fichiers.
$ sudo apt-get remove dphys-swapfile Reading package lists... Done Building dependency tree Reading state information... Done The following packages will be REMOVED: dphys-swapfile 0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded. After this operation, 85.0 kB disk space will be freed. Do you want to continue? [Y/n] y [...]
Bien que le package dphys-swapfile
ait été supprimé, le fichier de 100 Mo qu’il utilisait pour proposer cette mémoire alternative subsiste encore… éliminons-le !
$ ls -l /var/swap -rw------- 1 root root 104857600 Sep 24 15:33 /var/swap $ sudo rm -f /var/swap $ free total used free shared buffers cached Mem: 445044 220612 224432 4960 20384 142052 -/+ buffers/cache: 58176 386868 Swap: 0 0 0
Je préfère cette situation ! Nous voyons au passage qu’une bonne part de la mémoire est encore potentiellement libre (386868 ko).
Système de fichiers en lecture seule
Sur un système embarqué, je trouve important de laisser le système de fichiers principal, celui qui contient les exécutables binaires, les bibliothèques, etc. en lecture-seule. Ainsi en cas d’interruption brutale d’alimentation électrique, le système de fichiers restera intact, aucune écriture ne pouvant être en cours d’exécution au moment de la coupure. Cela réclame quelques efforts.
Tout d’abord, afin de simplifier les manipulations ultérieures, j’ai coutume de me créer deux petits scripts, que je nomme ro
(read only) et rw
(read/write), qui ont pour rôles respectifs de basculer le système de fichiers en lecture-seule ou lecture-écriture. Je les crée rapidement :
/usr/local/bin/ro: #! /bin/sh mount / -o ro,remount
et
/usr/local/bin/rw: #! /bin/sh mount / -o rw,remount
Il ne faut pas oublier de rendre ces scripts exécutables :
$ sudo chmod +x /usr/local/bin/ro /usr/local/bin/rw
Nous pouvons toujours essayer d’invoquer ro
, mais il échouera car certains processus maintiennent déjà ouverts des fichiers de l’arborescence principale.
$ sudo ro mount: / is busy
Lors du boot, le noyau monte lui-même la racine du système de fichier en s’appuyant sur le contenu du paramètre root=
transmis par le bootloader. Sur le Raspberry Pi, les paramètres de démarrage du noyau se trouvent dans le fichier /boot/cmdline.txt
. Le bootloader en ajoute d’autres également, mais cela ne nous concerne pas ici.
Par défaut, le noyau monte son arborescence en lecture-écriture, mais la présence du mot-clé ro
dans ses paramètres de démarrage lui demande de réaliser le montage en lecture-seule. Je vais donc commencer par éditer le fichier /boot/cmdline.txt
pour ajouter ce mot-clé.
/boot/cmdline.txt: ro dwc_otg.lpm_enable=0 console=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline fsck.repair=yes rootwait
J’ai inséré ici le mot-clé en début de ligne, mais on peut le placer n’importe où sur celle-ci. Attention : il faut bien que toutes les options soient sur la même ligne.
Une fois le boot du noyau terminé, l’espace utilisateur prend le relais, par l’intermédiaire de init
et ses scripts sur les distributions de type Système V ou de systemd
pour la plupart des distributions récentes. Durant cette étape de démarrage, le système de fichiers principal peut être remonté en lecture-écriture s’il est configuré ainsi.
Pour m’assurer que la racine du système de fichiers reste en lecture-seule après le boot du noyau, j’édite le fichier /etc/fstab
qui contient la configuration des partitions et je rajoute le mot clé ro
sur la ligne décrivant le montage de « /
« . Attention à ne pas ajouter d’espaces autour du mot-clé ou des virgules.
/etc/fstab: proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 2 /dev/mmcblk0p2 / ext4 defaults,ro,noatime 0 1
J’en ai profité pour effacer les deux dernières lignes de commentaire qui parlaient de dphys-swapfile
(que nous avons supprimé précédemment).
Vérifions le fonctionnement :
# reboot [...] raspberrypi login: pi Password: (raspberry) pi@raspberrypi:~$ sudo -i # echo hello > /test -bash: /test: Read-only file system # rw # echo hello > /test # cat /test hello # rm /test # ro mount: / is busy #
Systèmes de fichiers temporaires non persistants
Notre système démarre bien en mode lecture-seule, et nous ne pouvons pas écrire sur le système de fichiers principal. Une fois basculé explicitement en mode lecture-écriture, il devient possible de modifier le contenu de ce système de fichiers.
Néanmoins, il est impossible de revenir en mode lecture-seule, car des processus ont profité du laps de temps où le système est monté en lecture-écriture pour y ouvrir des fichiers en écriture et les maintenir ouverts. Essayons de savoir quels fichiers sont concernés. Tout d’abord, je cherche la liste des processus qui tiennent un fichier ouvert dans cette arborescence.
# fuser -v -m / USER PID ACCESS COMMAND /: root kernel mount / root 1 .rce. systemd root 2 .rc.. kthreadd [...] root 60 .rc.. kworker/0:1H root 91 .rce. systemd-journal root 93 frce. systemd-udevd root 180 .rc.. kworker/0:3 root 375 .rc.. cfg80211 root 450 .rce. sshd root 451 .rce. cron root 455 .rce. systemd-logind avahi 471 .rce. avahi-daemon messagebus 478 .rce. dbus-daemon avahi 490 .rce. avahi-daemon nobody 492 .rce. thd ntp 501 .rce. ntpd root 502 Frce. rsyslogd root 521 .rce. login root 522 .rce. login pi 534 .rce. systemd pi 545 .rce. (sd-pam pi 571 .rce. bash root 599 .rce. dhcpcd pi 697 .rce. bash root 707 .rce. sudo root 714 .rce. bash root 740 frce. lightdm root 745 Frce. Xorg root 758 .rce. lightdm pi 771 Frce. lxsession pi 795 Frce. ssh-agent pi 798 .rce. dbus-launch pi 799 .rce. dbus-daemon pi 805 .rce. gvfsd pi 809 .rce. gvfsd-fuse pi 820 Frce. openbox pi 821 Frce. lxpolkit pi 823 Frce. lxpanel pi 825 Frce. pcmanfm pi 832 Frce. ssh-agent root 834 .rce. polkitd pi 847 .rce. gvfs-udisks2-vo root 849 .rce. udisksd pi 859 .rce. gvfs-afc-volume pi 864 .rce. gvfs-mtp-volume pi 868 .rce. gvfs-gphoto2-vo pi 872 .rce. gvfs-goa-volume pi 881 Frce. menu-cached pi 888 .rce. gvfsd-trash
J’ai éliminé de la liste les threads du noyau sur lesquels je n’ai pas vraiment de contrôle. Les processus qui nous intéressent sont ceux maintenant un fichier ouvert en lecture-écriture. Ceci est caractérisé par un F
majuscule en début de troisième champ. Je filtre ces processus et affiche la liste complète des descripteurs dont ils disposent. La liste est énorme car il y a également les terminaux, les sockets, les pipes, les fichiers exécutables, etc…
# fuser -v -m / 2>&1 | awk '($3 ~ /F.*/){ print "/proc/"$2"/fd"}' | xargs ls -l [...]
À l’aide d’une longue séquence de grep
successifs, je ne conserve que la liste des fichier qui m’intéressent.
# fuser -v -m / 2>&1 | awk '($3 ~ /F.*/){ print "/proc/"$2"/fd"}' | xargs ls -l| grep '^l.w' | grep -v socket: | grep -v /dev/ | grep -v "/proc" | grep -v anon_inode | grep -v pipe l-wx------ 1 root root 64 Oct 4 15:52 10 -> /var/log/auth.log l-wx------ 1 root root 64 Oct 4 15:52 11 -> /var/log/user.log l-wx------ 1 root root 64 Oct 4 15:52 6 -> /var/log/syslog l-wx------ 1 root root 64 Oct 4 15:52 7 -> /var/log/kern.log l-wx------ 1 root root 64 Oct 4 15:52 8 -> /var/log/messages l-wx------ 1 root root 64 Oct 4 15:52 9 -> /var/log/daemon.log l-wx------ 1 root root 64 Oct 4 15:55 0 -> /var/log/Xorg.0.log l-wx------ 1 pi pi 64 Oct 4 15:55 1 -> /home/pi/.cache/lxsession/LXDE-pi/run.log l-wx------ 1 pi pi 64 Oct 4 15:55 2 -> /home/pi/.cache/lxsession/LXDE-pi/run.log l-wx------ 1 pi pi 64 Oct 4 15:55 1 -> /home/pi/.cache/lxsession/LXDE-pi/run.log l-wx------ 1 pi pi 64 Oct 4 15:55 2 -> /home/pi/.cache/lxsession/LXDE-pi/run.log l-wx------ 1 pi pi 64 Oct 4 15:55 4 -> /home/pi/.cache/openbox/openbox.log l-wx------ 1 pi pi 64 Oct 4 15:55 1 -> /home/pi/.cache/lxsession/LXDE-pi/run.log l-wx------ 1 pi pi 64 Oct 4 15:55 2 -> /home/pi/.cache/lxsession/LXDE-pi/run.log l-wx------ 1 pi pi 64 Oct 4 15:55 1 -> /home/pi/.cache/lxsession/LXDE-pi/run.log l-wx------ 1 pi pi 64 Oct 4 15:55 2 -> /home/pi/.cache/lxsession/LXDE-pi/run.log l-wx------ 1 pi pi 64 Oct 4 15:55 1 -> /home/pi/.cache/lxsession/LXDE-pi/run.log l-wx------ 1 pi pi 64 Oct 4 15:55 2 -> /home/pi/.cache/lxsession/LXDE-pi/run.log
Nous voyons que les fichiers ouverts en écriture servent essentiellement à enregistrer des traces d’activité.
Sur un système embarqué les traces servent au moment de la mise au point, mais ne sont plus utiles après le basculement en production. Nous pouvons donc accepter de les placer sur un disque tmpfs (ramdisk automatiquement formaté et dimensionné par le noyau) où elles resteront accessibles pendant le fonctionnement du système mais ne survivront pas à un reboot du Raspberry Pi. Nous avons vu plus haut, dans le résultat de la commande mount
, que le répertoire /run
est un point de montage d’un tmpfs. Utilisons-le pour y stocker les fichiers de trace.
# rm -rf /var/log # ln -s /run/log /var/log
Il existe également un cas particulier dans les fichiers de configuration du système : /etc/resolv.conf
. Lorsque le système utilise le mécanisme DHCP pour demander à un serveur local (une box par exemple) les paramètres du réseau, il enregistre dans ce fichier l’adresse du DNS (le serveur de noms qui permet de résoudre un nom de machine par exemple www.kernel.org en une adresse IP comme 199.204.44.194). Le fichier doit donc être accessible en écriture pendant le fonctionnement normal du système. Pour cela le plus simple est de le rediriger via un lien symbolique vers un répertoire sur un système de fichier tmpfs.
# rm -f /etc/resolv.conf # ln -sf /run/resolv.conf /etc/ # reboot
Système de fichiers modifiables et persistants
Nous pouvons également être amenés à utiliser des fichiers qui devront être modifiables pendant le fonctionnement du système, mais qui devront aussi être persistants, c’est-à-dire survivre à un redémarrage de la machine. Nous allons les placer sur une partition spécifique en sachant que leur situation est néanmoins un peu plus précaire que le reste du système en cas de coupure d’alimentation électrique.
Créons une partition, que nous utiliserons par la suite pour le répertoire /home/pi
. Ceci permettra ainsi de sauvegarder les fichiers de traces applicatives que nous avons observés plus haut. Je voudrais coller cette partition à la fin de l’espace disque libre, pour pouvoir ensuite agrandir la partition système (celle en lecture seule) afin de disposer de place supplémentaire si je veux installer de nouveaux packages. Je vais créer une partition de /home/pi
de 2 Go.
# fdisk /dev/mmcblk0 Welcome to fdisk (util-linux 2.25.2). Changes will remain in memory only, until you decide to write them. Be careful before using the write command. Command (m for help): p Disk /dev/mmcblk0: 7.4 GiB, 7948206080 bytes, 15523840 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xba2edfb9 Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 8192 122879 114688 56M c W95 FAT32 (LBA) /dev/mmcblk0p2 122880 8447999 8325120 4G 83 Linux
Notre système dispose déjà de deux partitions : la première contient le bootloader et le noyau (nous y reviendrons plus bas), la seconde notre système de fichiers principal. Nous voyons dans le résultat de la commande ‘p
‘ que la taille des secteurs est de 512 octets et que la carte SD contient 15523840 secteurs. Je vais donc démarrer ma partition au secteur 15523840 – 4*1024*1024 = 11329536.
Command (m for help): n Partition type p primary (2 primary, 0 extended, 2 free) e extended (container for logical partitions) Select (default p): p Partition number (3,4, default 3): 3 First sector (2048-15523839, default 2048): 11329536 Last sector, +sectors or +size{K,M,G,T,P} (11329536-15523839, default 15523839): (Entrée) Created a new partition 3 of type 'Linux' and of size 2 GiB. Command (m for help): p Disk /dev/mmcblk0: 7.4 GiB, 7948206080 bytes, 15523840 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xba2edfb9 Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 8192 122879 114688 56M c W95 FAT32 (LBA) /dev/mmcblk0p2 122880 8447999 8325120 4G 83 Linux /dev/mmcblk0p3 11329536 15523839 4194304 2G 83 Linux Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Re-reading the partition table failed.: Device or resource busy The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8). #
Le message final m’indique que le noyau n’a pas honoré la demande de fdisk
concernant la relecture de la nouvelle table de partition. Pour s’assurer qu’elle soit bien prise en compte, redémarrons.
# reboot [...] [ 5.202270] systemd[1]: Mounting FUSE Control File System... Raspbian GNU/Linux 8 raspberrypi ttyAMA0 raspberrypi login: pi Password: (raspberry) Last login: Sun Oct 4 16:13:30 UTC 2015 on tty1 Linux raspberrypi 4.1.7+ #817 PREEMPT Sat Sep 19 15:25:36 BST 2015 armv6l The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. pi@raspberrypi:~$ sudo -i # ls -l /dev/mmcblk0* brw-rw---- 1 root disk 179, 0 Oct 4 16:13 /dev/mmcblk0 brw-rw---- 1 root disk 179, 1 Oct 4 16:13 /dev/mmcblk0p1 brw-rw---- 1 root disk 179, 2 Oct 4 16:13 /dev/mmcblk0p2 brw-rw---- 1 root disk 179, 3 Oct 4 16:13 /dev/mmcblk0p3
La partition 3 est bien présente. Formattons-la.
# mkfs.vfat -n HOME /dev/mmcblk0p3 mkfs.fat 3.0.27 (2014-11-12)
J’ai choisi un format vfat pour mon système de fichiers. Ce choix peut paraître a priori surprenant, il s’agit d’un format limité, ne supportant ni le choix d’appartenance des fichiers (ils appartiennent tous à root par défaut), ni la modifications des droits (rwxr-xr-x
pour tous les fichiers), ni les fichiers spéciaux de périphériques, ni les sockets, ni les tubes nommés, ni même les liens symboliques. Autant dire que pour un système de type Unix, ce format est particulièrement restrictif. Mais justement, c’est ce qui lui donne une bonne robustesse en cas de coupure d’alimentation pendant une écriture. Naturellement le fichier en cours de modifications sera incomplet, mais le système de fichiers lui-même ne sera pas endommagé. Peut-être que quelques secteurs seront « perdus » car ils seront considérés comme utilisés alors qu’aucun fichier ne permettra d’y accéder, mais il n’y aura pas d’incohérence au niveau de la partition elle-même. C’est ce que notre expérience quotidienne des clés USB nous apprend : même si un utilisateur l’arrache de l’ordinateur sans l’avoir démontée proprement, la clé reste utilisable même si le fichier en cours d’écriture peut être éventuellement incomplet.
C’est pour cette propriété de vfat que je le préfère à d’autres systèmes comme ext2 qui peuvent nécessiter une étape de récupération (une vérification avec fsck
) avant d’être remontés en cas d’arrêt intempestif. Bien sûr pour une partition système en lecture seule je préfère très largement ext2 qui offre tout le support des fichiers Unix, mais pour un répertoire de sauvegarde simple (comme /home/pi
ici) le format fat32 conviendra parfaitement.
J’ai cité à dessein ext2 plutôt que ext3 ou ext4 car je refuse habituellement l’usage d’un journal lorsque le périphérique de support est une mémoire flash. Avec la journalisation proposée par ext3 et ext4 on multiplie par trois le nombre d’écritures en cas de modification d’un fichier. Ce qui divise donc par trois la durée de vie de la mémoire flash… Ceci n’a pas d’influence lorsque le système de fichiers est en lecture seule comme notre partition principale.
La partition est prête, il faudra la monter automatiquement au démarrage, je l’ajoute donc dans /etc/fstab
avec des options uid
et gid
qui fixent l’appartenance par défaut des fichiers qu’elle contient :
# rw # nano /etc/fstab proc /proc proc defaults 0 0 /dev/mmcblk0p1 /boot vfat defaults 0 2 /dev/mmcblk0p2 / ext4 defaults,ro,noatime 0 1 /dev/mmcblk0p3 /home/pi vfat defaults,uid=pi,gid=pi 0 1 # reboot [...] Raspbian GNU/Linux 8 raspberrypi ttyAMA0 raspberrypi login: pi Password: (raspberry) [..] pi@raspberrypi:~$ ls pi@raspberrypi:~$ echo hello > test pi@raspberrypi:~$ ls test pi@raspberrypi:~$ cat test hello pi@raspberrypi:~$
Nous avons bien réussi à créer un fichier sur la partition montée sur le répertoire /home/pi
.
J’aimerais également augmenter la taille de la partition principale au maximum afin qu’elle remplisse tout l’espace restant de la carte SD pour pouvoir ajouter éventuellement d’autres applications. C’est ce que fait habituellement l’utilitaire raspi-config
de la distribution Raspbian. Malheureusement il ne peut pas fonctionner ici car il n’accepte que de redimensionner la dernière partition de la liste, ce qui n’est pas notre cas.
Commençons donc par agrandir avec fdisk
la partition sans toucher au système de fichiers. Pour cela, il faut la détruire et la reconstruire avec le même secteur de départ et une longueur plus grande.
pi@raspberrypi:~$ sudo fdisk /dev/mmcblk0 [...] Command (m for help): p Disk /dev/mmcblk0: 7.4 GiB, 7948206080 bytes, 15523840 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xba2edfb9 Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 8192 122879 114688 56M c W95 FAT32 (LBA) /dev/mmcblk0p2 122880 8447999 8325120 4G 83 Linux /dev/mmcblk0p3 11329536 15523839 4194304 2G 83 Linux Command (m for help): d Partition number (1-3, default 3): 2 Partition 2 has been deleted. Command (m for help): n Partition type p primary (2 primary, 0 extended, 2 free) e extended (container for logical partitions) Select (default p): p Partition number (2,4, default 2): 2 First sector (2048-15523839, default 2048): 122880 Last sector, +sectors or +size{K,M,G,T,P} (122880-11329535, default 11329535): (Entrée) Created a new partition 2 of type 'Linux' and of size 5.4 GiB. Command (m for help): p Disk /dev/mmcblk0: 7.4 GiB, 7948206080 bytes, 15523840 sectors Units: sectors of 1 * 512 = 512 bytes Sector size (logical/physical): 512 bytes / 512 bytes I/O size (minimum/optimal): 512 bytes / 512 bytes Disklabel type: dos Disk identifier: 0xba2edfb9 Device Boot Start End Sectors Size Id Type /dev/mmcblk0p1 8192 122879 114688 56M c W95 FAT32 (LBA) /dev/mmcblk0p2 122880 11329535 11206656 5.4G 83 Linux /dev/mmcblk0p3 11329536 15523839 4194304 2G 83 Linux Command (m for help): w The partition table has been altered. Calling ioctl() to re-read partition table. Re-reading the partition table failed.: Device or resource busy The kernel still uses the old table. The new table will be used at the next reboot or after you run partprobe(8) or kpartx(8). # reboot
Après redémarrage nous pouvons redimensionner le système de fichiers sans perdre son contenu
pi@raspberrypi:~$ sudo rw pi@raspberrypi:~$ sudo resize2fs /dev/mmcblk0p2 pi@raspberrypi:~$ sudo reboot [...] pi@raspberrypi:~$ df Filesystem 1K-blocks Used Available Use% Mounted on /dev/root 5449836 3121868 2047096 61% / devtmpfs 218240 0 218240 0% /dev tmpfs 222512 0 222512 0% /dev/shm tmpfs 222512 4784 217728 3% /run tmpfs 5120 4 5116 1% /run/lock tmpfs 222512 0 222512 0% /sys/fs/cgroup /dev/mmcblk0p1 57288 24256 33032 43% /boot /dev/mmcblk0p3 2093048 1010248 1082800 49% /home/pi
Recompilation du noyau
Une dernière phase de personnalisation consiste à recompiler notre noyau. Pourquoi cela ? Tout d’abord pour le plaisir de voir notre système fonctionner sur un kernel que nous pouvons configurer et ajuster à notre guise. Ensuite pour disposer de tout l’environnement nécessaire (fichiers d’en-tête, Makefiles, et fichiers de configuration) nécessaires à la compilation de modules supplémentaires personnels.
Cette compilation est facile à réaliser, elle nécessite surtout un temps de traitement assez long (deux bonnes heures avec un Raspberry Pi 2, et huit environ avec le modèle 1).
Installons les packages nécessaires non présents dans la distribution de base :
pi@raspberrypi:~$ sudo rw pi@raspberrypi:~$ sudo apt-get install -y bc libncurses5-dev
Ensuite récupérons les sources du noyau adaptées pour le Raspberry Pi :
pi@raspberrypi:~$ git clone https://github.com/raspberrypi/linux rpi-linux remote: Counting objects: 4521622, done. remote: Compressing objects: 100% (4139/4139), done. remote: Total 4521622 (delta 3292), reused 400 (delta 400), pack-reused 4517078 Réception d'objets: 100% (4521622/4521622), 1.26 GiB | 1.80 MiB/s, done. Résolution des deltas: 100% (3735624/3735624), done. Vérification de la connectivité... fait. Checking out files: 100% (49945/49945), done.
Nous allons compiler un noyau 4.1 :
pi@raspberrypi:~$ cd rpi-linux pi@raspberrypi:~/rpi-linux$ git checkout rpi-4.1.y
Voyons les configurations existantes pour notre système :
pi@raspberrypi:~/rpi-linux$ make help [..] bcm2709_defconfig - Build for bcm2709 bcm2835_defconfig - Build for bcm2835 bcm_defconfig - Build for bcm bcmrpi_defconfig - Build for bcmrpi bockw_defconfig - Build for bockw cerfcube_defconfig - Build for cerfcube clps711x_defconfig - Build for clps711x [..]
Celle qui nous intéresse pour le Raspberry Pi modèle 1 (B, A B+) est bcmrpi
(Broadcom Raspberry Pi).
pi@raspberrypi:~/rpi-linux$ make bcmrpi_defconfig
Pour un Raspberry Pi modèle 2, on fera :
pi@raspberrypi:~/rpi-linux$ make bcm2709_defconfig
Nous partons de cette configuration mais pouvons la modifier quelque peu :
pi@raspberrypi:~/rpi-linux$ make menuconfig
Je lance la compilation avec deux jobs en parallèle sur Raspberry Pi modèle 1 B, on peut en lancer environ 8 en parallèle sur un modèle 2.
pi@raspberrypi:~/rpi-linux$ make -j 2
Huit heures plus tard environ sur un modèle 1 (ou 1h30 sur un modèle 2) j’installe le nouveau noyau et ses modules :
pi@raspberrypi:~/rpi-linux$ sudo make modules_install pi@raspberrypi:~/rpi-linux$ sudo cp /boot/kernel.img /boot/kernel.img.prev pi@raspberrypi:~/rpi-linux$ sudo cp /boot/kernel7.img /boot/kernel7.img.prev pi@raspberrypi:~/rpi-linux$ sudo cp arch/arm/boot/zImage /boot/kernel.img pi@raspberrypi:~/rpi-linux$ sudo cp arch/arm/boot/zImage /boot/kernel7.img pi@raspberrypi:~/rpi-linux$ sudo reboot
Notez que le bootloader charge l’image kernel.img
sur les Raspberry Pi 1 et kernel7.img
sur les Raspberry Pi 2. Nous avons sauvegardé les images précédentes au cas où le nouveau noyau ne fonctionne pas… Après le redémarrage nous pouvons vérifier notre version :
pi@raspberrypi:~$ uname -a Linux raspberrypi 4.1.10-cpb #1 PREEMPT Mon Oct 5 10:58:11 UTC 2015 armv6l GNU/Linux
Conclusion
Nous avons pris ainsi possession d’une distribution Raspbian standard et à travers quelques modifications (qui ne changent pas la compatibilité pour les mises à jour) amélioré sa résilience en cas de coupure d’alimentation, protégé son système de fichiers principal contre les modifications involontaires, évité l’usure prématurée due au swap et conservé une partition spécifique pour l’utilisateur.
Je pense que ces modifications sont particulièrement utiles si l’on souhaite utiliser le Raspberry Pi dans un contexte de système embarqué plutôt qu’en desktop classique.
Toutes les remarques, corrections, critiques sont les bienvenues !
Pour faire un système embarqué, l’aspect reproductibilité du processus de construction du système Linux est essentiel. Ici, la série de bricolage d’une Debian pour aboutir à un résultat approximatif et non-reproductible est pour moi clairement l’exemple parfait de ce qu’il ne faut absolument pas faire.
Ce n’est pas pour rien qu’il existe des outils comme Buildroot ou Poky (du Yocto Project), précisément parce qu’ils permettent d’automatiser le processus de construction d’un système Linux embarqué.
Et puis compiler le noyau nativement sur la RPi, pendant 8 heures, c’est là aussi un exemple de mauvaise pratique. Les débutants qui liront ce post vont reproduire, sans forcément réfléchir, cet exemple, alors qu’ils devraient plutôt apprendre à cross-compiler.
Vraiment, je suis globalement attéré par la qualité générale de tous les posts/articles autour de la RPi. La très grande majorité d’entre eux sont très souvent des exemples parfaits de ce qu’il ne faut pas faire.
Bonjour Thomas,
On peut regretter le manque de qualité des constructions réalisées autour d’un Raspberry Pi, le fait est qu’elles existent.
Je suis parfaitement d’accord que dans un contexte industriel la reproductibilité d’une configuration est essentielle, c’est ce que je prêche à longueur d’années durant mes formations par exemple.
Lorsque je réalise un projet pour un client industriel, j’utilise généralement Buildroot, parfois (de plus en plus) Yocto, mais surtout je n’utilise pas de Raspberry Pi.
Néanmoins cette carte est à mon avis parfaitement adaptée pour des expériences hobbyistes ou des prototypes expérimentaux. Cet article s’adresse à ce type de public, qui ne dispose pas nécessairement de système hôte sous Linux, qui ne voudra pas s’investir dans la mise en oeuvre d’une toolchain de compilation croisée et encore moins dans la personnalisation de Yocto, mais qui a envie de réaliser rapidement un montage à base Raspberry Pi. Je connais pas mal de gens dans ce cas.
Et il reste néanmoins que leur utilisation du Raspberry Pi s’approche des problématiques d’un « vrai » système embarqué, alors il leur faut le résoudre tant bien que mal en s’appuyant sur une distribution existante.
Alors, pour être bien clair : cet article ne permet pas de transformer un Raspberry Pi avec une distribution Debian en un système embarqué robuste et industrialisable. Il s’agit simplement de le renforcer rapidement pour l’utiliser dans des circonstances un peu plus exigeantes que celles d’un desktop.
J’encourage les lecteurs à dépasser le stade de la distribution précompilée et à se former à l’utilisation de Yocto et Buildroot (par exemple avec les slides mis en ligne par Thomas).
Bonjour à tous,
je suis « globalement sidéré » de la manière dont certains peuvent réagir à des articles que je trouve personnellement très didactiques et d’un niveau que j’estime élevé pour ma part. Le fait que quelqu’un d’aussi compétent que Thomas intervienne sur ce blog en est d’ailleurs une preuve, non ?
L’avis de Thomas est tout à fait respectable …mais dans un contexte industriel où le déploiement du système doit se faire sur plusieurs cartes. La Raspberry n’est sûrement pas la plateforme de prédilection dans ce contexte.
Ceci étant dit et toujours de mon point de vue, apprendre Buildroot (ou encore pire de Poky) me semble incompatible avec le temps dont dispose un utilisateur moyen de Raspberry pour mener à terme son projet avant qu’il ne se décourage.
Convaincu de l’utilité des systèmes de build, je me suis essayé à ptxdist à l’époque où je « jouais » avec la carte mini2440. Cependant, j’ai assez vite laissé tomber car je me suis rendu compte qu’il fallait d’abord bien maitriser Linux avant de vouloir automatiser sa construction. Et c’est là que, d’une part, je rends hommage à Christophe pour ses articles qui donnent envie d’aller plus loin et, d’autre part, que je rejoins Thomas sur le fait que ce j’apprends ici me permettra peut-être un jour de ne plus me satisfaire de ce qui est présenté dans bon nombre de site ou de revues consacrés à la Raspberry.
Au plaisir de vous relire
Bonsoir,
je trouve la réaction de Thomas Petazzoni un peu sévère/impulsive.
Il est clair, qu’une carte de type Raspberry Pi/BeagleBone/autre n’est pas une solution industrielle mais un point d’entrée à coût relativement faible pour le hobbyiste/bricoleur. Et c’est en ce sens que je comprends l’article.
Il permet de donner des pistes pour rendre une carte RPi avec une distribution « standard » un peu plus proche des réalités d’un système embarqué.
Les solutions de type Poky/Buildroot/Amgström et j’en passe, sont pour un public plus « averti » et avec un objectif bien différent du bidouilleur. Elles demandent également un investissement en terme d’apprentissage beaucoup plus important.
Mes 2 cts.
Bonjour,
Tout d’abord bravo et merci de ce billet. J’aimerais également réagir sur la réponse de Thomas car je trouve que les propos sont injustifiés. Si l’auteur n’avait donné que de mauvaises directives, durs ou pas : il aurait fallut le dire. Pourtant ici, Christophe nous donne au fur et à mesure de ses billets des moyens : par transmission de la connaissance ou par les outils à utiliser, et pour moi ces moyens me permettent (et m’ont déjà permis) d’être autonome. Un peu comme la distribution Gentoo/funtoo pour comprendre les mecanismes en action: « apprendre à pêcher plutôt qu’avoir le poisson ». Et par conséquent, je regrette que Thomas n’ai pas inclus cet aspect important : dans quel but et quel contexte les propos de Christophe ont été donnés. J’y vois un jugement de valeurs assez surprenant pour un professionel de ce milieu. Etant d’ailleurs développeur/intégrateur dans le milieu de l’embarqué, je suis bien content d’avoir appris comment améliorer mon système, et même juste savoir comment trouver une information pour le noyau ou un FS, ce qui me fait défaut par manque de temps.
J’imagine pour les hobbyistes.
Un seul petit regret : la BeagleBone ou la Wandboard sont souvent mis en filigrane par rapport à la PI.
Bravo donc Christophe
systemd sur de l’embarqué, snif …..
Enfin la raspberry c’est plutot un nano ordinateur pas vraiment de l’embarqué mais ou est la limite de nos jours? C’est quoi en fait de l’embarqué ? Pas facile de répondre clairement à cette question.
Ah il est loin le temps ou on pouvait booter son noyau directement sur un DK et bidouiller une distribution pour l’adapter facilement.
Heureusement pour l’embarqué y a des trucs spécialisés comme yocto, ou comment s’embrouiller avec une usine à gaz mais bon c’est pour de l’industrie , faut bien que ca reste compliqué sinon c’est pas marrant.
Linux (le noyau) reste un critère de choix pour un système qu’il soit embarqué ou non. Par contre, pour les distributions on est clairement sur un virage un peu dur à négocier.
Bonjour,
Pareil je trouve la réaction de Thomas P. très dure. S’agissait-il d’une réaction sur l’ensemble des articles qui apparaissent sur la toile ?
Je trouve les posts de Christophe B. simple et facile d’accès pour le bricoleur/hobbyeur lambda de son canapé qui n’a pas tous les outils (matériel et logiciel) ni la connaissance pointue pour déployer des architectures de build telles que Yocto ou Buildroot (qui reste très simple pour ce dernier).
Mais ce qui est plus intéressant ce sont les petites astuces ou les complexités identifiées (qui viennent peut-être du monde Industriel) et qui amène l’utilisateur lambda à se poser des questions par exemple sur la robustesse, la sécurité, l’administration et qui amène aussi à se poser des questions sur l’architecture du noyau et des services sous Linux. Ces posts introductifs sont un début de réflexion qui à mon sens amèneront l’utilisateur lambda à aller voir plus loin.
Enfin, il faudrait m’expliquer comment introduire la cross-compilation à quelqu’un sans que celui-ci n’ait de connaissance sur les compilateurs et la compilation native… Point de vue personnel qui me vient de mon expérience personnelle (enseignement…).
C’était mes 2 cts.
Bonjour,
Merci pour ce post.
On oublie parfois de justifier le « périmètre de validité » d’un article, mais bon présenter une raspberryPI + debian c’est déjà en soit définir un contour que légèrement « industrialisable ».
Cette approche est aussi très bonne pour sensibiliser au développement embarqué : « on prend vos outils et on vous démontre leur limite ».
J’ai travaillé avec Yocto et je suis d’accord pour dire que l’apprentissage est « long » avant d’obtenir un premier résultat.
Par ailleurs rien n’empêche avec buildroot ou Yocto d’avoir les problèmes d’init et de montage FS relevé ici.
Et je pense que c’est le but de cet article : avoir une configuration cohérente du FS avec son environnement.
Vraiment, je suis globalement TRES HEUREUX par la qualité générale de tous les posts/articles autour de la RPi et particulièrement de celui-çi. La très grande majorité d’entre eux sont très souvent des exemples parfaits de ce qu’il faut faire, pour une utilisation personnelle.
Un grand bravo à toi. Les débutants ont une meilleures connaissance du système RPi. Continue !
Dans l embarqué, chacun ses besoins ou pratiques. Personnellement, je considere que customiser une debian est une solution , de plus qui a fait ses preuves. L’essentiel est de maitriser ce qui doit être fait pour durcir le systeme. Je suis désolé Thomas, mais avec un buildroot, tu maitriseras pas plus / ni mieux !
Bonjour,
Attention à l’illusion de la protection contre les ruptures d’alim avec la partition système montée read-only. De manière inattendue, les problèmes sont parfois pire quand on a un watchdog en fonctionnement (ou sur une phase de reboot qui dérape), sans rupture d’alim! Bien des fabricants de stockage flash SD/USB testent en fait mieux le redémarrage à froid du firmware interne du stockage que son redémarrage à chaud: Gare aux usb-reset, lors du reset controleur (et des réinit au démarrage: typiquement dans uboot/bist/linux), qui tombent alors que des écritures étaient en cours. Les pointeurs internes corrompus peuvent mener à des corruptions absolument partout, sans aucun égard pour le partitionnement logique du média! Typiquement, c’est des corruptions aléatoires de la taille d’une page interne du média de stockage… qu’on décide de creuser le jour ou ça tombe sur la table de partition ou sur un fichier de sa partition système ro!
D’expérience, je ne partage pas non plus votre constat sur l’intérêt du FAT vs un Ext4 avec les options de montage qui vont bien (« noatime » pour limiter les écritures mais surtout « journal_checksum », afin d’éviter les problèmes de corruption massives, via les métadonnées, si on se limite au simple contrôle sémantique de base des transactions: Répertoires entiers qui « disparaissent », corruptions de SB catastrophiques sur de petites partitions ou il n’y en a pas de sauvegarde). Ext4 est très mature, les performances sont comparables à du FAT (attention: Un seul équivalent de SB=corruptions totales possibles), surtout dans le temps car le mballoc fait que cela ne fragmente pas. On conserve des perfs proches du séquentiel/gros fichier. Autre avantage, certains stockages USB (y compris grand public) supportent TRIM et peuvent être montés « discard » pour là aussi avoir des perfs plus constantes dans le temps.
En réalité, le facteur perf le plus utile c’est dans /sys/block/sd?/device/max_sectors que cela se passe pour les stockages usb. Pour ne pas poser de problèmes à des clef USB grand public de mauvaise qualité, Linux limite par défaut ce paramètre à 240 (les autres stockages SCSI, c’est 1024) mais on peut très souvent aller au delà, surtout avec des stockages de qualité.
Car ce paramètre joue sur le nombre max de blocs contigus pouvant être lus/écrits avec une seule commande SCSI read_10/write_10 (en dessous, donc, on saucissonnera les accès sans nécessité, ajoutant des commandes/protocole inutiles vs les stricts données, pénalisant les perfs).
Le jeu de commande pur permettrait en fait un u16 (65535) mais aller jusque là pourrait générer d’autres problèmes sous OS (mais uboot peut sans problème mettre plus, en patchant la valeur USB_MAX_XFER_BLK du common/usb_storage.c, au bénéfice des temps de boot).
Attention toutefois à bien tester ce que supportent les stockages pouvant rentrer dans son produit. Les problèmes ne sont parfois pas visibles de suite: Il faut un fichier suffisamment gros et sans fragmentation, sinon ou saucissonnera sous la limite sans voir les problèmes: Tester via l’écriture de tests hors OS (via un test écrit sous uboot ou dans un bist) ou après création de gros fichiers, sur une partition récemment formatée (=> il sera contigu) et verif via le combo debugfs (la commande, sur la partition) et la commande stat dans le shell debugfs, sur le fichier test (un seul extent Ext4 = contigu?).
En pratique, on arrive à presque égaler sous Linux/Ext4 les performances brutes (sans FS) du stockage.
Bref, les stockages flash ne nécessitent pas d’utiliser des systèmes de fichiers antédiluviens et les problèmes peuvent ne pas être tous gérables via le simple choix de système de fichier, quand ils concernent le firmware même du contrôleur intégré à son stockage flash: C’est bien plus fréquent qu’on ne le croit, y compris sur des modules destinés à un usage embarqué (eUSB). Ayant eu à en sélectionner, 100% de ceux que j’ai eu entre les mains ont leur problèmes, plus ou moins graves.
Merci pour ce tuto qui fait ressortir de bonnes pratiques pour nos Rpi sous Raspbian
Je n’aurais pas pensé par exemple à mettre le fs en lecture seule, je suis tombé sur ce blog en recherchant la meilleure façon de désactiver le swap (la désinstallation complete de l’outil en l’occurence :p) afin d’économiser un peu de lifetime sur ma nouvelle carte SD.
J’ai trouvé bien plus d’infos utiles et détaillées que ce que je recherchais au départ 🙂
Damien
PS: Je me sers du Rpi afin d’avoir un environnement de dev pour mes projets NodeJS.
bonjour Mr Blaess,
j’applaudie pour tout le temps consacré à écrire vos articles, qui, de mon côté, m’ont permis de remettre un peu le pied à l’étrier en matière d’informatique embarquée, et même de construire un « réel » système embarqué Linux patché temps réel avec linux-rt, grâce à buildroot et d’avoir un résultat très rapidement, pour un besoin particulier (projet freeware)
Tous vos articles sont des mines d’information et un trésor pour beaucoup de personnes.
Votre attittude est « ouverte » et cela plait à beaucoup de gens.
Dire que compiler un noyau Linux, et faire de l’embarqué sur une Raspi, est réservé aux « hobbyistes » est abusif et déplacé.
Combien de personnes de l’informatique ne savent même pas les commandes de base sous Linux !
Ayant une expérience en administration système et réseaux sous Unix/Linux, je suis réellement surpris par les propos de Mr Petazzoni, car vos articles sont d’un bon niveau et aide réellement et concrètement beaucoup de personnes, à faire le lien entre diverses choses de l’informatique en général, et de l’embarqué en particulier.
Ce que devrait comprendre Mr Petazzoni, c’est que beaucoup de gens / informaticiens n’ont pas le temps ni les moyens de creuser un sujet : la polyvalence prévaut sur l’expertise maintenant dans beaucoup de projets, où sont entremêlés diverses compétences.
Pour avoir regardé un petit peu du côté de Yocto, cela me fait un peu penser aux gens qui sont experts en Java / C++ : beaucoup de « branlette intellectuelle » pour beaucoup de complications aussi.
Ne sont « experts » que les gens fermés et peu prompt à se remettre en question.
Alors qu’on peut rester simple, et oui on peut faire de l’embarqué avec des cartes populaires comme la raspi, sans l’obligation d’avoir un TIMER, un WATCHDOG ou bien une RTC
et sans être obligé de fourrer son nez dans Yocto,
Stéphane
Bonjour Christophe,
Le temps a passé depuis l’écriture de cet article mais je voudrais savoir si les remarques concernant l’utilisation d’un système de fichier non journalisé pour préserver la carte SD sont toujours d’actualité ? Tu expliques en effet que l’on aurait à gagner en passant à ext2 à la place de ext4 (système par défaut de Raspbian) mais n’y apporte pas de solution. Dans mes souvenirs modifier dans le fstab ext4 pour ext2 suffirait à désactiver la journalisation sans avoir à formater la partition, mais je n’en suis pas certain. Serait-ce une bonne solution ? Ou bien est-ce simplement sans intérêt finalement ?
re-Bonjour,
après quelques recherches, je me rends compte que mon souvenir est erroné ; ce truc ne fonctionne pas avec ext4. Je me corrige donc : il est possible de désactiver la journalisation de la partition grâce à tune2fs après l’avoir démontée bien sûr. Par contre la question de l’opportunité de la chose reste entière au regard des risques induits par l’absence de journalisation !
La journalisation est intéressante sur des serveurs pour permettre un redémarrage rapide en évitant de vérifier des centaines de Go ou des To de disque.
Sur un système embarqué son intérêt est très limité. Généralement on essaye de laisser au maximum les partitions en lecture seulement.
Pour les partitions accessibles en lecture-écriture, la journalisation présente un inconvénient (assez faible il est vrai) : elle multiplie le nombre d’écritures ce qui réduit la durée de vie de la mémoire flash. C’est pour cela que je l’évite sur les systèmes que je configure.
Merci beaucoup pour ces précisions !
La journalisation apporte aussi de la robustesse en permettant de conserver un système de fichier valide: On peut en effet ne même pas arriver à charger l’initramfs pour pouvoir effectuer le fsck au boot. Normalement, certes, cela ne peut se présenter sur un système embarqué que sur un upgrade ou l’on autorise à ré-écrire ce qui est dans sa partition de boot. Mais sur un réseau avec des milliers d’équipements dans des pays au réseau electrique pas toujours fiable, cela arrive.
Par contre il faut que le boot loader supporte le rejeu de journal, ce qui n’est pas le cas de u-boot et de son support ext simplifié: Là, on peut se retrouver coincé avec un système ne bootant pas. On le plug sur un PC Linux (avec support Ext complet), ca semble correct… et remis sur la carte cela fonctionne! On jette un coup d’oeuil au dmesg du PC à l’insertion du media pour découvrir un « replay journal » salvateur.
Mais bon, en FAT en pareille circonstance c’est à tous les coups on perds.
Bonjour,
J’ai tenté l’opération, mais il me reste une erreur au démarrage que je n’arrive pas à résoudre.
Voici le message lorsque je fait un « systemctl status » :
$ systemctl status systemd-rfkill@rfkill0.service
* systemd-rfkill@rfkill0.service – Load/Save RF Kill Switch Status of rfkill0
Loaded: loaded (/lib/systemd/system/systemd-rfkill@.service; static)
Active: failed (Result: exit-code) since jeu. 2017-04-06 18:16:54 CEST; 6 days ago
Docs: man:systemd-rfkill@.service(8)
Process: 235 ExecStart=/lib/systemd/systemd-rfkill load %I (code=exited, status=1/FAILURE)
Main PID: 235 (code=exited, status=1/FAILURE)
Je me doute qu’il ne réussi pas à écrire quelque part, mais je ne trouve pas ou !
Si vous aviez une idée ?
Bonjour et merci pour cet excellent article.
Je me permet une petite remarque: après avoir effectué toutes les modifications décrites, le système se retrouve dans l’incapacité à utiliser la completion depuis le shell. J’obtiens l’erreur cannot create temp file for here-document: Read-only file system
Je pensais pourvoir le contourner en créant un lien symbolique depuis /tmp vers /var/tmp mais ça ne semble pas fonctionner. Finalement j’ai monté mon propre tmpfs depuis fstab et maintenant tout semble marcher parfaitement: tmpfs /tmp tmpfs defaults,size=256M 0 0 (la capacité est peut être un peu grande, je verrai à l’usage)
C’est bon à savoir. Merci de l’information.