Pünktlich und priorisiert
Die Anwendung der Echtzeit-Mutexe ist einfach: Im Kernel gibt es die Datenstruktur »struct rt_mutex« und die darauf aufbauenden Funktionen »rt_mutex_lock()«, »rt_mutex_lock_interruptible()«, »rt_mutex_timed_lock()« und »rt_mutex_unlock()«. Wie in Listing 1 zu sehen, ruft der Entwickler die Funktion »rt_mutex_lock()« (im Code in der Variante »rt_mutex_lock_interruptible()«) auf, bevor sein Code den kritischen Abschnitt betritt. Gleiches gilt für »rt_mutex_unlock()«, um das Ende des kritischen Abschnitts zu signalisieren.
Die Funktionen »rt_mutex_lock()« und »rt_mutex_lock_interruptible()« unterscheiden sich nur dadurch, dass sich letztere durch ein Signal unterbrechen lässt, erstere nicht. Die Funktion »rt_mutex_timed_lock()« sorgt dafür, dass ihr Thread nicht unendlich lange auf die Freigabe des kritischen Abschnitts wartet.
|
Listing 1: Zwei Threads in |
|---|
01 #include <linux/module.h>
02 #include <linux/version.h>
03 #include <linux/init.h>
04 #include <linux/sched.h>
05 #include <linux/completion.h>
06 #include <linux/kthread.h>
07
08 static wait_queue_head_t wq;
09 static DECLARE_COMPLETION(on_exit);
10 static struct rt_mutex tmut;
11 static struct task_struct *plow, *phigh;
12
13 static int process(void *data) {
15 unsigned long to, i;
16 struct sched_param schedpar;
18
19 schedpar.sched_priority = (long)data;
20 sched_setscheduler(current, SCHED_FIFO, &schedpar);
22 printk("Thread %d Prio %d: rt_mutex_lock().n",
24 current->pid, current->rt_priority);
26
27 // Begin des kritischen Abschnitts
28 if (rt_mutex_lock_interruptible(&tmut, 0) < 0) {
30 printk("Interrupt waehrend rt_mutex_lock_interruptiblen");
31 } else {
32 printk("Thread %d, Prio %d: im kritischen Abschnitt.n",
34 current->pid, current->rt_priority);
35 for (i = 0; i < 5; i++) {
36 to = HZ; // eine Sekunde warten
37 to = wait_event_interruptible_timeout(wq, (to == 0), to);
39 printk("Thread %d Prio %d: aktuelle Prioritaet: %dn",
40 current->pid, current->rt_priority, 99 - current->prio);
43 }
44 }
45 printk("Thread %d Prio %d: rt_mutex_unlock().n",
47 current->pid, current->rt_priority);
49 rt_mutex_unlock(&tmut);
50 // Ende des kritischen Abschnitts
51
52 printk("Thread %d Prio %d: aktuelle Prioritaet: %dn",
54 current->pid, current->rt_priority, 99 - current->prio);
56 complete_and_exit(&on_exit, 0);
57 }
58
59 static int __init kthread_init(void) {
61 unsigned long to; // Timeout
62
63 init_waitqueue_head(&wq);
64 rt_mutex_init(&tmut);
65
66 printk("Thread mit niedriger Prio...n");
67 plow = kthread_create(process, (void *)50, "prio-low");
69 if (IS_ERR(plow)) return -EFAULT;
70 wake_up_process(plow);
71
72 to = HZ; // eine Sekunde warten
73 to = wait_event_interruptible_timeout(wq, (to == 0), to);
74
75 printk("Thread mit hoher Prio ...n");
76 phigh = kthread_create(process, (void *)70, "prio-high");
78 if (IS_ERR(phigh)) return -EFAULT;
79 wake_up_process(phigh);
81 return 0;
82 }
83
84 static void __exit kthread_exit(void) {
86 printk("kthread_exit()n");
87 wait_for_completion(&on_exit); wait_for_completion(&on_exit);
89 }
90
91 module_init(kthread_init); module_exit(kthread_exit);
94 MODULE_LICENSE("GPL");
|
Prozess rechts überholt
Wer Listing 1 kompiliert, erhält Einblick in die Prioritätsvererbung. Lädt er das Modul, erzeugt es zwei Threads. Einer erhält eine niedrige Priorität von 50, der andere eine hohe von 70. Das Beispiel räumt dem Thread mit niedriger Priorität genug Zeit ein, um den über das Realtime-Mutex geschützten kritischen Abschnitt zu betreten. Danach aktiviert es den zweiten Thread, der ebenfalls »rt_mutex_lock()« aufruft. Der bevorzugte Prozess wartet auf das RT-Mutex des niedriger eingestuften. Daher vererbt der Kernel die hohe Priorität auf den nachrangigen Prozess (Abbildung 3).
Abbildung 3: Der hochpriorisierte Thread 19679 vererbt dem niedrig priorisierten Thread 19677 seine Vorrangstellung, weil dieser ein gemeinsam genutztes Lock hält. Nun geht es für beide schneller voran.
Die aktuelle Priorität des Thread speichert Linux in dem Element »prio« des Prozess-Kontrollblocks »struct task_struct«. Da für den Kernel - entgegengesetzt der Definition am Programmier-Interface - jedoch 0 eine hohe und 99 eine niedrige Echtzeitpriorität bedeutet, rechnen die Zeilen 35 und 43 die Werte wieder in Posix-Darstellung zurück.
Die Kernelentwickler haben Prioritätsvererbung durchaus kontrovers diskutiert: So schrieb Linus Torvalds noch im Dezember 2005: "Friends don\'t let friends use priority inheritance." Dass er die Prioritätsvererbung letztlich doch in den Kernel eingebaut hat, zeigt, dass er durchaus in der Lage ist, seine Meinung zu revidieren. (mg)
| Infos |
|---|
| [1] Eva-Katharina Kunst, Jürgen Quade, "Linux-Treiber entwickeln": Dpunkt-Verlag, 2. Auflage, Juni 2006 [2] Willi Nüßer, "Kampf um die Ressourcen": Linux-Magazin 10/05, S. 84; [http://www.linux-magazin.de/heft_abo/ausgaben/2005/10/kampf_um_die_ressourcen] [3] Ulrich Drepper, "Tricky Futexes": [http://people.redhat.com/drepper/futex.pdf] [4] E.-K. Kunst, J. Quade: "Realtime-Preemption", Linux-Magazin 07/07, S. 102 [5] Ingo Molnar, "Robust Futexes", Kerneldokumentation: [http://lxr.linux.no/linux/Documentation/robust-futexes.txt] |
| Die Autoren |
|---|
| Eva-Katharina Kunst, Journalistin, und Jürgen Quade, Professor an der Hochschule Niederrhein, sind seit den Anfängen von Linux Fans von Open Source. Unter dem Titel "Linux Treiber entwickeln" haben sie zusammen ein Buch zum Kernel 2.6 veröffentlicht. |
Diesen Artikel als PDF kaufen
Express-Kauf als PDF
Umfang: 4 Heftseiten
Preis € 0,99
(inkl. 19% MwSt.)
Als digitales Abo
Weitere Produkte im Medialinx Shop »
Versandartikel
Onlineartikel
Alle Rezensionen aus dem Linux-Magazin
- Buecher/07 Bücher über 3-D-Programmierung sowie die Sprache Dart
- Buecher/06 Bücher über Map-Reduce und über die Sprache Erlang
- Buecher/05 Bücher über Scala und über Suchmaschinen-Optimierung
- Buecher/04 Bücher über Metasploit sowie über Erlang/OTP
- Buecher/03 Bücher über die LPI-Level-2-Zertifizierung
- Buecher/02 Bücher über Node.js und über nebenläufige Programmierung
- Buecher/01 Bücher über Linux-HA sowie über PHP-Webprogrammierung
- Buecher/12 Bücher über HTML-5-Apps sowie Computer Vision mit Python
- Buecher/11 Bücher über Statistik sowie über C++-Metaprogrammierung
- Buecher/10 Bücher zu PHP-Webbots sowie zur Emacs-Programmierung
Insecurity Bulletin
Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...





