Options de compilation pour Linux industriel (1)

Publié par cpb
Fév 19 2012

make menuconfig

J’ai remarqué une question récurrente, tant durant mes sessions de formation sur Linux industriel qu’au cours de prestations d’ingénierie concernant des systèmes temps-réel ou embarqués : « Quelles sont les options du noyau qui influent sur [un sujet donné] ? » Le sujet en question a généralement trait aux mécanismes d’ordonnancement, à la vitesse de boot, à la taille du code produit, etc.

Donner une réponse exhaustive est impossible mais au fil du temps, j’ai constitué une petite liste des options les plus importantes à vérifier lors de la compilation du noyau, pour optimiser certains aspects. Ces paramètres sont parfois complémentaires parfois antagonistes. Par exemple le souci d’économie énergétique sur un système embarqué autonome est aux antipodes des problématiques de temps de réponse aux interruptions en temps-réel.

Bien entendu, je ne traite pas ici des options permettant au kernel de fonctionner (reconnaître les périphériques présents, disposer des protocoles réseau, gérer les types de systèmes de fichiers nécessaires…) Je considère qu’elles sont indispensables pour que le noyau démarre. Ce qui m’intéresse ici, ce sont les options de compilation susceptibles d’améliorer le comportement dans un environnement industriel.

Je prends comme version de référence le noyau linux-3.2.tar.bz2 et je vais passer en revue les principaux menus de configuration que l’on peut observer avec  « make menuconfig » « make xconfig » « make gconfig » etc. Les paramètres décrits ci-dessous proviennent d’une configuration pour processeur x86, mais je décrirai également quelques options spécifiques à d’autres architectures.

 Menu General Setup

  • Cross-compiler tool prefix : lors d’une compilation croisée (pour un autre processeur), on indiquera ici le préfixe nécessaire pour trouver la cross-toolchain (que l’on peut générer de différentes manières). Par exemple /opt/cross-arm/usr/bin/arm-linux- indiquera que les appels au compilateur gcc devront se transformer en /opt/cross-arm/usr/bin/arm-linux-gcc, et ainsi de suite pour les autres outils de compilation (as, ld, ar, etc.). Il s’agit d’une option que l’on peut également surcharger en remplissant la variable d’environnement CROSS_COMPILE avant d’appeler make.
  • Kernel compression mode : pour optimiser la vitesse de boot on préférera une compression LZO, pour réduire au maximum la taille du noyau en mémoire flash (avant transfert dans la Ram) on choisira LZMA, pour avoir un équilibre entre ces deux paramètres j’utiliserais XZ. Sur certaines architectures, toutes les compressions ne sont pas disponibles.
  • Support for paging of anonymous memory (swap) : sur la plupart des systèmes industriels, l’utilisation de swap (partition ou fichier sur disque dans lesquels on transfère temporairement une partie de la mémoire Ram en cas de saturation) est proscrite. En effet le système de fichiers est généralement en mémoire flash qui ne supporte pas les écritures intensives. En outre cela diminue la prédictibilité des temps d’accès. Je désactive habituellement cette option afin de ne pas risque d’activer malencontreusement le swap ultérieurement.
  • System V IPC et Posix Message Queues : ces mécanismes de communication entre processus (files de messages, sémaphores, mémoire partagée) sont souvent employés dans les systèmes industriels, sauf si le code applicatif est constitué seulement de threads regroupé dans un unique processus. Généralement j’active ces deux options.
  • BSD Process accounting, Export task/process statistics, et Auditing Support : si ces options d’instrumentation peuvent être utiles pendant la phase de mise au point du code, elles n’ont plus lieu d’être activées sur un système en production. Je conseille de les désactiver (ce qui peut nécessiter d’intervenir dans les menus Security options et Virtualization que nous verrons dans d’autres articles).
  • Sous-menu RCU Subsystem : L’option Enable RCU priority boosting permet de limiter les inversions de priorité liées aux mécanismes de synchronisation Read-Copy-Update. Ceci peut être utile – bien que d’un effet limité – dans un système temps-réel à condition de mettre une valeur élevée (99 par exemple) pour Real-time priority to boost RCU readers to.
  • Kernel .config support et Enable access to .config through /proc/config.gz : ces deux options sont à mon avis très utiles. Elles permettent d’embarquer dans l’image du noyau compilé sa propre configuration (réalisée avec make menuconfig). La mise au point d’un système embarqué ou temps-réel peut nécessiter des dizaines de compilations et tests successifs en modifiant peu à peu les options décrites ici. Il n’est pas simple de garder une trace exacte de toutes les modifications apportées et la discipline nécessaire pour sauvegarder et documenter chaque fois le fichier .config vient souvent à manquer après des heures de frustrations et d’échecs successifs. Le fait que chaque noyau compilé puisse restituer sa propre configuration nous évite de gérer les versions et permet facilement de comparer les options utilisées.
  • Sous-menu Control Group support : la plupart des options de ce sous-menu peuvent être utiles pour gérer finement l’ordonnancement des tâches et la répartition des ressources (CPU, mémoire, entrées-sorties du sous-système Block, etc.). Ces paramètres peuvent servir à gérer des tâches en temps-partagé mais également en temps-réel (notamment Group CPU scheduler –> Group scheduling for SCHED_RR/FIFO).
  • J’ai évoqué l’option Automatic process group scheduling dans un article précédent. Elle active le regroupement automatique des processus rattachés au même terminal pour leur donner une part de CPU équivalente aux autres groupes en ordonnancement temps-partagé.
  • Sur de nombreux systèmes embarqués l’option Initial RAM filesystem and RAM disk sera nécessaire car elle permettra de démarrer avec un système de fichiers monté en mémoire Ram (quitte à accéder ensuite à des partitions différentes sur mémoire flash). On choisira en principe le même type de compression (LZMA, XZ, LZO…) que celui de l’option Kernel compression mode vue plus haut, en préférant un volume réduit ou une décompression plus rapide suivant les cas.
  • L’option Optimize for size sera activée sur les systèmes embarqués pour demander au compilateur de réduire la taille de l’image du noyau ; de même on désactivera Enable full-sized data structures for core qui se trouve un peu plus bas
  • Le sous-menu Configure standard kernel features (expert users) n’est parfois accessible que si l’option Embedded System (plus bas) est activée – ce qu’il faut faire. On peut désactiver toutes les options du sous-menu sur la plupart des systèmes embarqués. Le noyau deviendra totalement silencieux (pas de messages de trace avec printk(), pas d’avertissement avec WARN(), pas d’indication d’erreur interne avec BUG()) et ne nous fournira plus d’éléments de diagnostic. En revanche sa taille sera réduite et le boot sensiblement plus rapide.
  • J’active systématiquement Enable futex support pour bénéficier des mutex rapides (verrouillage sans passage par le noyau s’il n’y a pas de contention, pour plus de détails voir cet article précédent).
  • Toutes les options Profiling support, Kprobes, Optimize trace point call sites, et GCOV-based kernel profiling devront être désactivées sur le noyau final. Elles peuvent être trés utiles durant la mise au point du système, mais ne feraient que charger inutilement l’image cible.

Les options qui n’ont pas été mentionnées seront activées ou non en fonction de l’utilisation de votre système. Si l’appel-système signalfd() par exemple n’est jamais employé, l’option Enable signalfd() system call n’a pas vraiment d’intérêt. Néanmoins on ne gagnera pas grand-chose à la désactiver.

 

Voici un premier tableau récapitulatif des options à activer (Y) ou désactiver (N) en fonction des optimisations recherchées. Les options non mentionnées ici n’ont pas d’influence directe sur les aspects embarqués (taille mémoire et vitesse de boot) ou les performances temps-réel.

Option Optimisation
pour
embarqué
Optimisation
pour
temps-réel
Kernel compression mode LZMA / LZO
Support for paging of anonymous memory N N
BSD Process accounting N N
Open by fhandle syscalls N
Export statistics through netlink N
Auditing support N N
RCU Subsystem -> Enable tracing for RCU N N
RCU Subsystem -> Enable RCU priority boosting Y
Kernel .config support Y
Enable access to .config through /proc/config.gz Y
Control Group Support -> Example debug cgroup… N N
Control Group Support -> Freezer cgroup subsystem Y
Control Group Support -> Device controller… Y
Control Group Support -> Cpuset support Y
Control Group Support -> Group CPU -> …SCHED_RR/FIFO Y
Control Group Support -> Block IO controller Y Y
Control Group Support -> Enable Block IO controller debugging N N
Namespace support N
Automatic process group scheduling Y
Initial RAM filesystem and RAM disk Y
Support initial RAM disk cmopressed using LZMA Y
Support initial RAM disk cmopressed using XZ Y
Support initial RAM disk cmopressed using LZO Y
Optimize for size Y
Configure standard kernel features -> Enable 16-bit UID… N
Configure standard kernel features -> Sysctl syscall support N
Configure standard kernel features -> Enable support for printk N
Configure standard kernel features -> BUG() support N
Configure standard kernel features -> Enable Elf core dumps N
Enable full-sized data structures for core N
Enable futex support Y
Enable AIO support Y
Embedded system Y
Kernel performance… -> Kernel performance counters N
Kernel performance… -> Debug; use vmalloc to… N N
Enable VM event counters for /proc/vmstat N N
Profiling support N N
Kprobes N N
Optimize trace point call sites N N
GCOV-based kernel profiling -> Enable gcov-based … N N

Nous examinerons les options d’un autre menu dans le prochain article

Tous les commentaires, rermarques, corrections, sont les bienvenus…

URL de trackback pour cette page