Die wichtigsten Funktionen und Makros, die beim Schreiben von Block-Treibern benutzt werden, sind hier zusammengefaßt. Um Platz zu sparen, führen wir allerdings die Felder von struct request, struct buffer_head und struct genhd nicht auf und lassen auch die vordefinierten ioctl-Befehle weg.
Diese Funktionen übernehmen die Registrierung des Geräts in der Initialisierungsfunktion und die Deregistrierung in der Aufräumfunktion.
Die erste Funktion initialisiert eine Warteschlange und etabliert die request-Funktion, die zweite wird zum Aufräumen verwendet.
Dieses Makro gibt die Default-I/O-Anfrage-Warteschlange für eine gegebene Major-Nummer zurück.
Dieses Array wird vom Kernel dazu benutzt, die passende Warteschlange für eine bestimmte Anfrage zu finden.
read_ahead enthält Vorauslesewerte auf Block-Ebene für jede Major-Nummer. Ein Wert von 8 ist für Geräte wie Festplatten sinnvoll; bei langsameren Medien sollte ein größerer Wert gewählt werden. max_readahead enthält Vorauslesewerte für alle Major- und Minornummern auf Dateisystem-Ebene und wird normalerweise gegenüber dem System-Default nicht verändert.
Dieses Array, das per Major- und Minor-Nummer indiziert wird, enthält die maximale Anzahl von Sektoren, die in einer einzigen I/O-Anfrage zusammengefaßt werden sollten.
Diese zweidimensionalen Arrays werden mit der Major- und Minor-Nummer indiziert. Der Treiber ist dafür zuständig, die zur jeweiligen Major-Nummer gehörende Reihe im Array zu allozieren bzw. zu deallozieren. In den Arrays steht die Größe der Blocks auf dem Gerät (normalerweise 1 KByte), die Größe jedes Minor-Gerätes in KByte (nicht in Blocks) und die Hardware-Sektorengröße in Bytes.
Diese Makros müssen vom Treiber definiert werden, bevor die Header-Datei <linux/blk.h> eingebunden wird, weil sie in dieser Datei verwendet werden. MAJOR_NR ist die Major-Nummer des Geräts, DEVICE_NAME der Name des Geräts, wie er in Fehlermeldungen verwendet wird, DEVICE_NR gibt die Minor-Nummer des physikalischen Geräts zurück, auf das die Geräte-Nummer verweist, und DEVICE_INTR ist ein selten verwendetes Symbol, das auf die untere Hälfte des Interrupt-Handlers des Geräts verweist.
Das Spinlock muß gehalten werden, wann immer eine I/O-Anfrage-Warteschlange manipuliert wird.
Dieses Makro zeigt auf die aktuelle Anfrage, wenn die Default-Warteschlange verwendet wird. Die Anfrage-Struktur beschreibt einen Datenblock, der übertragen werden soll, und wird von der request-Funktion im Treiber benutzt.
INIT_REQUEST überprüft die nächste Anfrage in der Warteschlange und springt zurück, wenn keine weiteren Anfragen mehr auszuführen sind. end_request wird bei der Beendigung einer Block-Anfrage aufgerufen.
Die I/O-Anfrage-Sperre muß zu jedem Zeitpunkt gehalten werden, an dem die Anfrage-Warteschlange manipuliert wird.
Diverse Funktionen zur Arbeit mit der I/O-Anfrage-Warteschlange.
Gibt an, ob die erste Anfrage in der Warteschlange aktiv vom Treiber bearbeitet wird oder nicht.
Stellt eine Funktion bereit, die Block-I/O-Anfragen direkt aus dem Kernel heraus bearbeitet.
Erledigen die erforderlichen Schritte, um eine Block-I/O-Anfrage abzuschließen. end_that_request_last wird nur dann aufgerufen, wenn alle Puffer in der Anfrage verarbeitet worden sind, also wenn end_that_request_first 0 zurückgegeben hat.
Meldet die Beendigung der I/O auf dem angegebenen Puffer.
Eine Hilfsfunktion, die die meisten der Standard-ioctl-Befehle von Block-Geräten implementiert.
Diese Funktion überprüft, ob ein Medienwechsel auf dem angegebenen Gerät erfolgt ist, und ruft, sollte das der Fall sein, die Methode revalidate des Treibers auf.
Mit der generischen Festplatte kann Linux leicht partitionierbare Geräte unterstützen. Die gendisk-Struktur beschreibt eine generische Festplatte; gendisk_head ist der Anfang einer verketteten Liste von Strukturen, die alle Festplatten im System beschreibt.
> Diese Funktion liest die Partitionstabelle der Festplatte neu ein und ändert genhd->part, um die neue Partitionierung wiederzugeben.