"loff_t" est un "long décalage", c'est-à-dire une position de recherche qui unifie la folle diversité de off_t
, off64_t
, et ainsi de suite, afin que les conducteurs puissent simplement utiliser loff_t sans s'en soucier.
Le pointeur lui-même, au moment où vous entrez dans le pilote, pointe vers le décalage fourni par l'utilisateur (en supposant que c'est le code utilisateur qui accède au pilote - techniquement, le noyau peut fournir le sien, mais le cas de l'utilisateur est celui à penser) via lseek
ou llseek
ou lseek64
, etc., puis par des opérations de lecture et d'écriture ordinaires. Prenons le cas d'un fichier standard sur disque :lors de la première open
le fichier, vous (en tant qu'utilisateur) demandez au noyau de fournir une structure de données qui garde une trace de votre position actuelle dans le fichier, de sorte que si vous read
ou write
quelques octets, le read
suivant ou write
reprend là où vous vous étiez arrêté.
De plus, si vous dup
le descripteur de fichier, ou faire l'équivalent par (par exemple) fork
et exec
en termes d'exécution d'une séquence de commandes, cette position de recherche est partagée par tous les processus héritiers. Ainsi, à l'invite du shell, la commande :
(prog1; prog2; prog3) > outputfile
crée un fichier de sortie, puis dup
s le descripteur des trois programmes, de sorte que la sortie prog2
les écritures vont dans le fichier immédiatement après la sortie de prog1
, et sortie de prog3
suit les deux autres, tout cela parce que les trois processus séparés partagent la même structure de données de noyau sous-jacente avec le même loff_t
interne .
Il en va de même pour les fichiers de pilote de périphérique. Lorsque vos fonctions de lecture et d'écriture sont appelées, vous recevez le "décalage actuel" fourni par l'utilisateur, et vous pouvez (et devriez) le mettre à jour si nécessaire ... en supposant qu'il y ait un besoin (par exemple, vous souhaitez fournir aux utilisateurs l'apparence d'un fichier normal, y compris le fait que les décalages de recherche se déplacent au fur et à mesure que vous lisez et écrivez). Si l'appareil a une application logique du décalage de recherche, vous pouvez l'utiliser ici.
Bien sûr, il y a beaucoup plus de pilotes de périphériques, c'est pourquoi il y a des chapitres de livre entiers sur ce sujet (q.v.). :-)
La réponse de Torek est excellente. Juste en ajoutant un peu de détails/contexte supplémentaires... À partir d'un noyau Linux antérieur (2.6.28), voici un exemple de décalage utilisé dans un appel système... il copie le décalage de l'espace utilisateur vers une variable temporaire avant d'obtenir dans le mécanisme d'invocation du pilote du noyau, puis le recopie dans le fichier utilisateur. C'est ainsi que le décalage que le pilote voit est découplé de la vue de l'utilisateur et facilite les situations où le décalage est NULL dans l'appel système, donc aucun SEGVIO ne se produit.
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);
}