abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
dnes 08:00 | Zajímavý software

Chafa (GitHub) je utilita a knihovna pro zobrazování libovolných obrázků v terminálu. Novinky v nejnovější verzi 1.8 v příspěvku na blogu.

Ladislav Hagara | Komentářů: 1
včera 12:11 | Nová verze

Společnost Jolla oznámila vydání verze 4.2.0 s kódovým názvem Verla mobilního operačního systému Sailfish OS (Wikipedie). Podrobný přehled novinek v poznámkách k vydání.

Ladislav Hagara | Komentářů: 0
18.9. 20:33 | Nová verze

Foreman (Wikipedie), nástroj pro kompletní správu životního cyklu fyzických i virtuálních serverů, byl vydán ve verzi 3.0. Přehled novinek v poznámkách k vydání.

Ladislav Hagara | Komentářů: 0
18.9. 14:11 | Nová verze

Byla vydána nová stabilní verze 2.10.28 svobodné aplikace pro úpravu a vytváření rastrové grafiky GIMP (GNU Image Manipulation Program). Verze 2.10.26 byla přeskočena. Přehled novinek v oznámení o vydání a v souboru NEWS na GitLabu. Vývojáři zdůrazňují opravu několika chyb ve verzi pro Windows. Nový GIMP je již k dispozici také na Flathubu.

Ladislav Hagara | Komentářů: 1
18.9. 13:55 | Nová verze

Český LibreOffice tým vydává překlad příručky LibreOffice Impress 7.0. Tato příručka je určena pro začátečníky i pokročilé uživatele aplikace Impress, prezentační komponenty v LibreOffice. S její pomocí můžete vytvářet snímky, které obsahují text, číslované a odrážkové seznamy, tabulky, grafy, videoklipy, kliparty a další objekty. Impress přichází s předdefinovanými textovými styly a předlohami snímků; můžete si také vytvořit vlastní. Příručka je ke stažení na stránce dokumentace. Tým nyní pracuje na překladu příruček Draw a Base.

Zdeněk Crhonek | Komentářů: 0
17.9. 20:00 | Nová verze

Bylo vydáno Ubuntu 18.04.6 LTS, tj. šesté opravné vydání Ubuntu 18.04 LTS s kódovým názvem Bionic Beaver (poznámky k vydání). Řešen je především problém s bootovaním předchozích instalačních obrazů se zapnutým Secure Bootem z důvodu revokace klíčů kvůli BootHole a dalším bezpečnostním chybám v zavaděči GRUB 2.

Ladislav Hagara | Komentářů: 2
17.9. 09:22 | Komunita

Vývojáři Ubuntu oznámili, že v Ubuntu Desktopu bude Firefox ve formátu deb nahrazen Firefoxem ve formátu snap vydávaným přímo Mozillou. Pravděpodobně již ve verzi 21.10.

Ladislav Hagara | Komentářů: 59
17.9. 08:00 | Nová verze

Deno (Wikipedie), běhové prostředí (runtime) pro JavaScript a TypeScript, bylo vydáno ve verzi 1.14. Přehled novinek v poznámkách k vydání.

Ladislav Hagara | Komentářů: 0
17.9. 07:00 | Komunita

Linux Mint má nové webové stránky. Pro porovnání stránky z minulého týdne.

Ladislav Hagara | Komentářů: 1
16.9. 22:55 | IT novinky

Dnes ve věku 81 let zemřel Clive Sinclair, známý především jako tvůrce počítače ZX Spectrum.

Ladislav Hagara | Komentářů: 10
Dotykový displej na notebooku nebo desktopu
 (37%)
 (7%)
 (5%)
 (52%)
Celkem 447 hlasů
 Komentářů: 11, poslední 18.9. 18:45
Rozcestník

Načítání dat v C: read vs. fread

4.9. 19:29 | Přečteno: 1172× | Linux | Výběrový blog | poslední úprava: 4.9. 19:29

U více začátečníků (včetně sebe kdysi) jsem se setkal se zmatením, jak se liší funkce read a fread, open a fopen, a jak je správně používat.

libc a syscally

Pro porozumění je potřeba vysvětlit, jak funguje libc. libc je standardní knihovna jazyka C a poskytuje funkce jako třeba printf, strlen nebo malloc. Existuje mnoho implementací libc, na Linuxu se nejčastěji setkáte s glibc, malé distribuce jako OpenWRT používají musl libc.

glibc poskytuje jednak funkce, které něco složitého dělají (například qsort nebo printf), a jednak funkce, které jsou jenom wrapperem na nějaký konkrétní syscall, aby člověk mohl zavolat syscall jménem a předat mu normálně parametry - jinak by bylo potřeba používat komplikovanou funkci syscall. To, do které ze dvou zmíněných tříd daná funkce patří, zjistíte z toho, v jakém oddílu manuálových stránek se nachází - 2. oddíl jsou syscally, 3. oddíl jsou skutečné knihovní funkce. Například malloc(3) nebo mmap(2).

Surové I/O nad file deskriptory

Funkce open(2), read(2) a write(2) jsou wrappery nad syscally a pracují přímo s file deskriptory, což je nějaké nízké číslo - například po spuštění má proces standardně otevřené deskriptory 0 (stdin), 1 (stdout) a 2 (stderr). Čísla jsou taky vidět v /proc/PID/fd a dají se strkat třeba do poll(2).

Stream I/O nad FILE objekty

Funkce fopen, fread a fwrite operují nad složitějšími objekty FILE*. Ten má nějaký vnitřní buffer a umožňuje složitější operace, například fgetc(3), ungetc(3) a fscanf(3). FILE* nemusí nutně odpovídat 1:1 nějakému file descriptoru, například se dá pomocí funkce fmemopen(3) otevřít soubor který je jenom virtuální v paměti.

Předem otevřené jsou streamy stdin, stdout a stderr.

Rozdíly mezi nimi

Surové I/O je víc low-level a není tolik portable na ne-unixové systémy. Z hlediska uživatele (programátora uživatelské aplikace) je důležité třeba to, že read a write můžou vrátit jenom částečně naplněný buffer (jako návratovou hodnotu vrátí, kolik dat se skutečně přečetlo/zapsalo, a pokud chcete víc, tak je musíte spustit znova se zbytkem dat) - to se děje když používáte síť, čtete data z roury atd. a víc dat není ještě dostupných. Oproti tomu streamové FILE* I/O blokuje dokud nepřečte všechno (nebo nedojde k chybě).

Další rozdíl, a to je ten, na který jsem u začátečníků nejvíc narazil, je rychlost pokud čteme malé prvky - například po bajtech nebo po něčem jako 4bajtových integerech. Syscally mají docela režii, nedávno se ještě zpomalily kvůli opravám chyby Meltdown, a typicky je možné udělat maximálně pár milionů syscallů za sekundu. Proto bude následující program, který čte po bajtech a zapisuje (nezměněné) velmi pomalý - u mě dává 2.4 MB/s.

#include <unistd.h>
#include <inttypes.h>

int main() {
  uint8_t a;
  while(1) {
    if(read(0, &a, 1) <= 0) { // EOF reached
      break;
    }

    // udělej něco s a

    write(1, &a, 1);
  }
}

To stejné přepsané pomocí fread dává 44 MB/s, tedy 20x víc.

#include <stdio.h>
#include <inttypes.h>

int main() {
  uint8_t a;
  while(1) {
    if(fread(&a, 1, 1, stdin) <= 0) {
      break;
    }

    fwrite(&a, 1, 1, stdout);
  }
}

Rozdíl je v syscallech, což můžeme zjistit například pomocí

cat /dev/zero | strace -e read ./test-read > /dev/null

U prvního programu vidíme, že každý syscall přečte jeden bajt, přesně jak jsme napsali:

read(0, "\0", 1)                        = 1
read(0, "\0", 1)                        = 1
read(0, "\0", 1)                        = 1
read(0, "\0", 1)                        = 1

Oproti tomu fread, díky tomu, že je bufferovaný, čte do svého vnitřního bufferu vždy 4096 bajtů najednou:

read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096
read(0, "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 4096) = 4096

(tohle bychom samozřejmě mohli ošetřit i na aplikační úrovni - nezpracovávat prvky v cyklu po jednom, ale vždy si jich načíst větší množství, zpracovat a zapsat. Opruz je s tím, že jak write může zapsat jenom část výsledku, tak se minimálně ten zápis musí opakovat a buffer správně managovat…)

fread_unlocked

I tak je 44 MB/s docela málo (na druhou stranu jde o prvky o velikosti 1 bajt, pokud čtete třeba 4bajtové inty, bude to lepší). Ukazuje se, že bottleneck je v tom, že fread a fwrite musí být thread-safe - mají ten vnitřní buffer a samozřejmě by se to pokazilo, kdyby z něj četla dvě vlákna současně. Proto při každém volání zamykají a odemykají. Existují varianty fread_unlocked a fwrite_unlocked, po jejich použití mi to dává 460 MB/s. Samozřejmě si pak musíme sami ošetřit, abychom nepoužívali jeden soubor ve více vláknech současně.

Další zrychlení se pak už dosáhne jen načítáním více prvků najednou. Už při načítání 64B bufferů se dostaneme na 1.8 GB/s.

Pokud by nám šlo pouze o maximální výkon I/O a nestačily by nám ani tyto GB/s, tak pro další optimalizace se naopak hodí napsat si vlastní bufferování s read a write, protože fread a fwrite mají trochu overhead tím vlastním bufferováním. V takovém případě by ale už bylo lepší porozhlédnout se po nějakém jiném způsobu optimalizovaném na masivní I/O - například soubor mapovaný do paměti pomocí mmap, komunikaci mezi procesy pomocí vmsplice a I/O pomocí io_uring.

       

Hodnocení: 100 %

        špatnédobré        

Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

Komentáře

Vložit další komentář

4.9. 20:36 move On
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Jako cool, ze se tady resi programatrostina, ale neni C tak 20 let za zenitem a opicema? Co takhle Rust?
4.9. 21:13 johnyK | blog: uxblog
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
ja pisu v kazdem jazyku C-programy
4.9. 21:32 dik
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
První příspěvek a hned rust-katolík :-D Víš jak poznáš že někdo dělá v rUsTU? řekne ti to.
4.9. 21:51 move On
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Co to jsou za konzervativni kecy? Je Cecko 50leta vykopavka? Je. Ma sve fatalni mouchy? Ma. Tak proc nepodporit jazyk, ktery je ve vsem lepsi nez C a syntakticky velice blizky?
4.9. 21:53 dik
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Kliiiid vegane, věř si čemu chceš ale nikomu to necpi.
4.9. 23:24 plostenka
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Uz ma Rust dynamicky linkovane knihovny? Uz je v ABI kompatibilni aspon zpetne sam se sebou?
5.9. 07:53 move On
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Samozrejme ze binarni interfejs je v Rust spetne linkovatelny. Ceckare ale sere ze neni kompatibilni a nemohou tak krast krasne knihovny napsane v Rustu! Detto dynlink, prekonany koncept z dob kdy se setrilo harddiskem. Proc ma kazdy flatpack apky? Aby se predeslo dll hell s dynamickymi knihovnamy Sherlocku. Takze se tu nesnaz prudit ceckarskyma starozitnostma kdyz jsou mimo misu.
6.9. 12:30 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Uz ma Rust dynamicky linkovane knihovny? Uz je v ABI kompatibilni aspon zpetne sam se sebou?
ABI stabilní není.

Dynamické linkování funguje už velmi dlouho, akorát ti s tim nepomůže tooling a musíš si sestavování, kompatibilitu etc. řešit do značný míry sám. Osobně bych nečekal, že by vůbec někdy Rust v nějaký větší míře přecházel na dynamické linkování vzhledem k širokému používání generik. Dynamického linkování v Rustu bych spíš viděl jako doplněk pro případy jako třeba nějaké binární pluginy apod.
I am not a sheep! | Preferovaná zájmena: his Royal Highness / his Royal Highness
xkucf03 avatar 5.9. 01:32 xkucf03 | skóre: 49 | blog: xkucf03
Rozbalit Rozbalit vše C, D, Java, Rust, Go

Syntakticky blízké je třeba D nebo Java. Zrovna Rust je dost jiný (a často mi přijde, že poněkud samoúčelně, podobně jako Go… trochu z toho čiší snaha dělat věci za každou cenu jinak a vymezovat se proti stávajícím jazykům).

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes
6.9. 12:19 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
První příspěvek a hned rust-katolík :-D Víš jak poznáš že někdo dělá v rUsTU? řekne ti to.
Spíš je to troll, kterýmu je to reálně jedno, jen si našel způsob trollení.
I am not a sheep! | Preferovaná zájmena: his Royal Highness / his Royal Highness
Gréta avatar 6.9. 12:37 Gréta | skóre: 32 | blog: Grétin blogísek | Stockholm
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread

aje teda jakoby víc lepšejší rust nebo c????? :O :O ;D ;D

bin ladin 👳🏾💣: 'bidena nezabíjejte je neschopnej'wie spát ist es?? 🛏 ⌚
6.9. 12:40 Gilhad | skóre: 20 | blog: gilhadoviny
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
To jako záleží na tom, koho zrovna chceš vícejc trolit :D :D :D
6.9. 19:19 move On
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Rustaka nevytrolis, ma IQ i EQ. Na fakta ti odpovi anekdotou a na emoce te zazdi neprustrelnym faktem. Takze prudit tu budou hlavne C-konzervy s bibli od Kernighan-Richieho v ruce jedne a s "Jak poznam srakzmus" v ruce druhe.
6.9. 12:59 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread

aje teda jakoby víc lepšejší rust nebo c????? :O :O ;D ;D

No, tak čistě osobně jsem rustem nadšen od doby, co jsem s tim začal něco dělat (ca. 2014), takže samozřejmě rust :Đ, ale to je subjektivní, objektivní názor neexistuje a záleží, jaký máš požadavky, preference a tak...
I am not a sheep! | Preferovaná zájmena: his Royal Highness / his Royal Highness
6.9. 13:13 Tomáš Roll
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Nejlepší je Java - píšeš podobnou syntaxí jako v céčku, ale je to mnohem bezpečnější. Plus tam máš generika i sdílené knihovny (nemusíš si vybrat jen jedno z toho, jak by ti nutil Králík).
6.9. 19:11 Tro7
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
A elf binarka hello worldu v jave ma 5 mega nebo 6 ?
6.9. 20:21 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Nevim jak v Javě, ale v Rustu zhruba tolik no :-D
I am not a sheep! | Preferovaná zájmena: his Royal Highness / his Royal Highness
6.9. 21:09 Debian-
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
To jsou pomluvy! HelloWorld v C 8k, v Rust 400k.
6.9. 21:42 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
By default dostanu z release buildu u mě 3.2MB. Je ale pravda, že naprostá většina toho jsou debug symboly, který když stripnu, je z toho ~300k...
I am not a sheep! | Preferovaná zájmena: his Royal Highness / his Royal Highness
6.9. 21:58 linker
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Tych 8k je len preto, lebo to nemas staticky zlinkovane so stdio, teda libc, co na linuxe je glibc a bude to mat 2 mega kamo.
6.9. 21:32 Tomáš Roll
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Má to nějakých 2,4 MB (zkoušeno se starší verzní GraalVM). Ano, na hello world, který jen na výstup vyplivne pár bajtů, je to hodně, ale nezávisí to na žádných dynamických knihovnách (kromě obligátních systémových libc, librt, linux-vdso...) a když si vypíšeš symboly (nm), tak zjistíš, že to podporuje Unicode a konverzi kódování UTF-8, UTF-16, ISO-8859-1, ASCII... nebo že tam máš garbage collector a další věci. Jasně, můžeš říct, že pro hello world to je zbytečné a navíc, ale v drtivé většině aplikací zrovna tyhle věci potřebuješ a do té céčkovské aplikace by sis příslušné knihovny musel přidat a ta binárka by ti taky nakynula. Výsledek je pak srovnatelný, akorát v té Javě se píše o dost pohodlněji a máš tam lepší správu paměti, tu podporu Unicodu a další věci, které moderní vysokoúrovňový jazyk podporuje.

Jinak ano, taky je mi bližší, když si člověk explicitně přibalí jen to, co potřebuje, a ta základní povinná výbava je minimální. Ale těch 2,4 MB je na dnešní poměry docela málo a zbytečností tam moc není. Takže za mě je tohle fajn cesta. Určitě lepší než smolit nějaké céčko jak v 70. letech a každou chvíli se střílet do nohy.
9.9. 15:19 j
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Spis tak 500 ... nezapomen zahrnout jeste vsechny ty sracky kolem ktery potrebujes k tomu aby to slo vubec spustit.

---

Dete s tim guuglem dopice!
9.9. 15:48 gugl nepujde do pice
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Bavime se o prekompilovane elf binarce, ne o java runtime ktera samozrejme potrebuje podporne soubory JRE.
11.9. 21:21 katon
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Však Ti nikdo nebrání něco o RUSTu napsat, o čem píšou ostatní je jejich věc..
4.9. 21:31 johnyK | blog: uxblog
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Z hlediska uživatele (programátora uživatelské aplikace) je důležité třeba to, že read a write můžou vrátit jenom částečně naplněný buffer (jako návratovou hodnotu vrátí, kolik dat se skutečně přečetlo/zapsalo, a pokud chcete víc, tak je musíte spustit znova se zbytkem dat)
to je skutecne u site nebou roury ten pripad, jak pises, ale u souboru na harrdisku si myslim je mozne rici, ze pokud se neprecte tolik, kolik se zadalo v tom odpovidajicim parametru, tak je problem ...
Jendа avatar 4.9. 21:33 Jendа | skóre: 77 | blog: Jenda | JO70FB
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Ještě mohl přijít signál (třeba u dd je tohle populární, protože mu lidi posílají USR1 aby se dozvěděli progress).
Víte o tom, že losování Sportky je ve skutečnosti česká number station?
4.9. 23:27 plostenka
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
dd uz nejakou dobu umi status=progress.
Josef Kufner avatar 4.9. 21:34 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Nebo je fragmentovaný soubor a než se našel druhý blok, tak přišel signál a volání přerušil.
Hello world ! Segmentation fault (core dumped)
4.9. 22:30 johnyK | blog: uxblog
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
ale u toho signalu je pak return-code = -1 nebo?

jediny co u harddisku snad muze byt, kdy je return >= 0 , kdyz se aktualni pozice v souboru nachazi nekde u konce toho souboru a je pozadovano vice bajtu jak jeste do konce zbyva. Pak se skutecne vrati min nez pozadovano a pro to pristi volani (kdy chci ten 'mysleny' zbytek) se vrati nula - coz je take samozrejme spravne.

Ale takovy vyse uvedeny pripad je podle me jen teorie, ktera nema s aplikacni praxi nic moc spolecneho. Jestlize v aplikaci ocekavam nejaky pocet bajtu a nedostanu je, tak je asi nekde chyba.
Josef Kufner avatar 4.9. 23:12 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Pokud se systémové volání přeruší dřív (např. signálem), než načte všechna požadovaná data, tak jich prostě vrátí méně. Ten read() je vážně nízkouúrovňová věc, která toho moc neumí. Proto máme fread(), který takové ošklivosti řeší a drží si vlastní buffer, který se do integeru (file descriptoru) prostě nevejde (narozdíl od FILE*).
Hello world ! Segmentation fault (core dumped)
5.9. 01:28 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread

Konkrétně viz read(3p):

If a read() is interrupted by a signal before it reads any data, it shall return −1 with errno set to [EINTR].

If a read() is interrupted by a signal after it has successfully read some data, it shall return the number of bytes read.

5.9. 16:09 johnyK | blog: uxblog
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
diky za odpoved, ale presto bych rad, aby to nekdo ted vysvetlil.

Ja se priznam, ze prichazim z jine doby a za me existoval jen read(2). - to jsem ted zkontroloval v me referencni prirucce od AT&T pro unix system V. Take tam stoji, ze kdyz se behem toho volani read vyskytne signal, tak je return = -1. O tom jestli se neco precetlo nebo ne se tam nic nerika.

Dost jsem koukal, ze to co jste uvedl skutecne existuje = read(3p).

K tomu mam ted samozrejme otazku - v tech linux manual pages pro read(2) a read(3p) jsem nepostrehl, jak to udelam aby se vyvolala ta funkce=(3p) a nebo ten syscall=(2).

Autor blogpostu rozlisoval prave read a fread -> tam je to jasne co je syscall a co je knihovni funkce.

Jeste na okraj, u toho read(2) mam pocit, ze i v tech novych manual pages se u signalu vrati -1 at uz se neco nacetlo nebo ne.
5.9. 16:12 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
read(3p) je posixová manuálová stránka, která popisuje, jak by se ten syscall měl chovat podle POSIXu. read(2) je linuxová manuálová stránka, která (je-li dostatečně aktuální) popisuje, jak se aktuálně chová na Linuxu (včetně případných rozšíření).
5.9. 16:16 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Jinak moje verze read(2) také uvádí
EINTR     The call was interrupted by a signal before any data was read; see signal(7).

Dává to tak i víc smyslu. Pokud byste vrátil -1/EINTR, nebude mít volající šanci poznat, jestli se něco přečetlo a pokud ano, kolik toho bylo.

5.9. 01:23 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
u souboru na harrdisku si myslim je mozne rici, ze pokud se neprecte tolik, kolik se zadalo v tom odpovidajicim parametru, tak je problem

Ne tak úplně:

mike@lion:/srv/ram> ls -l file8
-rw-r--r-- 1 mike users 8589934592 zář  5 01:12 file8
mike@lion:/srv/ram> strace dd if=file8 of=/dev/null bs=8G 
...
read(0, "t\371\246\323\310\34\365\332\202\200'X\366\234GI\327N9\353\224\361\n\315\200)z(?\221\220&"..., 8589934592) = 2147479552
write(1, "t\371\246\323\310\34\365\332\202\200'X\366\234GI\327N9\353\224\361\n\315\200)z(?\221\220&"..., 2147479552) = 2147479552
read(0, "\234]Z\213\217\214B\247 SZ\320\20\361\273i\376\250?\26\324\320\333\213\n\256^=\26{0\325"..., 8589934592) = 2147479552
write(1, "\234]Z\213\217\214B\247 SZ\320\20\361\273i\376\250?\26\324\320\333\213\n\256^=\26{0\325"..., 2147479552) = 2147479552
read(0, "\"\177l\254\316\212\325\342]\378\244;*\\\365l\25A\352\6\t\310\311/\313\336.\23\250D<"..., 8589934592) = 2147479552
write(1, "\"\177l\254\316\212\325\342]\378\244;*\\\365l\25A\352\6\t\310\311/\313\336.\23\250D<"..., 2147479552) = 2147479552
read(0, "\204\232\271\5\225\10/J\346\333\236\326/~{\264\214\217\244\31\367\212SK\220\2421\220\302n<A"..., 8589934592) = 2147479552
write(1, "\204\232\271\5\225\10/J\346\333\236\326/~{\264\214\217\244\31\367\212SK\220\2421\220\302n<A"..., 2147479552) = 2147479552
read(0, "\372\271\247_\252K\32\253\253\372\366\300\34\37\362\33\332\363\r{\3\6-\24\20\344\302\376\333~\366\245"..., 8589934592) = 16384
write(1, "\372\271\247_\252K\32\253\253\372\366\300\34\37\362\33\332\363\r{\3\6-\24\20\344\302\376\333~\366\245"..., 16384) = 16384
read(0, "", 8589934592)                 = 0
close(0)                                = 0
close(1)                                = 0
...
0+5 records out
8589934592 bytes (8,6 GB, 8,0 GiB) copied, 1,06331 s, 8,1 GB/s)
Josef Kufner avatar 4.9. 21:33 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Hlavní rozdíl mezi read() a fread() je v tom, že read() je dost těžké použít zcela správně. Takže hlavní poučení je používat knihovny, například fread(), kde už se s tím trápil někdo jiný.
Hello world ! Segmentation fault (core dumped)
5.9. 01:34 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Většinou ano, ale jsou situace, kdy je potřeba jemnější kontrola nad tím, co a jak se přesně čte nebo zapisuje, kterou ta knihovní nadstavba neumožňuje.
5.9. 19:44 luky
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Tak treba pri cteni virtualnich souboru (/proc/, /sys/ etc.) muze fread nacist bordel, protoze neprecte data jednim volanim, a je mnohem vetsi sance, ze uzivatel dostane, co ceka, pokud pouzije read. Jedine, co jde doporucit, je, at se programator seznami s tim, jak funguje I/O na urovni jadra a jak funguje "nadstavba" v glibc a potom si vybere podle potreby.
6.9. 01:54 debian+ | skóre: 25 | blog: analyzy
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Tak subor z /proc treba citat po bajtoch. Zrejme to je znakove pseudo-zariadenie, a nie blokove.
debian.plus@protonmail.com
6.9. 05:23 kvr
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
To vůbec nesouvisí s tím, zda je blokové nebo znakové a vůbec nesouvisí s tím, jestli fread vs read přečtou celé nebo jenom kus. Bude-li čtení přerušeno, tak fread se taky může vrátit předčasně (teď nevím, co přesně udělá EINTR či EAGAIN, ale všechny ostatních chyby se budou reportovat). /proc jsou typicky virtuální soubory (případně část pseudo-linky na skutečné soubory), kernel bude mnohem radši, když jej userspace přečte celý najednou než po bytech.
6.9. 07:47 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Jádro se s tím nějak vypořádá, problém je spíš v tom, že mnohé soubory v proc nebo sysfs prezentují aktuální stav, který se průběžně mění, takže je docela dobře možné, že složením toho, co přečtou dvě volání read(), dostanete nekonzistentní obsah (a dost možná i obsah, který vůbec nedává smysl).
6.9. 18:11 kvr
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Já bych řekl, že výsledky budou atomické. Což znamená, že jádro si musí někde zapamatovat aktuální stav v době prvního čtení (případně ten zformátovaný buffer). Takže ano, jádro se s tím samozřejmě vypořádá, ale bude stát tenhle snapshot navíc, proto věta "jádro bude určitě radši, když si userspace přečte všechno najednou".
6.9. 18:28 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Aby tohle mohlo fungovat, muselo by jádro držet buď celý snapshot v podobě, v jaké půjde na výstup, nebo data, ze kterých se generuje. Jednak vím, že to tak není, protože už jsem s generováním proc souborů měl něco do činění, jednak to tak dost dobře fungovat ani nemůže, protože mezi těmi dvěma voláními může uběhnout libovolně dlouhá doba nebo dokonce druhý read() nemusí přijít vůbec a pak byste tam měl leak za každé takové nedokončené čtení.
xkucf03 avatar 6.9. 18:39 xkucf03 | skóre: 49 | blog: xkucf03
Rozbalit Rozbalit vše Syntetické souborové systémy a atomické čtení

Nebylo by pak lepší napoprvé vracet chybu, pokud se nepovede načíst vše najednou?

Třeba informace z alsy jsou někdy docela dlouhé:

$ cat /proc/asound/card0/codec#0 | wc 
    113     527    3958

Jindy je to třeba jen jedno číslo nebo jeden krátký řádek.

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes
6.9. 19:20 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Syntetické souborové systémy a atomické čtení
Nebylo by pak lepší napoprvé vracet chybu, pokud se nepovede načíst vše najednou?

Někde by to asi smysl mělo, ale určitě ne obecně. Co když userspace opravdu zajímá jen začátek? Navíc existují soubory jako /proc/kcore, které celé najednou ani přečíst nejdou.

Mimochodem, 3958 není tak moc, to se pořád vejde do 4096, což je IIRC defautní délka bloku, po kterém čte glibc, pokud si neřeknete o víc (např. když zavoláte fgetc()). Ale jsou i soubory, které mohou být podstatně delší, např. v /proc/net.

xkucf03 avatar 6.9. 19:37 xkucf03 | skóre: 49 | blog: xkucf03
Rozbalit Rozbalit vše Re: Syntetické souborové systémy a atomické čtení

To je pravda, někdo asi může chtít číst jen začátek a nemusí to být chyba. Správné řešení by nejspíš bylo to vázat na otevřený FD a dokud ho uživatel nezavře, tak držet tu původní verzi konzistentní (zatímco jiným už poskytovat novější data). Akorát by se musela paměť alokovat dynamicky a bylo by to náročnější na implementaci.

Mám rád, když se lidé přou, znamená to, že vědí, co dělají, a že mají směr. Frantovo.cz, SQL-DK, Relational pipes
7.9. 00:36 luky
Rozbalit Rozbalit vše Re: Syntetické souborové systémy a atomické čtení
Todle je blbost z nekolika duvodu:

- Muzete si otevrit soubor a cist ho treba kazdou vterinu, a tim samplovat stav systemu. Periodicke volani pread s offsetem 0 na fd souboru v /proc nebo /sys je beznej usecase.

- U velkych souboru by to slo pouzit k DOS, protoze bych mohl vyalokovat mnohem vic pameti, nez mi povoluje ulimit (pamet by slo omezit jen pomoci memcg).

- Mrhani zdroji pri generovani dat, ktera nikdo necte.

Nejlepsi proste je, kdyz uzivatel neni pitomec a preste si, jak veci funguji, nez je pouzije. Pak se muze informovane rozhodnout, jestli data potrebuje precist atomicky a nebo ne a podle toho proste pouzije velkej buffer a nebo ne.
Jendа avatar 7.9. 00:46 Jendа | skóre: 77 | blog: Jenda | JO70FB
Rozbalit Rozbalit vše Re: Syntetické souborové systémy a atomické čtení
Mimochodem nedávno se řešil readfile syscall, který načte soubor a tečka - takže věci co čtou periodicky hodně z /proc nemusí dělat open, (p)read, close. Ale zatím to nevypadá hotově.
Víte o tom, že losování Sportky je ve skutečnosti česká number station?
7.9. 13:40 luky
Rozbalit Rozbalit vše Re: Syntetické souborové systémy a atomické čtení
Tak to nemusej ani ted, muzou volat v cyklu pread ;-) Hodi se to spis pro aplikace typu grep, co prohledava vsechny soubory.
7.9. 14:04 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Syntetické souborové systémy a atomické čtení
Hodi se to spis pro aplikace typu grep, co prohledava vsechny soubory.
AFAIK rychlý alternativy ke grepu (ag, ripgrep) se na tohle snažej používat memory mapping. ripgrep v komentářích tvrdí, že používá heuristiky, ale jestli to dobře čtu, tak jen vypne mmaping na 32 bitech a na macosu, ale jinak se snaží používat mmap.

Nevim, jestli readfile má tohle změnit...
I am not a sheep! | Preferovaná zájmena: his Royal Highness / his Royal Highness
Jendа avatar 7.9. 20:51 Jendа | skóre: 77 | blog: Jenda | JO70FB
Rozbalit Rozbalit vše Re: Syntetické souborové systémy a atomické čtení
To se vyplatí pro velké soubory. Pokud máš malinké soubory, bude mít mmap taky overhead (otevřít a zavřít ten soubor musíš stejně, takže zbytečně mnoho syscallů se děje, a ještě asi budeš muset udělat munmap).
Víte o tom, že losování Sportky je ve skutečnosti česká number station?
7.9. 21:25 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Syntetické souborové systémy a atomické čtení
Zmíněný nástroje by default používaj mmap pro všechny velikosti. Můj odhad je, že pro velký soubory to je rychlejší a pro malý to vyjde nastejno...
I am not a sheep! | Preferovaná zájmena: his Royal Highness / his Royal Highness
6.9. 18:53 kralyk z abclinuxu | skóre: 29 | blog:
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Když jsem si tady hrál s těmi kernel ultras fortunami v kernelu, dělal jsem to tak, že jsem sestavil ten obsah v paměti a pak ho vrátil do userspace celej, takže na jedno volání (typicky to bylo pár stovek bajtů, možná kilobajt). Pokud měl userspace menší buffer než výsledek, tak jsem mu řekl, že EINVAL. (Což možná není úplně košér / serióznější projekt by to asi udělal jinak, ale zas mi nepřijde, že možností by bylo kdovíkolik, protože jak píšeš, člověk si tam nechce skladovat někde nějaký rozdělaný "transakce".)
I am not a sheep! | Preferovaná zájmena: his Royal Highness / his Royal Highness
5.9. 15:50 debian+ | skóre: 25 | blog: analyzy
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Nemáš pravdu o glib knižnice. Ona je doplnok, nie náhrada. Napr. glib nemá niečo také, ako je fclose. :) Napr. má user-like hast tables.
debian.plus@protonmail.com
5.9. 16:21 johnyK | blog: uxblog
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
autor napsal glibc
6.9. 01:59 debian+ | skóre: 25 | blog: analyzy
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Tak funkcie s prefixom majú aj vážny dôvod. Sú aj user like. Ošetrujú kadejaké vynimky, trebárs chyba na busy. A jasne, nastavovanie/rušenie týchto prípadných signálov niečo výkonu stoji.
debian.plus@protonmail.com
6.9. 18:19 kvr
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
fread žádné signály nenastavuje. Implementuje userspace cache, aby se pro každý byte nešlo do jádra a organizuje čtení do bloků, které vyžaduje volající. To má klady a zápory, jak s ohledem na výkon, tak některé potenciálně nechtěné vedlejší efekty, jako nekonzistence mezi tím, co říká jádro a co říká userspace (například select vrací žádná data, zatímco v userspace buffer ještě jsou).
6.9. 18:31 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
Zrovna použití select() / poll() / epoll() je příklad toho, kdy je potřeba jít na nižší úroveň a knihovní nadstavby použít nejde. Vlastně už samotné neblokující čtení by se s fread() kombinovalo dost obtížně.
Josef Kufner avatar 6.9. 23:04 Josef Kufner | skóre: 70
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
To není pravda. Filedescriptor můžeš získat pomocí fileno() a vesele ho předat select(). Například Qt toto umí také. Také jde naopak někde sebrat file descriptor a pomocí fdopen() si nad ním nachystat tu nadstavbu.

Neblokující IO je však trochu jiná kapitola, tam už to je komplikovanější.
Hello world ! Segmentation fault (core dumped)
6.9. 23:30 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread
fileno() nebo fdopen() je ta jednoduchá část. Problém je v tom, že otázka, jestli read() bude blokovat, není stejná jako jestli fread() bude blokovat. A kterýkoli z těch tří syscallů mi odpoví jen na tu první, zatímco mne, pokud budu používat ke čtení fread() bude zajímat ta druhá.
Gréta avatar 6.9. 12:30 Gréta | skóre: 32 | blog: Grétin blogísek | Stockholm
Rozbalit Rozbalit vše Re: Načítání dat v C: read vs. fread

supr fígl to ulocked dělání se souboramama :O :O snad stim jako někde neudělám neštěstí :D

bin ladin 👳🏾💣: 'bidena nezabíjejte je neschopnej'wie spát ist es?? 🛏 ⌚

Založit nové vláknoNahoru

ISSN 1214-1267   www.czech-server.cz
© 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.