summaryrefslogtreecommitdiff
path: root/realtime/rt-specialties/handout_rt-specialties_de.tex
diff options
context:
space:
mode:
authorManuel Traut <manut@linutronix.de>2009-06-22 15:47:30 +0200
committerManuel Traut <manut@linutronix.de>2009-06-22 15:47:30 +0200
commit9cbb0a699f398daffa8c1808d02bf447ebf0c1f0 (patch)
treeea3f4d4081b0648e1da7b1e1d8d3dabe12705a0a /realtime/rt-specialties/handout_rt-specialties_de.tex
parent9e0bab8ec70646ed9c51d5c7d272da4b51698c6c (diff)
parent719085c3dc98ab3df272476e16e983e4a16fe14b (diff)
Merge branch 'master' of ssh://tglx.de/home/linutronix/git/schulung
Diffstat (limited to 'realtime/rt-specialties/handout_rt-specialties_de.tex')
-rw-r--r--realtime/rt-specialties/handout_rt-specialties_de.tex300
1 files changed, 294 insertions, 6 deletions
diff --git a/realtime/rt-specialties/handout_rt-specialties_de.tex b/realtime/rt-specialties/handout_rt-specialties_de.tex
index 4c391b2..33dc9b6 100644
--- a/realtime/rt-specialties/handout_rt-specialties_de.tex
+++ b/realtime/rt-specialties/handout_rt-specialties_de.tex
@@ -1,17 +1,305 @@
-\documentclass{article}
+\documentclass{lxarticle}
\usepackage{german}
\usepackage[utf8]{inputenc}
+\usepackage{lxheaders}
+\usepackage{lxextras}
\begin{document}
-\section*{Titel}
+\section*{Anwendung des Preempt RT Patches}
+\subsection*{Besorgen und Anwenden des Patches}
+Preempt RT wird als Patch gegen den Mainline Linux Kernel gepflegt.
+Unter:\newline
+http://www.kernel.org/pub/linux/kernel/projects/rt sind die aktuellsten Patche
+für Preempt RT zu finden. Im Unterverzeichnis older/ sind ältere Patche
+archiviert. Das Vorbereiten eines Kerneltrees mit Preempt RT ist denkbar
+einfach:
+\begin{lstlisting}
+# Vanilla Kernel
+wget http://www.kernel.org/pub/linux/kernel\
+/v2.6/linux-2.6.29.5.tar.bz2
-\subsection*{Abschnitt1}
+# Preempt RT Patch
+wget http://www.kernel.org/pub/linux/kernel\
+/projects/rt/patch-2.6.29.5-rt21.bz2
-Text
+# Extract the kernel tree
+tar xjvf linux-2.6.29.5.tar.bz2
+# Patch the kernel tree
+cd linux-2.6.29.5
+bzcat ../patch-2.6.29.5-rt21.bz2 | patch -p1
+\end{lstlisting}
+Mit Steven Rostedt's Version des Pythonskripts ''ketchup'' geht es sogar noch einfacher (Steven
+Rostedt's ketchup Version steht unter:\newline
+http://people.redhat.com/srostedt/rt/tools/ketchup-0.9.8-rt3 zum Download
+bereit):
+\begin{lstlisting}
+mkdir linux-2.6.29.5-rt21
+cd linux-2.6.29.5-rt21
+ketchup -f --no-gpg 2.6.29.5-rt21
+\end{lstlisting}
-\subsection*{Abschnitt2}
+\subsection*{Konfigurieren und Übersetzen eines Preempt RT Kernels}
+Die Konfiguration und das Übersetzen machen keinen Unterschied zu Linux ohne
+Preempt RT Patch:
+\begin{lstlisting}
+# external build directory
+mkdir ../build
+# base build on existing config
+cp /boot/config-x-x-x ../build/.config
+make O=../build oldconfig
+\end{lstlisting}
+Für ein Echtzeitsystem müssen verschiedene Kerneloptionen aktiviert werden:
+\begin{lstlisting}
+make O=../build menuconfig
+\end{lstlisting}
+Die wichtigsten Optionen befinden sich unter dem Menupunkt ''Kernel features''
+bzw. ''Processor type and features''.
+\begin{figure}[ht!]
+\centering
+\includegraphics[height=0.5\textwidth]{images/menu_rt_001.png}
+\end{figure}
+Dort müssen folgende Optionen aktiviert werden:
+\begin{itemize}
+\item High Resolution Timer Support
+\item Preemption Mode (Complete Preemption (Real-Time))
+\end{itemize}
+\begin{figure}[ht!]
+\centering
+\includegraphics[height=0.5\textwidth]{images/menu_rt_002.png}
+\end{figure}
+\begin{figure}[ht!]
+\centering
+\includegraphics[height=0.5\textwidth]{images/menu_rt_003.png}
+\end{figure}
+\begin{figure}[ht!]
+\centering
+\includegraphics[height=0.5\textwidth]{images/menu_rt_004.png}
+\end{figure}
+Das Übersetzen des Kernels erfolgt nun wie üblich mit
+\begin{lstlisting}
+make O=../build
+make O=../build modules
+make O=../build install
+make O=../build modules_install
+\end{lstlisting}
+\section*{Testen eines Preempt RT Systems}
+\subsection*{RT Tests}
+Die RT Tests sind eine Sammlung von Programmen, zur Validierung der
+Eigenschaften von Echtzeitsystemen. Die RT Tests umfassen folgende Tools:
+\begin{itemize}
+\item cyclictest: High Resolution Timer Testsoftware.
+\item hwlatdetect: Python Script zur Steuerung des Kernelmoduls zur Erkennung
+von System Management Interrupts (hwlat\_detector).
+\item pi\_stress: Stresstest für Mutexe mit Priority Inheritance Attribut
+\item signaltest: Benchmark, bei dem Signale zwischen Tasks ausgetauscht werden.
+\end{itemize}
+Die Sourcen der RT Tests werden in einem GIT Tree verwaltet.
+\begin{lstlisting}
+# Checkout RT Tests
+git-clone git://git.kernel.org/pub/scm/linux/kernel\
+/git/clrkwllms/rt-tests.git
-Text
+# Compile RT Tests
+cd rt-tests
+make
+\end{lstlisting}
+\subsection*{Cyclictest}
+Cyclictest ist die wohl meistgenutzte Testsoftware auf Preempt RT Systemen. Mit
+Cyclictest kann eine bestimmte Anzahl von Timertasks mit einem definierten
+Interval aufgesetzt werden. Für diese Tasks wird kontinuierlich die Abweichung
+zum gewünschten Intervall gemessen und hierfür die Maximale und Durchschnittliche
+Abweichung aufgezeichnet. Die wichtigsten Parameter für Cyclictest sind die
+Anzahl und die Priorität der gewünschten Timertasks, die Art des zu verwendenden
+Timers und das gewünschte Timerintervall:
+\begin{lstlisting}
+# 4 Timertasks (2000 , 2500, 3000, 3500us)
+# -i options tells us the interval of the first task
+# the interval of all other tasks will be increased
+# by 500us
+# The -p options tells us the priority of the first task
+# the priorities of all other tasks will be decremented by 1
+# -n = using nanosleep
+zi:~# cyclictest -p80 -n -t4 -i2000
+0.32 0.30 0.12 1/56 2124
+T: 0 ( 2121) P:80 I:2000 C: 1258 Min: 62 Act: 99 Avg: 83 Max: 161
+T: 1 ( 2122) P:79 I:2500 C: 1007 Min: 47 Act: 76 Avg: 77 Max: 130
+T: 2 ( 2123) P:78 I:3000 C: 841 Min: 54 Act: 76 Avg: 82 Max: 136
+T: 3 ( 2124) P:77 I:3500 C: 723 Min: 67 Act: 95 Avg: 96 Max: 177
+\end{lstlisting}
+\subsection*{Lastszenarien}
+Um eine Aussage über das Echtzeitverhaltens treffen zu können, interessiert in
+der Hauptsache das Verhalten in Worst-Case Szenarien (hohe CPU Last, hohe
+Interruptlast). Ein ausgezeichnetes Werkzeug, um CPU Last zu erzeugen, ist
+''hackbench''. Hackbench wurde ursprünglich als Schedulerbenchmark entwickelt.
+Es erzeugt eine bestimme Anzahl an Prozessgruppen von Clients und Servern, die
+über Sockets miteinander kommunizieren:\newline
+http://people.redhat.com/mingo/cfs-scheduler/tools/hackbench.c
+
+Interruptlast, läßt sich hervorragend mit einem Floodping von einem entfernten
+Rechner erzeugen. Ein Floodping schickt eine große Anzahl von ICMP Paketen in
+kurzer Zeit. Dies erzeugt eine hohe Anzahl von Netzwerkinterrupts. Um Floodpings
+zu generieren muß das Programm ping mit Rootrechten und mit der Option -f
+ausgeführt werden.
+\subsection*{Pitfall}
+Ein sehr häufig gemeldetes Phänomen bei Testläufen von Cyclictest mit einem
+Floodping als Lastszenario, sind extrem große Ausreißer in der Größenordnung von
+50ms. Dies ist auf ein ''Feature'' aktueller Preempt RT Kernel zurückzuführen.
+Da Preempt RT auch auf vielen Desktops eingesetzt wird, auf denen Low Latency
+Anwendungen betrieben werden (z.B. Multimedia Anwendungen), häuften sich
+Fehlerberichte, die letztendlich nicht auf ein Kernelproblem zurückzuführen
+waren, sondern auf eine Realtime Applikation, die den Rest des Systems
+aushungerte. Daher wurde eine Option eingeführt, die die Laufzeit von Realtime
+Tasks beschränken kann. Überschreiten die Realtime Tasks dieses Zeitlimit,
+werden diese für einen bestimmten Zeitraum nicht mehr geschedult. Die
+Standardeinstellung liegt bei 950ms. Bei Überschreiten der 950ms werden die
+Echtzeittasks für 50ms suspendiert.
+Da Interrupts unter Preempt RT als Kernelthread mit Echtzeitprioriät laufen
+und durch den Floodping eine hohe Anzahl an Netzwerkinterrupts
+(einschliesslich der zugehörigen Softinterrupts) erzeugt wird, nehmen Realtime
+Tasks im System einen Großteil der Resourcen ein. Somit kann es passieren, daß
+dieses Zeitlimit überschritten wird.
+Das Limit für die Rechenzeit kann durch Schreiben des gewünschten Wertes nach
+/proc/sys/kernel/sched\_rt\_runtime\_us angepaßt werden.
+Zum Deaktivieren dieser Funktion muß Folgendes getan werden:
+\begin{lstlisting}
+echo -1 > /proc/sys/kernel/sched_rt_runtime_us
+\end{lstlisting}
+\section*{Erstellen einer Realtime Task für Preempt RT}
+\subsection*{Schedulingklassen / Prioritäten}
+Eine Realtime Applikation auf Preempt RT ist eine POSIX Realtime Applikation.
+POSIX sieht für Echtzeitapplikationen folgende Schedulingstrategien vor:
+\begin{itemize}
+\item SCHED\_FIFO: Scheduling mit statischen Prioriäten
+\item SCHED\_RR: Round Robin mit Prioritäten
+\end{itemize}
+Echtzeitpriorität bekommt eine Applikation nur dann, wenn dies explizit
+gewünscht wird. Hierzu ist die Funktion sched\_setscheduler() vorgesehen.
+\subsection*{Beispiel einer Echtzeitapplikation}
+Das folgende Beispiel zeigt eine einfache POSIX Realtimeapplikation:
+\begin{lstlisting}
+/*
+ * POSIX Realtime Example
+ * based on the example on http://rt.wiki.kernel.org
+ /
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+#include <sched.h>
+#include <sys/mman.h>
+#include <string.h>
+
+#define MAX_SAFE_STACK (8*1024) /* The maximum stack size which is
+ guranteed safe to access without
+ faulting */
+
+void stack_prefault(void) {
+
+ unsigned char dummy[MAX_SAFE_STACK];
+
+ memset(&dummy, 0, MAX_SAFE_STACK);
+ return;
+}
+
+int main(int argc, char* argv[])
+{
+ struct sched_param param;
+
+ /* Declare ourself as a real time task */
+ param.sched_priority = 80;
+ if(sched_setscheduler(0, SCHED_FIFO, &param) == -1) {
+ perror("sched_setscheduler failed");
+ exit(-1);
+ }
+
+ /* Lock memory !!!*/
+ if(mlockall(MCL_CURRENT|MCL_FUTURE) == -1) {
+ perror("mlockall failed");
+ exit(-2);
+ }
+
+ /* Pre-fault our stack */
+ stack_prefault();
+
+ while(1) {
+ [...]
+ }
+}
+\end{lstlisting}
+Die oben aufgelistete Applikation zeigt sehr schön, was notwendig ist, um eine
+Applikation mit deterministischem Zeitverhalten zu erzeugen:
+\begin{itemize}
+\item RT Scheduling Policy und Priorität festlegen
+\item Speicher locken, um undeterministisches Zeitverhalten durch
+Pagefaults auszuschliessen.
+\item ''Stack Pre-Faulting'', um zu vermeiden, daß Stackfaults
+undeterministisches Zeitverhalten verursachen
+\end{itemize}
+Eine Ausgezeichnete Einführung zum Erstellen von Echtzeitapplikationen und zur
+Verwendung von Preempt RT findet sich unter:\newline
+http://rt.wiki.kernel.org
+\subsection*{Tracing / Latenzen aufspüren}
+\subsubsection*{FTrace}
+Ein hervorragendes Werkzeug, um kernelseitige Codepfade aufzuspüren, die lange
+Latenzzeiten verursachen, ist Ftrace. Ftrace wird über DebugFS, einem virtuellen
+Dateisystem, gesteuert und platziert dort auch seine Ausgaben. Die einfachste
+Methode, FTrace zu verwenden ist Cyclictest. Cyclictest biete bereits einige
+Optionen, um FTrace zu steuern. Die Option -f schällt Cyclictests Ftrace
+Support an, -b <max\_latency> veranlaßt Cyclictest, bei Überschreiten einer
+maximalen Latenzzeit, abzubrechen und einen Trace zu triggern.
+\subsubsection*{Kerneloptionen für FTrace}
+Um FTrace verwenden zu können, müssen beim Konfigurieren des Kernels einige
+unter dem Menupunkt ''Kernel hacking-->Tracers'' einige Optionen aktiviert werden:
+\begin{itemize}
+\item Kernel Function Tracer
+\item Beliebige Optionen, die mit Trace beginnen (der zu verwendende
+Tracetyp kann cyclictest über die Commandline mitgegeben werden, siehe
+cyclictest -h. Default ist der Event Tracer)
+\end{itemize}
+\subsubsection*{Beispiel eines Traces}
+Das Erstellen eines Traces mit cyclictest läßt sich am Besten mit einem Beispiel
+erläutern:
+\begin{lstlisting}
+# mount DebugFS
+mkdir -p /mnt/debugfs
+mount -t debugs debugfs /mnt/debugfs
+
+# list available tracers
+zi:~# cat /mnt/debugfs/tracing/available_tracers
+wakeup_rt wakeup preemptoff function sched_switch nop
+
+# start trace
+cyclictest -p80 -n -f -b 100
+
+zi:~# less /mnt/debugfs/tracing/trace
+# tracer: function
+#
+# TASK-PID CPU# TIMESTAMP FUNCTION
+# | | | | |
+IRQ-129-772 [000] 4154503386.851178: __rt_mutex_adjust_prio<-t
+IRQ-129-772 [000] 4154503386.851186: __rt_mutex_adjust_prio<-t
+IRQ-129-772 [000] 4154503386.851189: task_setprio<-__rt_mutex_
+IRQ-129-772 [000] 4154503386.851192: task_rq_lock <-task_setpr
+IRQ-129-772 [000] 4154503386.851195: sched_clock <-sched_clock
+IRQ-129-772 [000] 4154503386.851199: dequeue_task <-task_setpr
+IRQ-129-772 [000] 4154503386.851202: dequeue_task_fair <-deque
+IRQ-129-772 [000] 4154503386.851206: update_curr <-dequeue_tas
+IRQ-129-772 [000] 4154503386.851217: enqueue_task_rt <-task_se
+IRQ-129-772 [000] 4154503386.851221: dequeue_rt_stack<-enqueue
+IRQ-129-772 [000] 4154503386.851226: switched_to_rt <-task_set
+IRQ-129-772 [000] 4154503386.851234: timer_interrupt<-ret_from
+[...]
+\end{lstlisting}
+
+\subsection*{Kontrollfragen}
+\begin{itemize}
+\item Welche Optionen sollten beim Übersetzen eines Preempt RT Kernels
+mindestens gesetzt sein?
+\item Wozu dient das Tool cyclictest?
+\item Welchen bekannten ''Pitfall'' gibt es bzgl. hoher Latencies mit Floodping
+als Lastszenario? Wie kann dieser umgangen werden?
+\item Welche 3 Schritte sind notwendig, um das deterministische Zeitverhalten
+einer Applikation zu garantieren?
+\end{itemize}
\end{document}