Brian Kernighan v tomto videu vysvětluje prvotní přitažlivost Bellových laboratoří k malým jazykům/programům založeným na omezení paměti
Velký stroj by měl 64 k-bajtů – K, ne M nebo G – a to znamenalo, že žádný jednotlivý program nemohl být příliš velký, a tak existovala přirozená tendence psát malé programy a poté mechanismus potrubí, v podstatě vstupní přesměrování výstupu, umožnilo propojení jednoho programu s druhým.
Ale nechápu, jak by to mohlo omezit využití paměti, když vezmeme v úvahu skutečnost, že data musí být uložena v paměti RAM, aby bylo možné přenášet mezi programy.
Z Wikipedie:
Ve většině systémů podobných Unixu se všechny procesy potrubí spouštějí ve stejnou dobu [zdůrazňuji důl] , s jejich proudy vhodně propojenými a spravovanými plánovačem spolu se všemi ostatními procesy běžícími na počítači. Důležitým aspektem, který odlišuje unixové roury od jiných implementací rour, je koncept ukládání do vyrovnávací paměti:například odesílající program může produkovat 5000 bajtů za sekundu a přijímající program může být schopen přijmout pouze 100 bajtů za sekundu, ale ne. data jsou ztracena. Místo toho je výstup odesílajícího programu uložen ve vyrovnávací paměti. Když je přijímající program připraven číst data, další program v potrubí čte z vyrovnávací paměti. V Linuxu je velikost vyrovnávací paměti 65536 bajtů (64KB). K dispozici je open source filtr třetí strany s názvem bfr, který v případě potřeby poskytuje větší vyrovnávací paměti.
To mě mate ještě víc, protože to zcela maří účel malých programů (ačkoli by byly do určitého rozsahu modulární).
Jediná věc, kterou si dokážu představit jako řešení mé první otázky (omezení paměti je problematické v závislosti na velikosti dat), by bylo to, že velké datové sady se tehdy jednoduše nepočítaly a skutečný problém potrubí měl vyřešit. množství paměti požadované samotnými programy. Ale s ohledem na tučný text v citaci z Wikipedie mě mate i toto:protože jeden program není implementován najednou.
To vše by dávalo velký smysl, kdyby byly použity dočasné soubory, ale chápu, že roury nezapisují na disk (pokud není použit swap).
Příklad:
sed 'simplesubstitution' file | sort | uniq > file2
Je mi jasné, že sed
čte soubor a chrlí jej řádek po řádku. Ale sort
, jak uvádí BK v propojeném videu, je tečka, takže všechna data je třeba načíst do paměti (nebo ano?), poté jsou předána uniq
, což (podle mého názoru) by byl program s jedním řádkem za druhým. Ale mezi prvním a druhým potrubím musí být všechna data v paměti, ne?
Přijatá odpověď:
Data není nutné ukládat do paměti RAM. Pipes blokují své autory, pokud tam čtenáři nejsou nebo nemohou držet krok; pod Linuxem (a většinou dalších implementací, jak si myslím) existuje nějaké ukládání do vyrovnávací paměti, ale to není nutné. Jak zmínili mtraceur a JdeBP (viz odpověď posledně jmenovaného), rané verze Unixu ukládaly roury na disk, a takto pomohly omezit využití paměti:procesní potrubí bylo možné rozdělit na malé programy, z nichž každý by zpracovával nějaká data. , v rámci limitů vyrovnávací paměti disku. Malé programy zabírají méně paměti a použití rour znamenalo, že zpracování mohlo být serializováno:první program by běžel, naplnil jeho výstupní vyrovnávací paměť, byl pozastaven, pak by byl naplánován druhý program, zpracovával vyrovnávací paměť atd. Moderní systémy jsou příkazy o velikosti větší než rané unixové systémy a může vést mnoho potrubí paralelně; ale u obrovského množství dat byste stále viděli podobný efekt (a varianty tohoto druhu techniky se používají pro zpracování „velkých dat“).
Ve vašem příkladu
sed 'simplesubstitution' file | sort | uniq > file2
sed
čte data ze file
podle potřeby jej zapíše tak dlouho, dokud sort
je připraven ji číst; if sort
není připraven, bloky zápisu. Data nakonec skutečně žijí v paměti, ale to je specifické pro sort
a sort
je připraven řešit jakékoli problémy (bude používat dočasné soubory, pokud je množství dat k třídění příliš velké).
Chování blokování můžete vidět spuštěním
strace seq 1000000 -1 1 | (sleep 120; sort -n)
To vytváří značné množství dat a převádí je do procesu, který není připraven číst nic na první dvě minuty. Uvidíte počet write
operace projdou, ale velmi rychle seq
se zastaví a počká, než uplynou dvě minuty, blokováno jádrem (write
systémové volání čeká).