Was ist der Unterschied zwischen Kerneltreibern und Kernelmodulen?

67

Wenn ich einen lspci -kauf meinem Kubuntu mit einem 3.2.0-29-generischen Kernel mache, sehe ich so etwas:

01:00.0 VGA compatible controller: NVIDIA Corporation G86 [Quadro NVS 290] (rev a1)
    Subsystem: NVIDIA Corporation Device 0492
    Kernel driver in use: nvidia
    Kernel modules: nvidia_current, nouveau, nvidiafb

Es gibt einen Kernel - Treiber nvidiaund Kernel - Module nvidia_current, nouveau, nvidiafb.

Nun habe ich mich gefragt, was der Unterschied zwischen Kerneltreibern und Kernelmodulen sein könnte.

JohnnyFromBF
quelle

Antworten:

78

Ein Kernelmodul ist ein kompilierter Code, der zur Laufzeit in den Kernel eingefügt werden kann, z. B. mit insmododer modprobe.

Ein Treiber ist ein Stück Code, der im Kernel ausgeführt wird, um mit einem Hardwaregerät zu kommunizieren. Es "treibt" die Hardware an. Fast jeder Hardware-Komponente Ihres Computers ist ein Treiber zugeordnet.¹ Ein großer Teil eines laufenden Kernels ist der Treibercode.²

Ein Treiber kann statisch in die Kerneldatei auf der Festplatte eingebaut werden.³ Ein Treiber kann auch als Kernelmodul eingebaut werden, damit er später dynamisch geladen werden kann. (Und dann vielleicht entladen.)

Üblicherweise werden Treiber nach Möglichkeit als Kernelmodule erstellt, anstatt sie statisch mit dem Kernel zu verknüpfen, da dies mehr Flexibilität bietet. Es gibt jedoch gute Gründe, dies nicht zu tun:

  • Manchmal ist ein bestimmter Treiber unbedingt erforderlich, um das System hochzufahren. Das passiert aufgrund der initrd- Funktion nicht so oft, wie Sie sich vorstellen können .

  • Statisch erstellte Treiber können genau das sein, was Sie in einem System mit statischem Gültigkeitsbereich möchten, z. B. einem eingebetteten System . Das heißt, wenn Sie im Voraus genau wissen, welche Treiber immer benötigt werden und dass sich dies nie ändern wird, haben Sie einen guten Grund, sich nicht mit dynamischen Kernelmodulen zu beschäftigen.

  • Wenn Sie Ihren Kernel statisch erstellen und die Funktion zum Laden dynamischer Linux-Module deaktivieren, verhindern Sie, dass der Kernelcode zur Laufzeit geändert wird. Dies bietet zusätzliche Sicherheit und Stabilität auf Kosten der Flexibilität.

Nicht alle Kernelmodule sind Treiber. Eine relativ neue Funktion im Linux-Kernel ist beispielsweise, dass Sie einen anderen Prozess-Scheduler laden können . Ein weiteres Beispiel ist, dass die komplexeren Hardwaretypen häufig mehrere generische Schichten aufweisen, die sich zwischen dem Hardwaretreiber auf niedriger Ebene und dem Benutzerland befinden, z. B. der USB-HID-Treiber , der ein bestimmtes Element des USB-Stacks unabhängig von der zugrunde liegenden Hardware implementiert.


Nebenbei:

  1. Eine Ausnahme von dieser breiten Aussage ist der CPU - Chip, der keine „Fahrer“ hat per se . Ihr Computer enthält möglicherweise auch Hardware, für die Sie keinen Treiber haben.

  2. Der Rest des Codes in einem Betriebssystemkernel stellt allgemeine Dienste wie Speicherverwaltung , IPC , Zeitplanung usw. bereit. Diese Dienste können in erster Linie Benutzeranwendungen bedienen , wie in den zuvor verknüpften Beispielen, oder sie können interne Dienste sein, die von Treibern oder anderen internen Diensten verwendet werden. Kernel-Infrastruktur.

  3. Der in /boot, in den Arbeitsspeicher geladen beim Booten von der Bootloader zu Beginn des Startvorgangs .

Warren Young
quelle
1
Module können Dateisysteme, Netzwerkprotokolle, Firewall-Funktionen und vieles mehr sein. Einige Hardware (z. B. WiFi-Karten) erfordern einen Stapel von Modulen, einige bieten eine allgemeine Infrastruktur, während andere die Hardware selbst verwalten.
Vonbrand
1
Dies ist ein guter allgemeiner Überblick, aber ich hatte genau die gleiche Frage wie das OP, stieß dann auf diese Antwort und wusste immer noch nicht, warum sich der "verwendete Treiber" von den "Modulen" unterscheidet. Die Antwort von @Jim Paris ist dagegen richtig. From man lspci: "-k Zeigt die Kernel- Treiber an, die jedes Gerät und auch die dazu fähigen Kernel- Module handhaben ." Sie können dies so lesen: "Zeigen Sie den Treiber an, der gerade das Gerät bedient, und auch alle Module, die damit umgehen können / sollen ."
Binarus
Wenn Sie Windows kennen: Ein Modul ist einer DLL sehr ähnlich. Unter Unix ähnelt ein Modul einem gemeinsam genutzten Objekt, ein Modul ist jedoch nur für den Kernel bestimmt. Ein dynamisch verknüpftes Modul kann Treiber enthalten. Ein Kernel kann statisch verknüpfte Treiber enthalten. Ein Modul unterscheidet sich von einer DLL (oder .so), da der Kernel bestimmte Anforderungen dafür hat, wie Dinge dynamisch geladen werden.
Robocat
18

Um Ihre spezifische Frage zur lspciAusgabe zu beantworten , gibt die Zeile "Kerneltreiber" an, welcher Treiber aktuell an die Karte gebunden ist, in diesem Fall der proprietäre nvidiaTreiber. In der Zeile "Kernelmodule" sind alle Treiber aufgeführt, von denen bekannt ist, dass sie an diese Karte gebunden werden können. Hier zeigt der proprietäre Treiber einen anderen Namen an, wahrscheinlich weil lspcider Treiber und sein Dateiname im Vergleich zum im Treiber selbst codierten Namen gefunden wurden.

Jim Paris
quelle
Danke - das hat geholfen. Wenn ich nur ausgestellt hätte man lspci- es sagt genau, was Sie geschrieben haben.
Binarus
5

Nach diesem netten Tutorial :

... Ein Modultyp ist der Gerätetreiber, mit dem der Kernel auf die mit dem System verbundene Hardware zugreifen kann.

Wenn wir also versuchen, einen Baum zu zeichnen, werden wir einen "Gerätetreiber" haben, der vom (erweiterten) Modul erbt und der spezifischere Eigenschaften hat, zwischen denen wir "Zugriff auf Hardware" finden ...

user1847726
quelle
Dies ist nur teilweise richtig. Der Treiber ist ein Objekt einer Klasse in der Hierarchie (ja, das interne Design von Linux ist wie die meisten aktuellen Betriebssysteme objektorientiert). Der Treiber kann jedoch ein Modul sein (das zur Laufzeit geladen werden kann) oder in den Kernel kompiliert werden. In Bezug auf den Code gibt es keinen (oder nur einen sehr geringen) Unterschied zwischen den Alternativen.
Vonbrand
4

Ein Kernelmodul ist möglicherweise überhaupt kein Gerätetreiber.

"Kerneltreiber" ist kein genau definierter Begriff, aber lassen Sie es uns versuchen.

Dies ist ein Kernelmodul, das keine Hardware antreibt und daher nicht als "Gerätetreiber" angesehen werden kann:

#include <linux/module.h>
#include <linux/kernel.h>

MODULE_LICENSE("GPL");

static int myinit(void)
{
    printk(KERN_INFO "hello init\n");
    return 0;
}

static void myexit(void)
{
    printk(KERN_INFO "hello exit\n");
}

module_init(myinit)
module_exit(myexit)

Nach dem Build können Sie es verwenden mit:

insmod hello.ko

und es druckt hello initzu dmesg.

Es gibt jedoch Kernelmodule, die keine Gerätetreiber sind, aber tatsächlich nützlich sind, z. B. Module, die Kernel-Debugging- / Leistungsinformationen bereitstellen.

Gerätetreiber sind in der Regel auch Kernelmodule.

Ein Beispiel für etwas, das ein "Gerätetreiber" ist, ist etwas schwieriger zu generieren, da es eine Hardware zum Fahren erfordert und Hardwarebeschreibungen in der Regel kompliziert sind.

Mit QEMU oder anderen Emulatoren können wir jedoch Softwaremodelle aus realer oder vereinfachter Hardware erstellen. Dies ist eine hervorragende Möglichkeit, um zu lernen, wie man mit Hardware spricht. Hier ist ein einfaches Beispiel eines minimalen PCI-Gerätetreibers: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/hello.c

Wir sehen dann, dass es in x86 bei der Kommunikation mit der Hardware darauf ankommt,

Diese Operationen können im Allgemeinen nicht vom Userland aus durchgeführt werden, wie unter: Was ist der Unterschied zwischen User Space und Kernel Space? Es gibt jedoch einige Ausnahmen: https://stackoverflow.com/questions/7986260/linux-interrupt-handling-in-user-space .

Der Kernel bietet dann APIs auf höherer Ebene, um solche Hardware-Interaktionen einfacher und portabler zu machen:

  • request_irq Interrupts zu behandeln
  • ioreadX und IO-Speicherzuordnung
  • noch übergeordnete Schnittstellen für gängige Protokolle wie PCI und USB
Ciro Santilli ist ein Schauspieler
quelle
0

Meine Antwort wird mit Jim gehen. Ein Kernel-Treiber ist ein Programm (Kernel-Modul), mit dem ein Teil der Hardware angesteuert wird. Die lspci-Ausgabe besagt, dass nvidia der Kerneltreiber ist, da es das loadedModul für das Gerät ist. Zusammen mit ihm kommen andere verfügbare Kernelmodule zur Verfügung.

Ich werde hinzufügen, dass die Befehle in Linux zum Auflisten und Entfernen von Treibern lsmodund rmmodsind. Was sagt Listenmodul und Modul entfernen.

Malkasten
quelle
0

Alle Treiber sind Module. Nicht alle Module sind Treiber.

Module können zur Laufzeit eingefügt werden. Module / Treiber können zusammen mit dem Kernel auch statisch kompiliert werden.

Typisches Modul init hat

module_init(init_fn);
init_fn()
{
   /* some code */
}

Das gleiche Modul kann zum Treiber gemacht werden

module_init(init_fn);
init_fn()
{
   device_register(&device);
   /* some code */
}
Prabagaran
quelle
8
Treiber sind nicht immer Module, sondern können in das Haupt-Kernel-Image aufgenommen werden.
Gilles
3
@Prabagaran: "Alle Treiber sind Module. Alle Module sind keine Treiber." Das ist widersprüchlich. In mathematischen Begriffen ist das, was Sie sagen, D -> M und M ->! D. Dies ermöglicht D und! D.
Francesco Turco
2
Ich denke, er meint "Alle Treiber sind Module. Nicht alle Module sind Treiber".
Renan
4
@Renan: Das wäre korrekt, aber wenn Sie sich den Bearbeitungsverlauf für diese Antwort ansehen, hat bereits jemand versucht, den Fehler zu beheben, und der Autor hat ihn zurückgesetzt. Normalerweise bearbeite ich nur, um den Fehler zu beheben und fortzufahren, aber in diesem Fall habe ich -1'ed, weil es einfach falsch und das Problem verwirrend ist.
Caleb
Wie ich mich erinnere (ich habe eine Weile nicht rumgespielt), gibt es einige Treiber, die nicht als ladbare Module gebaut werden können. Ich scheine mich an andere zu erinnern, die nur als Module gehandhabt werden können.
Vonbrand