podle me jsou stali, suckless jen polovicaty radikalismus a pokrok v mezich zakona.
kdyby ti frajeri meli koule tak by hned sli do plan9.
ten ma totiz minimalismus v sobe od zacatku, vsecko fs, zadne sockety, miliony radku kodu v kernelu.
takze radsi meli dopsat soft pro plan9 a neohybat linux.
Ok, takže slinkujeme všechno staticky. Spustím si text editor, natáhne se staticky slinkovaný kolos třeba 2MB velký (jenom kvůli omu, že do něho někdo staticky zalinkoval binárky na vykreslení memo boxu, aby si je nemusel zbytečně dynamicky linkovat z OS). Vedle spustím web browser, otevřu na stránce formulář a ejhle - stejný editační pole, ale staticky zalinkovaný do web browseru, požere dalšího 0,5MB RAM. Místo toho, aby jeho "chování" bylo popsáno na jednom místě a různý programy tu samou binárku pustily na svoje data...
Statickým linkováním programy porostou ještě víc, protože každý program bude mít v sobě napevno kopii toho samýho, co ostatní programy.
"Statickým linkováním programy porostou ještě víc, protože každý program bude mít v sobě napevno kopii toho samýho, co ostatní programy."
To je pravda pouze za podmínky, kdy programy budou skutečně využívat stejné části kódu. Potom ale nastává otázka, zda by se ty programy neměly rozdělit a z té společné části kódu udělat samostatný program.
Pokud by tahle granularita byla dostatečná, potom by žádný sdílený kód nebyl.
Tak toto je pekna blbost, co ti hovoria kniznice? To akoze vznikne nejaky standardizovany interface medzi dvomi programami ci stdin <-> stdout?
A co potom to staticke linkovanie riesi. Ako vyriesim problem ze dva rozne programy potrebuju dve rozne verzie programu. To uz mozu rovno zostat dynamicke kniznice, nie?
"To akoze vznikne nejaky standardizovany interface medzi dvomi programami ci stdin <-> stdout?"
To už dávno existuje. V praxi máme také ls | grep. Toto je místo, kde se aktuálně ona granularita zastavila, taky nemáme jeden program, který umí totéž co ls | grep, máme tyto dva. Dále, například grep úplně zbytečně umí pracovat se soubory. To se také dá řešit jinými existujícími programy. Tato funkcionalita by se dala z grepu odstranit (a tím i závilosti na jedné z mnoha knihoven. Takových tam bude.).
Jenomže potom jsou jenom tři možnosti.
1) Jeden program proběhne a předá data dalšímu. Potom jeden musí skončit a předat komplet data dalšímu. To znamená uložit data na pomalý disk, skončit, uvolnit resourcy, načíst druhý program (pomalý disk), alokovat prostředky, načíst data (pomalý disk),... a uživatel je akorát tak nas..., že kompl nic nedělá a jenom hrabe po disku.
2) Program vytvoří další proces a bude komunikovat prostřednictvím named pipe. Jenomže ten proces pojede ve vlastním kontextu a musí být reentrantní, takže od systému potřebuje přepínání kontextu, musí se synchronizovat vlákna,... a výkon aplikace jde do kytek.
3) Sdílený kód se natáhne přímo do paměti hlavního procesu, takže není potřeba synchronizovat vlákna víc aplikací, přepínat kontext, furt hrkat po disku,... Prostě se předá modulu ukazatel na data a instrukce, co s nima dělat a všechno proběhne často přímo ve volajícím vlákně bez další režie. Jediná obrovská nevýhoda je, že tomu někdo dal smrdutý název "dynamický linkování", takže je to v praxi nepoužitelný...
1 a 2 jsou v podstate stejne. Porad se predavaji data pres nejakou formou souboru/streamu a chytry OS to udela tak, ze to zustane v pameti.
Jinak takovy pristup ma i nekolik vyhod - automaticka sprava pameti (GC), automaticke paralelni zpracovani, lazy eval...
Dovedu si predstavit, ze nejake jednoduche streamove zpracovani dat nebude pomalejsi nez monolytickym programem.
"Dovedu si predstavit, ze nejake jednoduche streamove zpracovani dat nebude pomalejsi nez monolytickym programem."
To si nemusíte představovat. Jinak to má i další výhodu. Zatímco udělat víceprocesový program není až tak úplně jednoduché, tak pomocí pipe tohle máte zadarmo. Každý jednotlivý program může zůstat jednoduše singlethread, přičemž po spojení pipou tyhle programy poběží všechny současně (tak jak budou přicházet data).
Precte si neco o Erlangu, pokud jste to jeste nevidel. Tam se vasim myslenkam podobne postupy jiz nejakou dobu aplikuji. Akorat misto operacniho systemu maji svuj virtual machine co bezi nad prakticky libovolnym operacnim systememe.
Kod se zde vykonava v procesech (ve smyslu Erlangu) jejichz beh je rizen shedulerem co bezi nad kazdym procesorovym jadrem co to najde (jako vlakno procesu ve smyslu operacniho systemu).
Sdilena pamet neexistuje (zdroj tezko nalezitelnych chyb a problemu). Procesy komunikuji zpravami (soucast jazyka a prislusneho VM, nikoliv nejaka nadstavba).
Vytvorit proces ve smyslu Erlangu je lacine a vyplati se to delat pro kazdou konkurenci akrivitu co se vyskytne (i kdyz transakce co ji to obsluhuje trva par milisekund).
Pripadna komunikace s vnejskem se da udelat necim cemu se tam rika Port (pusti se binarka a komunikuje se s ni pres STDIN/STDOUT jistym binarnim protokolem).
Ma to hodne zajimavych vlastnosti (napr. reload kodu aplikace za behu bez nutnosti restaru a prislusne ztraty dat u rozpracovanych transakci) a nejedna se jen o nejaky experiment, ale v praxi vyuzivany a overeny nastroj.
Nevyhodou je ponekud jiny pristup k programovani za ktery dostatete zajimavy vykon a pomerne kratke zdrojovky k programum (zajimava efektivita vysledneho dila ale i programatora). Nevyhodou je zmineny jiny pristup, ktery se musite naucit (tak mesic). Pro lepsi seznameni doporucji pouzit nejakou knizku, nejen uvodni tutorialy. A pozorne delat RTFM, snadno se da dulezity detail prehelednout :-)
> jednoduche streamove zpracovani dat nebude pomalejsi
ALE BUDE, obzvlast N krat opakovane s malym mnozstvom dat. Priklad nasobenie matic ktore sa pouziva pri vykreslovani objektov. To si mam ako skompilovat program co bude nejako 'jednoducho' parsovat matice z input streamu a potom celu scenu co idem vykreslit budem prehanat bod po bode cez externy programcek. BLBOST AKO TRAKY.
Obávám se, že například balit a komprimovat data určitě nezvládnete naprogramovat rychleji, než já napíšu tar | gzip. Dále tohle má neomezenou volnost, pokud budu chtít ty data opravdu důkladně šifrovat, tak tar | gzip | rot13 (:-D). Výsledný program sice jistě budete schopen naprogramovat také, ale mnohem obtížněji budete řešit věci jako multithreading apod.
Samozřejmně ;-)
Jinak v praxi se všechny 3 přístupy používají. Na bod 1 se často používají tmpfs (nebo prostře jakýkoliv fs v ram), a do stávající fs se dávají heuristiky na detekci takovýchto dočasných souborů.
Dvojka se používá úplně běžně na proudová data. Asi každý zná tar | gzip, dá se použít i ten nc na uložení na jiný stroj.
Trojka se používá, samozřejmně přehození jednoho pointeru je nejrychlejší způsob "předání" dat.
Každopádně, myšlenky Sali, Suckless nejsou úplně špatné (nesmí se brát dogmaticky a do extrému) v době, kdy dneska kdejaký programátor ke svému programu přibalí i celý framework, přičemž kdyby se zamyslel, tak by to šlo udělat mnohem úsporněji.
Jasne. No ty pipy jsou dost nesikovne kdyz chcete znat vysledek toho procesu (hodi se pro streamy). Takhle skoncite s tim, ze z kazde funkce udelate program a pak uz to muzete skladat v nejakym shellu protoze to bude tak jak tak silene pomaly. Tim dostanete dokonaly unix. Tak z tech programu udelate servisy a tim dostanete neco jako hurd. A pak si reknete, ze to je porad dost pomaly, tak to zacnete linkovat. A tim jsme na zas na zacatku, vse uz tu bylo...
Rozhraní se samozřejmě může měnit jenom rozšířením a kvůli backward kompatibilitě to bude udržovat i obsolete funkce. Takže to bude bobtnat o funkcionalitu, kterou už používá třeba jenom 1% klientů jak u widlí. Jak znám suckless, tak i ten unit test jsou řádky navíc a nevešli by se do limitu. Takže obsolete funkcionalitu nebude nikdo testovat, protože "je to tam už roky a nikdo do toho přece nesahal". Když se najde potenciálně nebezpečná funkce, nedá se jednoduše vyhodit a v systému budou zadní vrátka pro hackery...
Jedinou "výhodu" vidím v tom, že black hat si u multiaplikačního řešení může tu obsolete nebezpečnou funkci komfortně zavolat z CLI a nemusí se snížit na binární úroveň.
> To uz bylo vynalezeno, rika se tomu knihovny.
Myslim, ze tobe i Tomáši Crhonkovi uniká jedna hezka a podstatna vlastnost statickeho linkovani.
Tim, ze bude program staticky slinkovany, nehrozi jeho rozbiti, pokud nekdo zmeni nekterou cast systemu, at uz je to knihovna nebo program komunikujici pres rouru. Modularita systemu je pak zajistena na urovni zdrojovych kodu stejne, jak je tomu treba v jadre. Dokazu si predstavit pouziti takoveho reseni u systemu, ktere potrebuji mit zajistenou opravdu vysokou miru stability kvuli nakladnemu testovani, certifikacim, atd. napr. v prumyslu, letectvi/kosmonautice, medicine, ...
On to zase neni tak uplne neproveditelny napad. Windows de facto tak dnes funguji. Ty sice pouzivaji ve velkem DLL, ale temer kazda aplikace si taha svoje verze a kopie knihoven, ktere zabiraji misto v pameti tak jako tak, takze je to pomalu jak staticke linkovani.
ano rika se tomu winsxs a je to neco jako mapovaci tabulka (adresarova stromova struktura instalovanych aplikaci s hardlinkovanymi soubory konkretnich verzi knihoven)
a treba se k tomu casem nekdo dobere... dependency hell uz se resi treba tady: http://developerconference2014.sched.org/event/bdfb5804fb8e00691ec45f817d9102ce?iframe=no&w=100&sidebar=yes&bg=dark
„Statickým linkováním programy porostou ještě víc, protože každý program bude mít v sobě napevno kopii toho samýho, co ostatní programy.“
Pokud linkujete staticky, ve výsledné binárce zůstane (obvykle) jenom malá část kódu jinak běžně dynamické knihovny. Není žádný důvod, proč by kompilátor měl v binárce nechávat podprogramy, které nikdy aplikace nepoužije. Tedy statické linkování zalinkuje jen použitou podmnožinu knihovny.
Kromě toho statické linkování je efektivnější, protože je možné efektivnější volání, a také odpadají režie toho, že je to samostatná knihovna (např. nutnost vyřešit alokaci paměti zvlášť pro knihovnu a zvlášť pro hlavní program). A řada dalších věcí, optimalizace kompilátoru bude optimalizovat binárku jako celek, což bude efektivnější, než program a knihovna zvlášť.
Klidně se může stát, že když z jedné knihovny, která v dynamické podobě má 100 MB použije program pouze jednu malou funkci, že při statickém linkování se binárka zvětší o několik kilobajtů, protože není třeba linkovat to, co se nepoužívá.
Osobně si myslím, že glorifikace dynamických knihoven se přehání. Ušetření paměti není nic moc. Data v knihovnách stejně víceméně musí každý program duplikovat znovu a znovu. Sdílení kódu je možné jen za předpokladu stejném bázové adresy, na kterou je knihovna natáhnuta, což je zase silně proti bezpečnosti.
Ostatně už jenom to, že program linkuje dynamickou knihovnu přes nějaké API, je bezpečnostní díra jako hrom. Velké možnosti cracknout daný program.
Dynamická knihovna byla odjakživa především možnost prodávat kód třetích stran bez zdrojáků. A možnost vyvinout několika týmy samostatné knihovny, aniž by bylo nutné sdílet kódy. To byl účel dynamických knihoven především.
Sdílení dynamických knihoven různými aplikacemi je problematické, pokud se nejedná o čisté C. Obvykle u vyšších jazyků musí být program i knihovny zkompilovány stejnou verzí kompilátoru se stejnými optiony, jinak nastávají problémy.
Nehledě na to, že dynamické knihovny toho moc neumí, v podstatě jen sdílet tabulky skoků. Jakmile chcete mít v knihovně třídy, objekty, a další, pak musíte něco nadstavovat, což znamená další režii oproti statickému linkování a nebo minimáůně požadavek stejné verze kompilátoru, stejných optionů a dalšího. Není proto divu, že některé jazyky si raději vytvořily vlastní formát knihoven.
Já bych dynamické linkování neglorifikoval. Kdybych tvořil vlastní systém, určitě by statické linkování bylo přednostní a dynamické linkování by – pokud vůbec – bylo někde daleko vzadu. Chápu, že dogmata bez rozumného zdůvodnění, jako třeba dogma „dynamické knihovny = pouze velké dobro a mír po celém světě“ jsou hodně rozšířené, ale myslím si, že v reále je tomu skoro naopak.
Miloslav Ponkrác
> např. nutnost vyřešit alokaci paměti zvlášť pro knihovnu a zvlášť pro hlavní program
Proc? Knihovna i program prece mohou pouzivat volani stejne knihovny (libc) ...
> Sdílení kódu je možné jen za předpokladu stejném bázové adresy, na kterou je knihovna natáhnuta, což je zase silně proti bezpečnosti.
To je problem hlavne Windows. V Linuxu se knihovny natahuji na ruzne adresy, ale vzdy jsou data ulozena ve stejnem ramci, ale mapovavana na ruzne stranky, takze rezie 0.
> Ostatně už jenom to, že program linkuje dynamickou knihovnu přes nějaké API, je bezpečnostní díra jako hrom. Velké možnosti cracknout daný program.
Tenhle argument je zhruba tak validni jako: ,,Uz jenom to, ze program je nahrany v pameti je bezpocnostni dira jako hrom.''
„Proc? Knihovna i program prece mohou pouzivat volani stejne knihovny (libc) ...“
V tom případě ale knihovna nezávisí jen na API, ale také na dalších předpokladech.
Jako programátor používající knihovnu nemůžete předpokládat, že libvolný zdroj vzniklý v knihovně (alokovaná paměť, otevřený soubor, thread, síťové spojení, …) vznikla jakoukoli cestou, a jediné čisté řešení je nechat tento zdroj ukončit knihovnou.
Nehledě na tom, že alokace paměti je velmi drahá operace a funkce malloc není nejlevnější, a ani se nejlépe nechová vůči multithreadovým programům, atd. Mnohokrát je lépe si alokaci řídit sám.
„To je problem hlavne Windows. V Linuxu se knihovny natahuji na ruzne adresy, ale vzdy jsou data ulozena ve stejnem ramci, ale mapovavana na ruzne stranky, takze rezie 0.“
Řekněte prosím, že si děláte legraci. V opačném případě bychom museli přijmout teorii, že tomu vůbec nerozumíte.
„Nezní to moc jako legrace. Spíš to zní jako docela dobrý popis Position-Independent-Code. Uchází mi něco?“
Ano.
1) Position-independent-code má určitá omezení, tedy je méně efektivní, než normální kód, protože určité optimalizace nejsou možné.
2) Veškeré position-independent-code jde do háje, jakmile se vám v kódu či datech objeví jeden jediný pointer na libovolnou globální či statikcou funkci či data.. A to zejména v těch datech, o kterých v té legraci mluví.
A přiznejme si a neljme si čistého vína, ony se ty pointery v C i jinde docela používají.
Házení termínama typu „position-independent-code“ a dalšími abrakadabra slovy nevyřešíte nic, jen zmírňujete některé palčivé problémy používání dynamických knihovny, abyste za ně získal jiné problémy.
Toto uz je fakt moc.
(1) Efektivita PIC na AMD64 se diky relativnimu adresovani blizi nePIC kodu. Jediny problem je dvojita dereference u globalnich dat. To se da ozelet, vetsinou to nejde ani poznat.
(2) Sdilene knihovny jsou mapovany s MAP_PRIVATE... z cehoz plyne: (a) kod (i data) se sdili mezi jednotlivymi procesy, (b) pokud nekdo neco zmeni, je to osetreno pres copy-on-write
(3) Pouzivat v knihovne globalni (mutovatelne) hodnoty, stavy, atd. je prasarna.
(4) Vase argumentace je vylozene detinska. Ve vasem prispevku jste psal: "Sdílení kódu je možné jen za předpokladu stejném bázové adresy", kdyz jste byl upozornen na to, ze se veci maji jinak, jedine, co jste zvadl byly urazky...
ad 1) Obecně máte pravdu, prakticky to bývá dost marginální.
ad 2) Hm, mohl byste to nějak rozvést? K těmto účelům snad slouží Global Offset Table, ne?
Samozřejmě, že dynamické knihovny s sebou nesou různé kličky a nešikovnosti, ale otázka je, zda převažují výhody či nevýhody. A já bych se klonil spíše k té první variantě. Nakonec - autor se v naprosté většině případů může sám rozhodnout, jakým způsobem svůj výtvor sestaví.
"Házení termínama typu „position-independent-code“ a dalšími abrakadabra slovy nevyřešíte nic, jen zmírňujete některé palčivé problémy používání dynamických knihovny, abyste za ně získal jiné problémy."
Budete se divit, ale vyřešil jsem. Jedním anglickým termínem jsem z vás vyrazil argumety, o kterých se dá bavit, místo házení žvástů typu "vůbec tomu nerozumíte".
Mimochodem "zmírňování palčivých problémů výměnou za jiné problémy" je dobrý popis veškerého výzkumu a vývoje.
> V tom případě ale knihovna nezávisí jen na API, ale také na dalších předpokladech.
A je na tom neco divneho? Je normalni, ze knihovny zavisi na dalsich knihovnach, atd. Rika se tomu abstrakce.
> Mnohokrát je lépe si alokaci řídit sám.
A mnohokrat ne. Ale to neznamena, ze kazda knihovna si nutne musi delat vlastni spravu pameti, jak jste tvrdil.
> V opačném případě bychom museli přijmout teorii, že tomu vůbec nerozumíte.
A nejaky argument by se nenasel?
Efektivni volani muzete mit i u dynamickeho, jen to vyzaduje stejnou base nebo prijdete o sdileni kodu mezi programy.
Myslim ze dynamicke linkovani nezavadi nejakou dalsi bezpecnostni diru ktera by bez toho neexistovala.
Dalsi vyhoda dyn knihoven je pri vyvoji - nemusim po kazde zmene sestavovat cely program.
„Efektivni volani muzete mit i u dynamickeho, jen to vyzaduje stejnou base nebo prijdete o sdileni kodu mezi programy.“
A právě ta vedlejší věta začínající u Vás „jen“ není velmi často splněna.
Kromě toho volání je u dynamické knihovny vždy horší, než u statické. Obvykle se volání dynamické knihovny překládá přes mezivrstvu zvanou tabulka skoků.
Nicméně jakékoli přizpůsobení externímu API, v tomto případě dynamické knihovně, snižuje efektivitu. To je cena za abstrakci. V tuto chvíli navíc kompilátor nemůže příliš optimalizovat, jako to dělá u statického volání.
Nemluvě o tom, že se skáče do jiných stránek paměti, jak v kódu, tak v datech, což snižuje účinnost procesorové keše, atd.
Osobně vůbec nechápu obhajování dynamických knihoven jako super cesty. Mám pocit, že v linuxové komunitě je spíše soupis „věcí k věření“, které jsou „pravda“, bez ohledu na realitu. Vůbec mi to připomíná náboženství více, než selský rozum. Dynamické knihovny mají spousty ale a spousty problémů, a samozřejmě jsou případy, kdy jsou výhodné, a kdy je to cesta do pekel. Ale kněží a biskupové linuxu nepsali, že dynamické knihovny jsou jedině dobré, a tak to lidé bez hlubších znalostí papouškují jako fakt. A snaží se to prosadit stylem „100 × opakovaná lež se stává pravdou“.
Já jsem záměrně vytvořil protiváhu k názoru, že jedině dynamické knihovny a nic jiného.
Většina lidí neví, proč dělá co dělá. Většina lidí se to bezhlavě od někoho naučila, aniž ví o tom něco více.
Stačí si projít tuto diskusi a zjistíte, že lidí, kteří by o dynamických knihovnách versus statickém linkování věděli něco více, je minimum. Většina z nich tu jenom papouškuje to, že jejich víra (nepodložená jakýmikoli znalostmi) je udivuje, že by snad nebyly dynamické knihovny jen dobré a pouze dobré.
Netvrdím, že dynamické knihovny jsou pouze špatné. Ale jejich používání má mnoho problémů. Pro některá nasazení je to ok, pro jiná je lepší staticky linkovat.
Schválně si tu spočítejte příspěvky těch, kteří o tomto problému napíší něco hlubšího. Odečtěte „názor“ bez zdůvodnění a házení prázdnými termíny. A pochopíte, jak „vědomě“ a „podloženě“ je ten názor utvořen.
Pravda se nedá odhlasovat. Když seženete milión lidí, co budou tvrdit, že voda díky gravitaci teče vždy do kopce – budete mít jen milión lidí s mylným názorem, nic víc.
Vzhledem k tomu, ze na vetsine platforem, kde ma o nejakem Unixu smysl se bavit (vyznamna vyjimka je i386 pred amd64) je mozne adresovat jak data tak kod oproti PC/RIP, tak pro volani a pristup k datum uvnitr stejneho sdileneho objektu neni pouzivat mechanizmy jako GOT a PLT. Volani pres hranici sdileneho objektu nebyva az zas tak kriticke (navic ten skok pres PLT trampolinu je na dnesnich CPU daleko efektivnejsi nez to na prvni pohled vypada, prakticky vzdy to ma mensi overhead nez volani C++ virtualni metody), pristup k datum pres hranice sdilenych objektu vede na GOT ci spise obecne na problemy (rozumne vyuziti je inicializace neceho v .data na pointer do jine knihovny, coz ma vtipnou vlastnost, ze neni zrovna dvakrat portabilni, protoze nektere formaty sdilenych objektu maji dost omezene schopnosti vyjadrovani relokaci).
Jinak staticka bazova adresa (+ pripadna privatni relokace, v zavorce proto, ze opravdu existuji pouzivane OS, ktere pri kolizi reknou "smula, nejde to") a PIC nejsou jedine dve mozna reseni. Treba Windows 9x umi sdilet mezi procesy i ty relokovane stranky, princip je ten, ze dynamicky linker je v kernelu a umi relokaci v pripade potreby provest pri obsluze vypadku stranky (nechci rict, ze je to nejak "dobre" reseni, ale je to take mozne reseni).
Jeden z problemu je ze cely ten mechanizmus sdilenych objektu/dynamickych knihoven je omezen tim, ze minimalni granularita mapovani je stranka a tudiz aby se to vyplatilo musi byt ten sdileny objekt vetsi nez alespon tolik stranek kolik ma segmentu, coz muze byt pro opravdu jemne modularni veci malo (hezky priklad veci co v systemu normalne je jsou vselijake moduly do jazyku typu python/perl/ruby ktere jsou jenom tenky wrapper kolem C knihovny a maji jednotky az desitky kB, takovy hypoteticky priklad by bylo treba rozsekat glib nebo Qt po tridach do samostatnych knihoven).
Modulární i statický kernel mají identická vnitřní i userland rozhraní, takže to nehraje roli. Vámi popisovaný efekt je známý a vysvětluje se tím, že modulární ovladač (ve vašem případě zvuku) leží v paměti "daleko" od zbytku kernelu a na takovém 486 se holt s oním zbytkem pere o cache.
Jeste dodam, dalsi. Spousta lidi si mysli, ze dynamicke = .so (staticke = .a) jako Linuxu - tak jak to podoporuje format .ELF. Pokud ovsem pisete multiplatformni aplikaci tak zjistite, ze: