Big Kernel Lock

aus Wikipedia, der freien Enzyklopädie
Wechseln zu: Navigation, Suche

Der Big Kernel Lock, kurz BKL, war eine Technologie, die mit Linux 2.0 im Jahr 1996 eingeführt wurde, um die Ausführung von Kernelcode durch mehrere Prozessoren bzw. Kerne auf Multiprozessorsystemen zu verwalten. Der BKL verhinderte, dass mehrere Kernel-(Sub)-Prozesse gleichzeitig (evtl. auf mehreren Kernen/Prozessoren) laufen, und schützte damit den Kernel (bzw. die Hardware) vor konkurrierenden Zugriffen auf Ressourcen wie System-Dateien auf der Festplatte. Im Grunde war der BKL also ein Spinlock, bei dem eine Funktion eine Sperrvariable auf „gesperrt“ setzt, solange er z. B. auf die Festplatte zugreift.

Geschichte[Bearbeiten]

BKL wurde mit Kernel 2.0 (1996) eingeführt, um die Nutzung von Multiprozessorsystemen zu ermöglichen. Nachdem Leistungseinbußen (s. Probleme) festgestellt worden waren, wurde in Kernel 2.2 der separate I/O-Lock für das Input/Output-Subsystem eingeführt. Diese Aufsplittung in kleinere Locks für Subsysteme wurde bis 2.6 (letzte Generation) fortgeführt, was zu sehr kleinen Einzellocks (sogenannten fine-grained locks, übersetzt „feinkörnige Locks“) führte, mit denen nur kleine Bereiche gesperrt werden können.

In Kernel 2.6.37 wurde der BKL generell und weitgehend abgeschafft[1], wobei bestimmte Dateisystemtreiber wie der UDF-Treiber den BKL noch brauchten, was aber durch Patches in Linux 2.6.38 gelöst wird. Im Kernel-Kompilierungsvorgang gibt es jetzt eine neue Option, mit der das Kompilieren ganz ohne BKL-Unterstützung möglich ist.[2][3] Mit Version 2.6.39 wurde die Unterstützung für BKL endgültig aus dem Kernel entfernt.[4] Neuer Code darf den BKL auf keinen Fall nutzen (er würde dann nicht in den offiziellen Kernel aufgenommen werden)

Eigenschaften und Nutzung[Bearbeiten]

Es ist für Nutzer (hier im Sinne von Funktionen innerhalb des Kernels) des Locks möglich, eine blockierende Operation auszuführen oder zu schlafen, während der BKL gehalten wird. Allerdings wird der BKL automatisch gelöst, sobald der aktuelle Nutzer des Locks vom Scheduler verdrängt wird und wieder aktiviert, wenn der Nutzer wieder laufen darf.

Der BKL ist ein rekursiver Lock, das heißt, er kann mehrfach gesperrt werden, ohne einen Deadlock auszulösen. Um den Lock vollständig zu lösen, muss der Lock allerdings genauso oft wieder gelöst werden.

Das Nutzen des BKL ist nur im Prozesskontext erlaubt. Im Gegensatz zu anderen Spinlocks ist es nicht erlaubt, den BKL im Interrupt-Kontext zu nutzen.

Außerdem deaktiviert das Locken des BKL die kernel preemption, also das Verdrängen von Kernel-Threads durch einen Scheduler. Auf Einprozessor-Maschinen deaktiviert der BKL nur die Preemption ohne ein tatsächliches Locking durchzuführen. [5]

Syntax-Beispiel:

lock_kernel();
 
/*
 * Kritische Region;
 * Hier koennen die Aktionen durchgefuehrt werden, die gelockt sein muessen
*/
 
unlock_kernel();

Nutzung und Vorkommen[Bearbeiten]

Im Quelltext von Kernel 2.6 existierten trotz der Ausstiegsstrategie immer noch ungefähr 500 BKL-Aufrufe (lock_kernel()).

Das rührt einerseits daher, dass in den Tiefen des Kernels noch solche Aufrufe behalten werden, beispielsweise für die Aufrufe reboot() oder sysctl(). Ebenfalls lief der frühe Bootprozess mit eingeschaltetem BKL. Intensiv wurde BKL auch von älteren Dateisystemtreibern genutzt, dazu gehören u. a. UFS, Coda, HPFS, das oft auf portablen Speichermedien eingesetzte FAT oder das Minix-Dateisystem. Auch gibt es einzelne Prozesse wie den rpciod-Thread oder die Core Dump-Erstellung, die BKL nutzen.

Etwa 10 % aller lock_kernel()-Aufrufe standen in alten und nicht mehr verwendeten Soundtreibern und Bestandteilen des Kernels, wohingegen ALSA (Advanced Linux Sound Architecture) bis auf eine Ausnahme keine BKL-Aufrufe nutzte.[6]

Inzwischen ist es strikt verboten, den BKL in neuem Code zu nutzen.

Problematik[Bearbeiten]

Die Problematik des BKL war vor allem die äußerst mangelhafte Skalierbarkeit – bei Kernel 2.0 und einem System mit schon zwei Prozessoren waren deutliche Leistungseinbußen zu spüren, und das Laufen auf noch mehr Prozessoren ist problematisch. Wenn der BKL für die unterschiedlichsten Daten und Code genutzt wurde, konnten andere Codebereiche, die eventuell völlig andere Aufgaben erledigten, aber den BKL nutzten, nicht auf ihre (zusammen mit ganz anderen Elementen gesperrten) Daten- oder Codebereiche zugreifen. Aus diesem Grund wurde der BKL in Locks für kleinere Bereiche umgewandelt, siehe Geschichte.

Eine weitere Problematik war offensichtlich, dass es absolut unklar war, was eigentlich durch einen bestimmten Lock-Aufruf geschützt wird. Was das Ersetzen durch moderne Spinlocks erschwerte, war außerdem, dass der BKL zu oft Code schützte, statt Daten, es also schwierig war, festzustellen, was tatsächlich gelockt wird.

In neuem Code wird für einzelne Daten (Variablen) oder kleine Gruppen davon jeweils ein einzelner Lock genutzt.

Weblinks[Bearbeiten]

Einzelnachweise[Bearbeiten]

  1. Neuerungen von Linux 2.6.37 - heise.de
  2. Kernel-Log 2.6.37 Architektur/Infrastruktur
  3. Post von Linux Torvalds, dass der BKL-freie UDF-Treiber zu spät für 2.6.37 kommt
  4. BKL: That's all, folks
  5. Robert Love: Linux Kernel Development: A thorough guide to the design and implementation of the Linux kernel, S. 198-199, Addison Wesley (Developer's Library) 2010, Third Edition. ISBN 978-0-672-32946-3
  6. Post über den BKL