Úvod do operačných systémov
Ahoj, Habr! Chcem vám predstaviť sériu článkov-prechodov zaujímavej literatúry - OSTEP. V tomto materiáli sa dosť hlboko skúma fungovanie unixových operačných systémov, konkrétne práca s procesmi, rôznymi plánovačmi, pamäťou a inými podobnými komponentmi, ktoré tvoria moderný OS. Originál všetkých materiálov si môžete pozrieť tu . Prosím berte na vedomie, že preklad bol vykonaný neprofesionálne (dosť voľne), ale dúfam, že som zachoval celkový zmysel.
Laboratórne práce na tomto predmete nájdete tu:
- originál:
- originál:
- moja osobná adaptácia:
A môžete sa pozerať aj na môj kanál v =)
Práca programu
Čo sa deje, keď sa spustí akýkoľvek program? Spustený program vykonáva jednu jednoduchú úlohu - vykonáva inštrukcie. Každú sekundu procesor z operačnej pamäte vyberá milióny, ba dokonca možno miliardy inštrukcií, ktoré následne dekóduje (napríklad rozpozná, k akému typu patria tieto inštrukcie) a vykonáva ich. Môže ísť o sčítanie dvoch čísel, prístup do pamäte, kontrolu podmienky, prechod na funkciu atď. Po dokončení jednej inštrukcie procesor prechádza k vykonaniu ďalšej. A takto inštrukcia za inštrukciou, vykonávajú sa, kým program neskončí.
Tento príklad je samozrejme zjednodušený - v skutočnosti sú moderné komponenty schopné vykonávať inštrukcie neporiadne, predpovedať možné výsledky, vykonávať inštrukcie súčasne a podobné triky na urýchlenie práce procesora.
Fón-Nejmanova výpočtová modelka
Popísaná zjednodušená forma práce je podobná Fón-Nejmanovej modelke výpočtov. Fón-Nejman bol jedným z priekopníkov počítačových systémov, takisto je jedným z autorov teórie hier.. Počas práce programu sa odohráva množstvo ďalších udalostí, pracuje mnoho iných procesov a externé logiky, ktorých hlavný cieľ je zjednodušiť spustenie, fungovanie a údržbu systému.
Existuje sada softvéru, ktorá je zodpovedná za jednoduchosť spúšťania programov (alebo dokonca umožňuje spúšťať niekoľko programov súčasne). Umožňuje programom zdieľať rovnakú pamäť a tiež interagovať s rôznymi zariadeniami. Takáto sada softvéru sa v podstate nazýva operačný systém a jeho úlohou je sledovať, aby systém fungoval správne a efektívne, a zároveň zabezpečiť jednoduchú správu tohto systému.
Operačný systém
Operačný systém, skrátene OS, je komplex vzájomne prepojených programov, určených na riadenie zdrojov počítača a organizáciu interakcie používateľa s počítačom..
OS dosahuje svoju efektívnosť predovšetkým prostredníctvom najdôležitejšej techniky — techniky virtualizácie.OS interaguje s fyzickými zdrojmi (procesorom, pamäťou, diskom a podobne) a transformuje ich na všeobecnejšiu, s širšími možnosťami a jednoduchšiu na používanie formu samého seba. Preto pre celkové pochopenie môžeme veľmi hrubo porovnať operačný systém s virtuálnym strojom.
Aby sme umožnili používateľom vydávať príkazy operačnému systému a týmto spôsobom využívať možnosti virtuálneho stroja (ako: spúšťanie programov, prideľovanie pamäte, prístup k súborom a podobne), operačný systém poskytuje určitý rozhranie, nazývané API (application programming interface), ku ktorému je možné robiť volania (call). Typický operačný systém umožňuje vykonať stovky systémových volaní.
A nakoniec, keďže virtualizácia umožňuje množstvu programov fungovať (týmto spôsobom zdieľajú CPU) a súčasne pristupovať k ich inštrukciám a údajom (čím zdieľajú pamäť), ako aj pristupovať k diskom (čím zdieľajú vstupno-výstupné zariadenia), operačný systém sa nazýva aj správcom zdrojov. Každý procesor, disk a pamäť sú zdrojmi systému, a tak jednou z úloh operačného systému sa stáva efektívne a spravodlivé riadenie týchto zdrojov, alebo naopak, v závislosti od úlohy, pre ktorú bol tento operačný systém vyvinutý.
Virtualizácia CPU
Pozrime sa na nasledujúci program:
(https://www.youtube.com/watch?v=zDwT5fUcki4&feature=youtu.be)

Nevykonáva žiadne špeciálne akcie, vlastne to, čo robí, je volanie funkcie spin(), ktorej úlohou je cyklické overovanie času a návrat, potom čo uplynula jedna sekunda. Týmto spôsobom nekonečne opakuje reťazec, ktorý používateľ poskytol ako argument.
Spustíme tento program a odovzdáme mu ako argument znak “A”. Výsledok nie je veľmi zaujímavý — systém jednoducho vykonáva program, ktorý periodicky zobrazuje znak “A”.
Teraz vyskúšajme variant, keď je spustených viac inštancií toho istého programu, ale zobrazujú rôzne písmená, aby to bolo jasnejšie. V tomto prípade bude výsledok trochu iný. Napriek tomu, že máme jeden procesor, program sa vykonáva súčasne. Ako je to možné? Systém operácií, s pomocou hardvérových možností, vytvára ilúziu. Ilúziu toho, že v systéme existuje niekoľko virtuálnych procesorov, pretvárajúc jeden fyzický procesor na teoreticky nekonečný počet a tým umožňuje, aby sa programy na pohľad vykonávali súčasne. Takú ilúziu nazývame Virtualizácia CPU.
Takýto obraz vyvoláva množstvo otázok, napríklad, ak niekoľko programov chce spustiť súčasne, ktorý z nich bude vlastne spustený? Za túto otázku sú zodpovedné “politiky” operačného systému. Politiky sa používajú na mnohých miestach OS a odpovedajú na podobné otázky, a takisto sú základnými mechanizmami, ktoré OS realizuje. Odtiaľ aj úloha OS ako správcov zdrojov.
Virtualizácia pamäte
Teraz si preberme pamäť. Fyzický model pamäte v moderných systémoch sa predstavuje ako pole bajtov. Na čítanie z pamäte je potrebné uviesť adresu bunky, aby sme sa k nej dostali. Na zapisovanie alebo aktualizáciu údajov je takisto potrebné uviesť údaje a adresu bunky, kam ich zapíšeme.
Prístup k pamäti prebieha neustále v procese práce programu. Program uchováva v pamäti celú svoju dátovú štruktúru a pristupuje k nej, vykonávajúc rôzne inštrukcie. Inštrukcie sú medzičasom taktiež uložené v pamäti, takže prístup k nej prebieha aj pri každom ďalšom požiadavku na nasledujúcu inštrukciu.
Volanie malloc()
Zvážme nasledujúci program, ktorý prideli oblasť pamäte pomocou volania malloc() (https://youtu.be/jnlKRnoT1m0):

Program robí niekoľko vecí. Po prvé, pridelí určitý objem pamäte (riadok 7), potom vypíše adresu prideleného bloku (riadok 9), zapíše nula do prvého slotu pridelené pamäte. Následne program vstúpi do cyklu, v ktorom inkrementuje hodnotu zapísanú v pamäti na adrese v premennej "p". Taktiež vypisuje identifikátor procesu samého seba. Identifikátor procesu je jedinečný pre každý spustený proces. Ak spustíme niekoľko kópií, narazíme na zaujímavý výsledok: V prvom prípade, ak neurobíme nič a jednoducho spustíme niekoľko kópií, adresy budú rôzne. Ale to nevyhovuje našej teórii! Správne, pretože v moderných distribúciách je predvolene zapnutá funkcia náhodného rozdelenia pamäte. Ak ju vypneme, dostaneme očakávaný výsledok — adresy pamäte dvoch súčasne bežiacich programov sa budú zhodovať.

Nakoniec sa ukazuje, že dva nezávislé programy pracujú so svojimi vlastnými súkromnými adresnými priestormi, ktoré sú sprístupnené systémom na fyzickú pamäť.Preto používanie adries pamäte v rámci jedného programu nijako neovplyvní iné a každému programu sa zdá, že má svoj vlastný kúsok fyzickej pamäte plne k dispozícii. Realita je však taká, že fyzická pamäť je zdieľaný zdroj, ktorého správu vykonáva operačný systém.
Konzistencia
Ďalšou dôležitou témou v rámci operačných systémov je konzistencia. Tento termín sa používa, keď ide o problémy v systéme, ktoré môžu vzniknúť pri práci s viacerými vecami naraz v rámci jedného programu. Problémy s konzistenciou vznikajú aj v samotnom operačnom systéme. V predchádzajúcich príkladoch s virtualizáciou pamäte a procesora sme pochopili, že OS spravuje mnohé veci naraz - spúšťa prvý proces, potom druhý a tak ďalej. Ako sa ukázalo, takéto správanie môže viesť k niektorým problémom. Napríklad moderné viacvláknové programy zažívajú tieto ťažkosti.
Pozrime sa na nasledujúci program:

Program v hlavnej funkcii vytvára dva vlákna pomocou volania Pthread_create(). V tomto príklade je možné vnímať vlákno ako funkciu, ktorá beží v jednom pamäťovom prostredí spolu s inými funkciami, pričom počet spustených funkcií je jednoznačne viac ako jedna. V tomto príklade každé vlákno sa spúšťa a vykonáva funkciu worker(), ktorá jednoducho inkrementuje premennú,.
. Spustíme túto program s argumentom 1000. Ako ste už mohli uhádnuť, výsledkom by malo byť 2000, pretože každé vlákno inkrementovalo premennú 1000-krát. Avšak všetko nie je také jednoduché. Pokúsme sa spustiť program s počtom opakovaní poriadne väčším.

Pri podaní čísla, napríklad 100000, očakávame vidieť na výstupe číslo 200000. Avšak, keď spustíme číslo 100000 niekoľkokrát, nielenže neuvidíme správnu odpoveď, ale dostaneme aj rôzne nesprávne odpovede. Riešenie spočíva v tom, že na zvýšenie čísla sú potrebné tri operácie — vyťahanie čísla z pamäte, inkrementácia a potom zapísanie čísla späť. Keďže všetky tieto inštrukcie sa nevykonávajú atomicky (všetky súčasne), môžu sa diať také zvláštne veci. Tento problém sa nazýva v programovaní race condition — stav súťaže. Keď neznáme sily v neznámom momente môžu ovplyvniť vykonanie akýchkoľvek vašich operácií.
Zdroj: habr.com
