"loff_t" ist ein "Long Offset", also eine Suchposition, die die verrückte Vielfalt von off_t
vereint , off64_t
, und so weiter, sodass Fahrer einfach loff_t verwenden können und sich keine Gedanken darüber machen müssen.
Der Zeiger selbst zeigt zu dem Zeitpunkt, an dem Sie in den Treiber gelangen, auf den vom Benutzer bereitgestellten Offset (vorausgesetzt, der Benutzercode übernimmt den Treiberzugriff - technisch gesehen kann der Kernel seinen eigenen bereitstellen, aber der Benutzerfall ist derjenige, über den Sie nachdenken sollten). über lseek
oder llseek
oder lseek64
usw. und dann durch gewöhnliche Lese- und Schreiboperationen. Betrachten Sie den Fall einer regulären Datei auf der Festplatte:Wenn Sie zum ersten Mal open
der Datei erhalten Sie (als Benutzer) den Kernel, um eine Datenstruktur bereitzustellen, die Ihre aktuelle Position in der Datei verfolgt, so dass, wenn Sie read
oder write
einige Bytes, die nächsten read
oder write
macht dort weiter, wo Sie aufgehört haben.
Außerdem, wenn Sie dup
den Dateideskriptor, oder machen Sie das Äquivalent durch (z. B.) fork
und exec
In Bezug auf das Ausführen einer Befehlsfolge wird diese Suchposition von allen erbenden Prozessen geteilt. Daher am Shell-Prompt der Befehl:
(prog1; prog2; prog3) > outputfile
erstellt eine Ausgabedatei, dann dup
s der Deskriptor für die drei Programme, so dass prog2
ausgegeben wird schreibt direkt nach der Ausgabe von prog1
in die Datei , und Ausgabe von prog3
folgt den anderen beiden – alles nur, weil alle drei separaten Prozesse dieselbe zugrunde liegende Kernel-Datenstruktur mit demselben internen loff_t
teilen .
Dasselbe gilt für Gerätetreiberdateien. Wenn Ihre Lese- und Schreibfunktionen aufgerufen werden, erhalten Sie den "aktuellen Offset", wie vom Benutzer bereitgestellt, und Sie können (und sollten) ihn nach Bedarf aktualisieren ... vorausgesetzt, es besteht Bedarf (z das Erscheinungsbild einer regulären Datei, einschließlich der Tatsache, dass sich Suchoffsets beim Lesen und Schreiben verschieben). Wenn das Gerät eine logische Anwendung des Seek-Offsets hat, können Sie das hier verwenden.
Natürlich gibt es noch viel mehr zu Gerätetreibern, weshalb es ganze Buchkapitel zu diesem Thema gibt (siehe auch). :-)
Toreks Antwort ist ausgezeichnet. Ich füge nur ein bisschen mehr Details/Kontext hinzu... Aus einem früheren Linux-Kernel (2.6.28) ist hier ein Beispiel für Offset, das in einem Systemaufruf verwendet wird... es kopiert den Offset vor dem Abrufen aus dem Benutzerbereich in eine temporäre Variable in den Kernel-Treiberaufrufmechanismus und kopiert sie dann zurück in die Benutzerdatei. Auf diese Weise wird der Offset, den der Treiber sieht, von der Benutzeransicht entkoppelt und erleichtert die Situationen, in denen der Offset im Systemaufruf NULL ist, sodass kein SEGVIO auftritt.
SYSCALL_DEFINE4(sendfile64, int, out_fd, int, in_fd, loff_t __user *, offset, size_t, count)
{
loff_t pos;
ssize_t ret;
if (offset) {
if (unlikely(copy_from_user(&pos, offset, sizeof(loff_t))))
return -EFAULT;
ret = do_sendfile(out_fd, in_fd, &pos, count, 0);
if (unlikely(put_user(pos, offset)))
return -EFAULT;
return ret;
}
return do_sendfile(out_fd, in_fd, NULL, count, 0);
}