Kernel und Module

Aus Xinux Wiki
Zur Navigation springen Zur Suche springen

Kernel

Grundlegendes

  • Der Kernel eines Betriebssystems bildet die hardwareabstrahierende Schicht.
  • Er stellt der aufsetzenden Software eine einheitliche Schnittstelle (API) zur Verfügung.
  • Diese agiert unabhängig von der Rechnerarchitektur.
  • Die Software kann so immer auf die Schnittstelle zugreifen und braucht die Hardware nicht genauer zu kennen.
  • Der Kernel ist so etwas wie ein Vermittler zwischen Anwendungsprogrammen und Hardware.
  • Die Aufgaben sind Speicherverwaltung, Prozessverwaltung, Multitasking, Lastverteilung, Durchsetzung der Berechtigungen und Eingabe/Ausgabe-Operationen auf verschiedenen Geräten.
  • Der Kernel wird beim Systemstart in den Speicher geladen und verbleibt dort während der ganzen Zeit.
  • Der Kern selbst hat keine Anwendungsprogramme, Bibliotheken oder Systemsoftware.

Monolithischer Kernel und Mikrokernel

  • Mikrokernel (z.B. QNX, Minix, seL4): Nur das Nötigste läuft im Kernel. Treiber laufen als eigene Prozesse im User Space.
  • Monolithischer Kernel: Treiber, Dateisysteme und Netzwerk laufen komplett im Kernel Space.
  • Linux ist ein modularer monolithischer Kernel.
  • Er ist monolithisch, kann aber Teile (Module) zur Laufzeit nachladen und entladen.
  • Wichtig: Ein geladenes Modul läuft im Kernel Space mit vollen Rechten. Ein fehlerhaftes Modul kann das ganze System mitreißen.

Schaubild

  • Die Anwendungsprogramme greifen nicht direkt auf die Hardware zu.
  • Sie rufen Kernel System Calls auf und diese machen dann die wirklichen Aktionen.
  • Meist geschieht das über die C-Bibliothek (glibc).
  • Der Kernel kann Aufrufe auch verweigern (z.B. fehlende Berechtigung).
kernel-space

Gerätetreiber unter Linux

  • Ein Gerätetreiber ist ein spezielles Stück Software, das ein Betriebssystem (wie Linux) mit einer Hardwarekomponente verbindet.
  • Jede Hardwarekomponente benötigt einen spezifischen Treiber, um korrekt zu funktionieren.
  • Unter Linux sind die meisten dieser Treiber als Kernel-Module verfügbar, die dynamisch geladen und entladen werden können.

Module

Kernel-Module

Ein Kernel-Modul ist ein Stück Code, das dynamisch in den Kernel eingefügt werden kann, um zusätzliche Funktionen bereitzustellen.
  • Viele Gerätetreiber sind als Kernel-Module implementiert, z.B. WLAN-Karte, Soundkarte, Netzwerkkarte.
  • Auch Dateisysteme (z.B. xfs, btrfs) und Netzwerkfunktionen (z.B. nftables) sind oft Module.
  • Distributionen wie Debian, Ubuntu oder Rocky nutzen einen "allgemeinen" Kernel und laden passend zur Hardware die nötigen Module.
  • In der Regel werden alle notwendigen Module beim Systemstart und bei Bedarf zur Laufzeit automatisch geladen.

Fest im Kernel verankert

  • Treiber ist Teil des Original-Kernel-Quellcodes.
  • Das Modul (Treiber) wurde beim Kompilieren fest in den Kernel eingebaut.
  • Es lässt sich somit nicht mehr entladen.
  • Anwendung: gehärteter Kernel
  • Wenn ich die Netzwerkkarten von meiner Produktionslinie kenne, brauche ich nur diese in den Kernel zu kompilieren.
kernel-und-module-1

Modul gehört zum Kernel und kann nachgeladen werden

  • Treiber ist Teil des Original-Kernel-Quellcodes.
  • Das Modul wurde beim Kompilieren mit übersetzt, aber als eigene Datei (.ko).
  • Es ist somit nachladbar.
  • Es kann direkt an den Kernel andocken und geht somit eine Symbiose mit dem Kernel ein.
  • Gewöhnliche und verbreitete Treiber sind normalerweise nachladbar.
kernel-und-module

Fest oder Modul? Selbst nachschauen

  • Die Konfiguration des laufenden Kernels liegt unter /boot/config-$(uname -r).
  • =y bedeutet fest eingebaut, =m bedeutet Modul.
  • grep -E "CONFIG_(UNIX|INET|EXT4_FS|XFS_FS)=" /boot/config-$(uname -r)
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_EXT4_FS=m
CONFIG_XFS_FS=m
  • Beispiel Debian 13: Unix-Sockets und IPv4 sind fest drin, selbst ext4 ist ein Modul (es steckt in der initramfs).
  • Alle fest eingebauten Treiber stehen in modules.builtin:
  • grep tcp_cubic /lib/modules/$(uname -r)/modules.builtin

Hersteller stellt Quellcode von einem Treiber zur Verfügung

  • Treiber ist nicht Teil des Original-Kernel-Quellcodes (out-of-tree).
  • Man muss das Modul nun für den passenden Kernel übersetzen.
  • Dazu braucht man nicht den kompletten Kernelquellcode, sondern nur die Kernel-Header.
    • Debian: linux-headers-$(uname -r)
    • Rocky: kernel-devel-$(uname -r)
  • Es gibt 2 Möglichkeiten.

Treiber vom Hersteller selbst kompilieren (schlechter)

  • Quellen des Treibers besorgen.
  • Kernel-Header des laufenden Kernels installieren.
  • Diverse Tools wie make und gcc installieren.
  • Modul gegen den aktuellen Kernel kompilieren.
  • Nachteil: Bei einem Kernelupdate geht das Spiel erneut los.
  • Das Modul liegt nur unter /lib/modules/<alte Version> und fehlt dem neuen Kernel.

DKMS (besser)

  • DKMS = Dynamic Kernel Module Support
  • Quellen sind meist über das Paketmanagement erhältlich (Pakete enden oft auf -dkms).
  • DKMS übersetzt das Modul gegen den laufenden Kernel.
  • Am Schluss ist das Modul verfügbar.
  • Vorteil: Bei einem Kernelupdate kompiliert DKMS das Modul automatisch neu.
  • apt install virtualbox-dkms
  • dkms status

Secure Boot

  • Ist Secure Boot aktiv, lädt der Kernel nur signierte Module.
  • Selbst gebaute und DKMS-Module sind zunächst nicht von der Distribution signiert.
  • DKMS erzeugt deshalb einen eigenen Schlüssel (MOK = Machine Owner Key).
  • Dieser muss einmalig importiert und beim nächsten Neustart im MOK-Manager bestätigt werden.
  • mokutil --sb-state
  • mokutil --import /var/lib/dkms/mok.pub
  • Typischer Fehler ohne Signatur: Key was rejected by service

Effekt

  • Der Effekt ist bei beiden Verfahren derselbe.
  • Wichtig: Der Kernel wird nicht neu kompiliert.
  • Die Header werden nur für die richtigen Andockpunkte im Quellcode benötigt.
kernel-und-module-2

Modulverwaltung

Installation

  • Die Programme sind in der Standardinstallation enthalten.
  • Sie stammen aus dem Paket kmod (früher module-init-tools).

Tools

  • lsmod: Zeigt geladene Module an
  • modinfo: Zeigt Informationen über ein Modul an
  • modprobe: Lädt und entlädt Module und löst dabei Abhängigkeiten auf
  • insmod: Lädt eine einzelne Moduldatei über ihren Pfad, ohne Abhängigkeiten aufzulösen
  • rmmod: Entlädt ein einzelnes Modul, ohne Abhängigkeiten
  • depmod: Erstellt die Dateien zur Auflösung von Modulabhängigkeiten
  • Im Alltag nimmt man modprobe statt insmod und rmmod.

Ort, wo die Module des laufenden Kernels liegen

Die Module des aktuellen Kernels befinden sich im Verzeichnis /lib/modules/$(uname -r).
  • Je nach Distribution sind sie komprimiert (.ko.xz oder .ko.zst).
  • Die Anführungszeichen sind wichtig, sonst wertet die Shell den Stern selbst aus.
  • find /lib/modules/$(uname -r) -name "*.ko*"

Geladene Module anzeigen

Mit dem Befehl lsmod kann man die aktuell geladenen Module anzeigen lassen.
  • lsmod
  • Die Spalte "Used by" zeigt, welche anderen Module ein Modul gerade benutzen.

Informationen anzeigen

Mit dem Befehl modinfo kann man Informationen zu einem bestimmten Modul anzeigen lassen.
  • modinfo usb_common
  • Interessant sind filename, depends, parm (Optionen) und signer.

Module laden und entladen

Mit dem Befehl modprobe können Module zur Laufzeit geladen oder entladen werden.
  • modprobe [Optionen] Modulname
Optionen sind unter anderem
  • -v: Ausführliche Ausgabe
  • -n: Simuliert das Laden des Moduls, lädt es aber nicht (sinnvoll zusammen mit -v)
  • -a: Lädt alle in der Kommandozeile angegebenen Module
  • -r: Entlädt das Modul und nicht mehr benötigte Abhängigkeiten
Beispiele
  • sudo modprobe -v usb_common
  • sudo modprobe -n -v xfs
  • sudo modprobe -r xfs
  • Ein Modul, das gerade benutzt wird, lässt sich nicht entladen.
modprobe: FATAL: Module xfs is in use.

Abhängigkeiten von Modulen

Manche Module können erst geladen werden, wenn andere Module geladen sind, da sie von diesen abhängen.
  • Diese Abhängigkeiten sind in der Datei /lib/modules/$(uname -r)/modules.dep hinterlegt.
  • depmod erstellt diese Datei neu, z.B. nachdem ein Modul von Hand nach /lib/modules kopiert wurde.
  • sudo depmod -a

Modul-Optionen

  • Viele Module haben Parameter, die man mit modinfo sieht.
  • Beim Laden: sudo modprobe Modulname parameter=wert
  • Dauerhaft in einer Datei unter /etc/modprobe.d/, die auf .conf endet:
options snd_hda_intel power_save=1
  • Die aktuellen Werte stehen unter /sys/module/<modulname>/parameters/.

Automatisches Laden von Modulen

  • Meist muss man nichts tun.
  • Erkennt der Kernel neue Hardware, lädt udev anhand der Geräte-ID (modalias) automatisch den passenden Treiber.
  • Module, die trotzdem beim Booten immer geladen werden sollen, trägt man in eine Datei unter /etc/modules-load.d/ ein.
  • Die Datei muss auf .conf enden, ein Modul pro Zeile.
# /etc/modules-load.d/lp.conf
lp
  • Debian liest zusätzlich noch die alte Datei /etc/modules.

Automatisches Laden verhindern - Blacklisting

  • Unter bestimmten Umständen kann es sinnvoll sein, das Laden von bestimmten Modulen zu verbieten.
  • Beispiel: Zwei Treiber kommen für dasselbe Gerät in Frage oder ein Treiber macht Probleme.
  • Dazu legt man eine Datei im Verzeichnis /etc/modprobe.d an.
  • Der Name ist frei wählbar, die Datei muss aber auf .conf enden.
  • In der Regel sind hier schon einige Dateien zu finden.

Blacklist-Datei

  • cat /etc/modprobe.d/blacklist.conf
# This file lists those modules which we don't want to be loaded by
# alias expansion, usually so some other driver will be loaded for the
# device instead.

# evbug is a debug tool that should be loaded explicitly
blacklist evbug

# these drivers are very simple, the HID drivers are usually preferred
blacklist usbmouse
blacklist usbkbd
...

Eigene Blacklist anlegen

  • echo "blacklist pcspkr" | sudo tee /etc/modprobe.d/blacklist-pcspkr.conf

Wichtig

  • blacklist verhindert nur das automatische Laden.
  • Von Hand mit modprobe oder als Abhängigkeit eines anderen Moduls wird es trotzdem geladen.
  • Soll ein Modul gar nicht geladen werden können, zusätzlich:
install pcspkr /bin/false
  • Wird das Modul schon in der initramfs geladen, muss diese neu gebaut werden.
    • Debian: sudo update-initramfs -u
    • Rocky: sudo dracut -f

Treiberprobleme beheben

Gerätetreiber installieren

  • Die genaue Methode zur Installation eines Gerätetreibers variiert je nach Treiber und Linux-Distribution.
  • Oftmals werden Treiber über den Paketmanager der Distribution installiert (z.B. firmware-* Pakete oder *-dkms Pakete).
  • Manchmal müssen Treiber jedoch von der Herstellerseite heruntergeladen und manuell installiert werden.

Welcher Treiber gehört zu welchem Gerät

Mit lspci -k sieht man zu jedem PCI-Gerät den benutzten Treiber.
  • lspci -k
00:03.0 Ethernet controller: Intel Corporation 82540EM Gigabit Ethernet Controller (rev 02)
	Subsystem: Intel Corporation PRO/1000 MT Desktop Adapter
	Kernel driver in use: e1000
	Kernel modules: e1000
  • Fehlt die Zeile Kernel driver in use, ist für das Gerät kein Treiber geladen.
  • Für USB-Geräte: lsusb und lsusb -t

Kernel-Nachrichten anzeigen

Mit dmesg sieht man die Meldungen des Kernels, z.B. beim Laden von Treibern oder fehlender Firmware.
  • Unter Debian braucht man dafür root-Rechte.
  • sudo dmesg
  • sudo dmesg -w (live mitlesen)
  • journalctl -k
  • sudo dmesg | grep -i firmware