"loff_t" je "dlouhý offset", tj. pozice hledání, která sjednocuje šílenou rozmanitost off_t
, off64_t
, a tak dále, aby řidiči mohli používat loff_t a nemuseli se o to starat.
Samotný ukazatel v okamžiku, kdy se dostanete do ovladače, ukazuje na offset poskytnutý uživatelem (za předpokladu, že je to uživatelský kód, který přistupuje k ovladači – technicky může jádro poskytnout svůj vlastní, ale je třeba myslet na případ uživatele) přes lseek
nebo llseek
nebo lseek64
atd. a poté běžnými operacemi čtení a zápisu. Zvažte případ běžného souboru na disku:když poprvé open
souboru, získáte (jako uživatel) jádro, které poskytne datovou strukturu, která sleduje vaši aktuální pozici v souboru, takže pokud read
nebo write
několik bajtů, dalších read
nebo write
pokračuje od místa, kde jste skončili.
Navíc, pokud dup
deskriptor souboru nebo proveďte ekvivalent (např.) fork
a exec
z hlediska spouštění posloupnosti příkazů je tato pozice hledání sdílena všemi dědícími procesy. Proto na příkazovém řádku shellu příkaz:
(prog1; prog2; prog3) > outputfile
vytvoří výstupní soubor a poté dup
je deskriptor tří programů, takže výstup je prog2
zápisy jde do souboru ihned po výstupu z prog1
a výstup z prog3
následuje další dva – to vše proto, že všechny tři samostatné procesy sdílejí stejnou základní datovou strukturu jádra se stejnou interní loff_t
.
Totéž platí pro soubory ovladače zařízení. Když jsou volány vaše funkce čtení a zápisu, obdržíte „aktuální offset“, jak je poskytnuto uživatelem, a můžete (a měli byste) jej aktualizovat podle potřeby... za předpokladu, že je to potřeba (např. chcete uživatelům poskytnout vzhled běžného souboru, včetně skutečnosti, že offsety vyhledávání se pohybují při čtení a zápisu). Pokud má zařízení nějakou logickou aplikaci offsetu hledání, můžete to použít zde.
Ovladačů zařízení je toho samozřejmě mnohem víc, a proto jsou o těchto věcech celé knihy (q.v.). :-)
Torekova odpověď je skvělá. Jen přidávám trochu dalších detailů/kontextu... Z dřívějšího linuxového jádra (2.6.28), zde je příklad offsetu používaného v systémovém volání... zkopíruje offset z uživatelského prostoru do dočasné proměnné, než získá do mechanismu vyvolání ovladače jádra a poté jej zkopíruje zpět do uživatelského souboru. Tímto způsobem je offset, který ovladač vidí, oddělen od uživatelského pohledu na něj a usnadňuje situace, kdy je offset v systémovém volání NULL, takže nedochází k žádnému SEGVIO.
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);
}