Open Source im professionellen Einsatz
Linux-Magazin 06/2014
© psdesign1, Fotolia

© psdesign1, Fotolia

Kernel- und Treiberprogrammierung mit dem Linux-Kernel – Folge 74

Kern-Technik

,

Die Ktap-Runtime-Library ermöglicht detaillierte Einsichten in den Linux-Kernel und eigene Treiber. Das Programmieren von Skripten im Ktap-eigenen Lua-Dialekt ist zum Glück leicht zu erlernen.

1283

Der Blick in interne Abläufe des Linux-Kernels lohnt sich nicht nur aus reiner Neugier. Sowohl der Sysadmin als auch der Kernel- oder Anwendungsprogrammierer gewinnt damit wertvolle Informationen zur Optimierung und Fehlersuche. Mit dem Tracing-Toolkit Ktap [1] ist das erstaunlich leicht. Meist installiert es sich problemlos und ist dank des Programmierinterface einfach in der Handhabung.

Wie in der vorhergehenden Kern-Technik [2] gezeigt, gelingt es bereits mit einfachen Aufrufen, Datei-Überwachungen zu implementieren oder Histogramme über die am häufigsten verwendeten Systemcalls zu erzeugen. Aber es geht noch viel mehr. Wer sich mit der Programmiersprache Lua beschäftigt sowie mit der vom Ktap-Entwickler Jovi Zhangwei bereitgestellten Runtime-Library, kann Programme schreiben, die gezielt Informationen im Kernel abgreifen.

Die Programmiersprache Lua hat der Huawei-Mitarbeiter Zhangwei für die Problemstellung Kerneltracing angepasst. Das äußert sich etwa darin, dass die im Original Pascal-ähnliche Syntax einer C-ähnlichen Syntax gewichen ist. Statt einen Block mit »then« und »endif« zu kennzeichnen, nutzt Ktap geschweifte Klammern (Tabelle 1).

Tabelle 1

Ktap-Lua kurz und knapp

Konstrukt

Bedeutung

»if (Bedingung) {Anweisung} else {Anweisung)}«

Bedingte Ausführung

»while (Bedingung) {Anweisung}«

Kopfgesteuerte Schleife, Abbruch mit »break«

»repeat Anweisung until (Bedingung)«

Fußgesteuerte Schleife, Abbruch mit »break« ; keine Klammern, kein »while« , sondern »until«

»for ( i=Init, Limit, Step ) {Anweisung}«

Schleife im Lua- respektive Basic-Stil

»for ( Init; Bedingung; Körper) {Anweisung}«

Klassische C-Schleife, Abbruch mit »break«

»for (k, v in pairs([Tabelle])) {Anweisung}«

Key-Value-Schleife über den Inhalt einer Tabelle

»#«

Kommentar

»;«

Optionaler Abschluss eines Befehls

»function Funktionsname(Parameterliste) {Anweisung return ...}«

Funktionen geben keinen, einen oder sogar mehrere Werte zurück

»+« , »-« , »*« , »/« , »%« , »^«

Arithmetische Operatoren

»and« , »or« , »not«

Logische Operatoren

»==« , »<« , »>« , »<=« , »>=« , »~=«

Vergleichsoperatoren

»..«

Stringoperator (zum Aneinanderhängen, entspricht »+« bei Java)

Sonst enthält Lua die typischen Elemente einer Programmiersprache: Bedingungen, Schleifen, Operatoren, Variablen. Letztere zeigen den größten Unterschied zu der von Kernelprogrammierern eingesetzten Sprache C: Lua-Variablen sind nicht typisiert. Erst wenn einer Variablen ein Wert zugewiesen wird, legt Lua den Datentyp fest. Dabei erkennt der Bytecode-Interpreter, ob es sich um einen Integerwert, eine Fließkommazahl, ein Boolean oder einen String handelt.

Eine weitere Besonderheit ist der Datentyp Tabelle. Lua verarbeitet Tabellen, die in ihren Zeilen nicht immer die gleiche Anzahl Spalten haben, die also beispielsweise dreieckig sind. Noch interessanter ist die Möglichkeit, Tabelleneinträge nicht nur per Index, sondern auch per Inhalt (Name) als Assoziativ-Array anzusprechen.

Das machen sich Ktap-Programme eifrig zu Nutze, wenn sie beispielsweise die Aufrufe eines Systemcalls zählen sollen (Abbildung 1). In diesem Fall dient der Name des Systemaufrufs (»probename« ) als Index in die Tabelle, der dort abgelegte Wert zählt das Auftreten. Über Tabellen kann man übrigens mit einer besonderen Art der For-Schleife iterieren, die auf der Ktap-Funktion »pairs()« beruht.

Abbildung 1: Histogramm eingebaut: Das Ktap-Programm sctop.kp ermittelt die am häufigsten verwendeten Systemcalls.

Tracepoints

Die Runtime-Library ist eine Lua-Erweiterung, die die Sprache in den Linux-Kernel einbettet. Sie hilft Daten ausgeben, enthält statistische Funktionen und setzt die Tracepunkte. Darüber hinaus bietet sie Zeitmessfunktionen, um beispielsweise Latenzen zu bestimmen. Tracepunkte setzt der Ktap-Anwender mit der Funktion »trace« . Die hat den folgenden Aufbau, wie auch Abbildung 2 zeigt:

Abbildung 2: Das zentrale Schlüsselwort für ein Ktap-Programm ist trace. Es lässt sich auf eine Funktion ansetzen und mit Filtern einschränken.
trace Funktion / Filter / { Aktion }

Sobald der Kernel die spezifizierte Funktion aufruft, wendet Ktap den Filter an. Trifft die Filterbedingung zu, wird der hier als Aktion angegebene Lua-Code abgearbeitet. Im Rahmen dieses Codes kann der Anwender auf eine Reihe von Variablen zugreifen (Tabelle 2). Es ist auch möglich, auf die Argumente der Kernelfunktion zuzugreifen, die den Tracepunkt aktiviert hat. Falls es sich um Adressen aus dem Userland handelt, lassen sich auch die dazugehörigen Speicherzellen auslesen.

Tabelle 2

Eingebaute Variablen

Variablenname

Bedeutung

»arg0« … »arg9«

Argumente des Event-Objekts

»cpu«

ID der aktuell genutzten CPU

»pid«

Prozess-Identifikationsnummer

»tid«

Thread-Identifikationsnummer

»uid«

User-Identifikationsnummer

»execname«

Name des gerade ausgeführten Programms

»argstr«

Repräsentation des Event-Strings

»probename«

Name des Events

An dieser Stelle fallen dem Leser möglicherweise die unterschiedlichen Bezeichnungen im Vergleich zum vorigen Artikel [2] auf – der Ktap-Entwickler Zhangwei hat die letzten Monate damit verbracht, Ktap auf die Aufnahme in den Standard-Linux-Kernel vorzubereiten. Im Zuge dieser noch nicht abgeschlossenen Tätigkeit hat er auch einige Veränderungen am Interface vorgenommen. Daher ist es ratsam, Ktap per »git pull« auf den neuesten Stand (bei Redaktionsschluss 0.4) zu bringen.

Die Spezifikation eines Tracepunkts in der beschriebenen Art und Weise ist insofern kompliziert, als Ktap verschiedene Trace-Methoden respektive Event-Typen des Linux-Kernels nutzt, die der Anwender spezifizieren muss (Abbildung 3). So lassen sich Linux-Systemcalls wie »open()« , »read()« , »exit()« oder »exec()« mit Hilfe des Schlüsselworts »syscall« überwachen, viele interne Kernelfunktionen über »ftrace« und Kernelprobes über »kprobe« .

Abbildung 3: Hintergrundinformationen über Tracepoints bezieht Ktap aus dem /sys-Filesystem.

Anfang und Ende

Ein weiteres wichtiges Feature bietet außerdem die Möglichkeit, den Tracepunkt auf den Einstieg in (»enter« ) oder den Ausstieg (»exit« oder auch »%return« ) aus einer Kernel- oder Bibliotheksfunktion zu setzen.

Die Runtime-Library stellt mit »tick-*« , »profile-*« und »trace_end« weitere Event-Funktionen zur Verfügung (Tabelle 3). Die Timer »tick« und »profile« bieten die Möglichkeit, Funktionen zeitgesteuert abarbeiten zu lassen. Den Code einer »tick« -Funktion arbeitet eine einzelne CPU periodisch ab, den Code einer »profile« -Funktion jeder der in einem System vorhandenen Prozessoren.

Tabelle 3

Elemente der Ktap-Runtime-Library

Schlüsselwort

Beschreibung

Basisfunktionen

print

Unformatierte Ausgabe

printf

Formatierte Ausgabe (wie in C)

print_hist

Ausgabe eines Histogramms

pairs

Funktion zur Iteration durch eine Tabelle

len

Länge eines Strings

delete

Löschen von Tabellen

stack

Stacktrace

print_trace_clock

Ausgabe eines genauen Zeitstempels

num_cpus

Anzahl der CPU-Kerne

arch

Architektur

kernel_v

Kernelversion

kernel_string

Konvertiert eine Kerneladresse in einen String

user_string

Konvertiert eine Userspace-Adresse in einen String

stringof

Konvertiert eine Adresse in einen String

ipof

Adresse der übergebenen Funktion

gettimeofday_ns

Zeitstempel in Nanosekunden

gettimeofday_us

Zeitstempel in Mikroekunden

gettimeofday_ms

Zeitstempel in Millisekunden

gettimeofday_s

Zeitstempel in Sekunden

curr_taskinfo

Informationen zur aktiven Task

in_iowait

Wahr, falls sich die Task im Schlafen-Zustand befindet

in_interrupt

Wahr, falls sich der Kernel gerade im Interruptkontext befindet

exit

Beendet das Ktap-Programm

Ausgabe

ansi.clear_screen

Löschen des Bildschirms

ansi.set_color

Setzen der Farbe 1

ansi.set_color2

Setzen der Farbe 2

ansi.set_color3

Setzen der Farbe 3

ansi.reset_color

Farbpalette zurücksetzen

ansi.new_line

Neue Zeile ausgeben

Tracing

trace_by_id

Tracepunkt über die Event-ID setzen

trace_end

Funktion, die bei Skriptabbruch aufgerufen wird

kdebug.tracepoint

Tracepunkt per Kerneldebugger setzen

kprobe

Tracepunkt per Kprobe setzen

Netzwerk

ip_sock_saddr

Quelladresse eines Sockets extrahieren

ip_sock_daddr

Zieladresse eines Sockets extrahieren

format_ip_addr

IP-Adresse in String konvertieren

Timer

tick_us

Funktion periodisch auf einer CPU aufrufen, Zeitangabe in Mikrosekunden

tick_ms

Funktion periodisch auf einer CPU aufrufen, Zeitangabe in Millisekunden

tick_s

Funktion periodisch auf einer CPU aufrufen, Zeitangabe in Sekunden

profile_us

Funktion periodisch auf jedem CPU-Kern aufrufen, Zeitangabe in Mikrosekunden

profile_ms

Funktion periodisch auf jedem CPU-Kern aufrufen, Zeitangabe in Millisekunden

profile_s

Funktion periodisch auf jedem CPU-Kern aufrufen, Zeitangabe in Sekunden

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 5 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Linux-Magazin kaufen

Einzelne Ausgabe
 
Abonnements
 
TABLET & SMARTPHONE APPS
Bald erhältlich
Get it on Google Play

Deutschland

Ähnliche Artikel

  • Kern-Technik

    Das Tracing-Werkzeug Ktap hilft Admins und Kernelentwicklern bei Tuning und Fehlersuche. Diese Kern-Technik zeigt die ersten Schritte mit dem Interpreter im Kernel.

comments powered by Disqus

Ausgabe 10/2017

Digitale Ausgabe: Preis € 6,40
(inkl. 19% MwSt.)

Artikelserien und interessante Workshops aus dem Magazin können Sie hier als Bundle erwerben.