Der Big Kernel Lock, kurz BKL, war ein Verfahren, das 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 Prozessoren bzw. Prozessorkernen) laufen, und schützte damit den Kernel (bzw. die Hardware) vor konkurrierenden Zugriffen auf Ressourcen wie System-Dateien auf der Festplatte.

Geschichte

Bearbeiten

BKL wurde mit Kernel 2.0 (1996) eingeführt, um die Nutzung von Multiprozessorsystemen zu ermöglichen. Nachdem Leistungseinbußen (s. Problematik) festgestellt worden waren, wurde mit 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 Einzel-Locks (sogenannten fine-grained locks, übersetzt „feinkörnige Locks“) führte, mit denen nur kleine Bereiche gesperrt werden konnten.

Neuer Code durfte den BKL auf keinen Fall nutzen (er wäre dann nicht in den offiziellen Kernel aufgenommen werden), jedoch existierten noch lange Zeit eine Reihe von Aufrufen. Im Kernel 2.6.37 wurde der BKL weitgehend abgeschafft,[1] wobei bestimmte Dateisystemtreiber wie der UDF-Treiber den BKL noch benötigten, was aber durch Patches in Linux 2.6.38 gelöst wurde. Im Kernel-Kompilierungsvorgang gab es dann eine neue Option, mit der ein Kompilat ganz ohne BKL-Unterstützung erstellt werden konnte.[2][3] Mit Version 2.6.39 wurde die Unterstützung für BKL vollständig aus dem Kernel entfernt,[4] und der nachfolgende Kernel "3.0" getauft.[5] Mit diesem Aufräumen verschwand der BKL 2011 endgültig.

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.

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 Sperren („lock“) 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.[6]

Syntax-Beispiel:

lock_kernel();

/*
 * Kritische Region;
 * Hier koennen kritische Aktionen durchgefuehrt werden.
 */

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.[7]

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.

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

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@1@2Vorlage:Toter Link/git.kernel.org (Seite nicht mehr abrufbar, festgestellt im April 2018. Suche in Webarchiven)  Info: Der Link wurde automatisch als defekt markiert. Bitte prüfe den Link gemäß Anleitung und entferne dann diesen Hinweis.
  5. Ankündigungsmail von Version 3.0-rc1 (Memento des Originals vom 30. November 2016 im Internet Archive)  Info: Der Archivlink wurde automatisch eingesetzt und noch nicht geprüft. Bitte prüfe Original- und Archivlink gemäß Anleitung und entferne dann diesen Hinweis.@1@2Vorlage:Webachiv/IABot/thread.gmane.org
  6. Robert Love: Linux Kernel Development: A thorough guide to the design and implementation of the Linux kernel. Third Edition. Addison-Wesley (Developer’s Library), 2010, ISBN 978-0-672-32946-3, S. 198–199.
  7. Post über den BKL