SystemTap : Profilez et utilisez rapidement des fonctionnalités du kernel

From Deimos.fr / Bloc Notes Informatique
Jump to: navigation, search
SystemTap

1 Introduction

SystemTap est un logiciel pour simplifier la récupération d'informations sur un système Linux. Il permet d'analyser et diagnostiquer un problème de performance ou de fonctionnalité. Il permet de s'affranchir de tous les besoins de recompilation de kernel, de reboot et d’événements indispensable pour une collecte de donnée bas niveau.

SystemTap fournit une interface à la ligne de commande type awk et un language de scripting proche du C qui permet d'écrire des outils directement sur un live kernel. Au delà du tracing/probing, il est utile pour des taches complexes nécessitant une analyse temps réel, programmable avec réponses aux évenements...

SystemTap peut profiler tous les appels system qui utilisent kprobes. A l'inverse d'OProfile, SystemTap capture 100% des évennements.

Un des gros avantage de SystemTap, c'est qu'il a été conçu de manière à être exécuté sur des environnements de production. On a donc :

  • Une machine de développement : Sur laquelle on va compiler et tester les modules kernel SystemTap avec tous les outils et librairies nécessaire au bon développement de celui ci.
  • Des machines de Production : Avoir le minimum de packages installés, avec juste le module compilé désiré, récupéré de la machine de développement.

2 Installation

2.1 Red Hat

2.1.1 Développement

Assurez vous d'avoir le repository debuginfo. Si ce n'est pas le cas, créez ce fichier avec ce contenu (à adapter) :

Configuration File /etc/yum.repos.d/rhel-debuginfo.repo
[rhel-debuginfo]
name=Red Hat Enterprise Linux $releasever - $basearch - Debug
baseurl=ftp://ftp.redhat.com/pub/redhat/linux/enterprise/$releasever/en/os/$basearch/Debuginfo/
enabled=1

Puis installez ces packages :

Command yum
yum install systemtap kernel-debuginfo kernel-devel gcc

2.1.2 Production

Comme expliqué dans l'introduction, l'avantage de SystemTap, c'est que sur une machine de production, il n'y a qu'un seul package à installer :

Command yum
yum install systemtap-runtime

Lorsque vous utiliserez un module, vérifiez la compatibilité entre l'environnement de développement et de production grâce à cette commande :

Command modinfo
modinfo modulename | grep vermagic

Si vous voulez connaitre d'un coup tous les modules avec leur version de kernel associée :

Command bash
> for i in `lsmod | awk '{ print $1 }' | egrep -v '^Module$'` ; do modinfo $i | grep vermagic | xargs echo "$i :" ; donefuse : vermagic: 2.6.32-220.el6.x86_64 SMP mod_unload modversions
autofs4 : vermagic: 2.6.32-220.el6.x86_64 SMP mod_unload modversions
sunrpc : vermagic: 2.6.32-220.el6.x86_64 SMP mod_unload modversions
nf_conntrack_ipv4 : vermagic: 2.6.32-220.el6.x86_64 SMP mod_unload modversions
nf_defrag_ipv4 : vermagic: 2.6.32-220.el6.x86_64 SMP mod_unload modversions
...

3 Créer un script systemtap

Vous pouvez trouver beaucoup d'exemple sur le site de SystemTap : http://sourceware.org/systemtap/examples/

Les scripts doivent utiliser un notation avec des points et supportent les wilcards. Pour donner une idée de ce qui donnerait un hello world en systemtap :

Configuration File hello_world.stp
#! /usr/bin/env stap
probe begin { println("hello world") exit () }

3.1 Les fonctions

Un bon nombre de fonctions existent déjà et sont utilisable dans /usr/share/systemtap/tapset/*.
Pour appeler une fonction, on va utiliser probe. Voici un exemple :

Configuration File my_systemtap_script.stp
#! /usr/bin/env stap
probe kernel.function("foo")
probe kernel.function("*").return

Voici quelques infos que l'on peut trouver dans ces scripts histoire de comprendre un peu mieux ce qui s'y passe :

  • ioscheduler.elv_next_request : Détecte lorsqu'une requête (de type disque lecture/écriture) est récupérée de la queue
  • ioscheduler.elv_next_request.return : Sort (fonction return de n'importe quel langage) lorsqu'une requête est retournée
  • process.exec : Le process va exécuter un nouveau programme
  • process.release : Lorsque le process souhaité va être libéré de la mémoire (en état non Zombie)
  • netdev.receive : Voir l'arrivée de n'importe quelle donnée réseaux sur toutes les cartes
  • tcp.sendmsg : Lorsque le kernel envoie une trame tcp
  • vm.pagefault : Voir les pagesfault (lorsque la mémoire est physiquement allouée/lorsque les données sont prise depuis la swap...)

Si vous souhaitez obtenir la liste complète de toutes les fonctions disponibles par le kernel :

Command stap
stap -p2 -e 'probe kernel.function("*") {}' | sort -u

4 Exécution

4.1 Stap

Vous l'aurez certainement compris, c'est la commande stap qui est utilisée pour lancer le scripts. Cette commande est donc à utiliser sur une machine de développement et est découpée en 5 niveaux/étapes :

  1. Parsing du script (vérification de la syntaxe du script systemtap)
  2. Comparaison et vérification des symboles/fonctions avec celles du kernel-debuginfo
  3. Conversion du code SystemTap en C
  4. Création d'un module Kernel
  5. Chargement du module et lancement de celui ci (également déchargement, tout ceci requiert les privilèges root)

Il est possible de ne pas créer de script et de lancer directement la commande stap dans un shell. Vous pouvez également lui définir un niveau d'exécution de cette commande (par exemple 2 grâce à l'option -p). Si vous n'en spécifiez pas, les 5 niveaux seront exécutés et le module restera chargé jusqu'à sa fermeture (via Ctrl+C).

Voyons un exemple de ligne de commande qui va permettre de placer un traceur sur la fonction sys_open() du kernel et qui affichera tous les appels avec leurs arguments :

Command stap
stap -e 'probe syscall.open {printf("%s: %s\n", execname(), argstr)}'

Note : vous pouvez utiliser l'option -k pour garder une trace de votre compilation dans /tmp pour vérifier s'il y a eu un problème lors d'une étape

5 FAQ

5.1 systemtap ERROR: Build-id mismatch

Si vous observez ce genre de comportements lors d'une compilation d'un module SystemTap, c'est surement que la version du kernel-dev est différente de la version du kernel qui tourne actuellement sur votre machine. Pour le vérifier, il va falloir comparer le Build-id du kernel en cours d'exécution :

Command eu-readelf
> eu-readelf -n /boot/vmlinuz-`uname -r` | grep "Build ID"
    Build ID: efbb1bd2e40f890370b8f2fc536c991a2d4abda7

Avec celle du module kernel-dev :

Command eu-readelf
> eu-readelf -n /usr/lib/debug/lib/modules/ma_version_du_noyau/vmlinux | grep "Build ID"
    Build ID: adcf5270333d375aa5a034523b006373e8f54e48

Et là nous pouvons voir qu'il y a un problème de version, ce qui aura pour effet d'avoir ce type de message :

Passe 5 : lancement de l'exécution
ERROR: Build-id mismatch: "kernel" vs. "vmlinux" byte 0 (0xad vs 0xef) address 0xffffffff814f7380 rc 0
Warning: /usr/bin/staprun exited with status: 1
Pass 5: run completed in 10usr/10sys/232real ms.
Passe 5 : échec de l'exécution.Essayez encore avec une option '--vp 00001' supplémentaire.

Pour résoudre votre problème, il suffira donc de prendre la bonne version de chaque packages requis.