Operační systémy: Tři snadné kousky. Část 1: Úvod (překlad)

Úvod do operačních systémů

Ahoj, Habr! Rád bych vám představil sérii článků-překladů jedné zajímavé literatury — OSTEP. V tomto materiálu se dostatečně podrobně zabýváme fungováním unixových operačních systémů, konkrétně — prací s procesy, různými plánovači, pamětí a dalšími podobnými komponentami, které tvoří moderní OS. Originál všech materiálů můžete najít zde tady. Upozorňuji, že překlad byl proveden neprofesionálně (poměrně volně), ale doufám, že jsem zachoval celkový smysl.

Laboratorní práce k tomuto předmětu najdete zde:
— originál: pages.cs.wisc.edu/~remzi/OSTEP/Homework/homework.html
— originál: github.com/remzi-arpacidusseau/ostep-code
— moje osobní adaptace: github.com/bykvaadm/OS/tree/master/ostep

A můžete také nahlédnout na můj kanál na Telegramu =)

Fungování programu

Co se tedy děje, když běží nějaký program? Spuštěný program vykonává jednu jednoduchou činnost — provádí instrukce. Každou sekundu procesor načítá miliony a dokonce možná miliardy instrukcí z operační paměti, následně je dekóduje (například rozpozná, k jakému typu patří tyto instrukce) a vykonává je. Může to být sčítání dvou čísel, přístup do paměti, kontrola podmínky, skok na funkci a tak dále. Po dokončení jedné instrukce se procesor přesune k provedení další. A tak se instrukce provádějí jedna za druhou, dokud program nedokončí.
Tento příklad je samozřejmě zjednodušený — ve skutečnosti moderní hardware umožňuje procesoru vykonávat instrukce mimo pořadí, předvídat možné výsledky, provádět instrukce současně a používat podobné triky.

Von Neumannova architektura

Náš popsaný zjednodušený model fungování je podobný Von Neumannově modelu výpočtů. Von Neumann byl jedním z průkopníků počítačových systémů, také je jedním z autorů teorie her. Během práce programu se odehrává ještě spousta dalších událostí, běží mnoho dalších procesů a vedlejší logika, jejichž hlavním cílem je zjednodušení spuštění, běhu a údržby systému.
Existuje sada softwaru, která je zodpovědná za jednoduchost spouštění programů (nebo dokonce umožňuje spouštění více programů současně), umožňuje programům sdílet stejnou paměť a také interagovat s různými zařízeními. Tato sada softwaru se v zásadě nazývá operačním systémem a jeho úkolem je sledovat, aby systém fungoval správně a efektivně, a také usnadňovat správu tohoto systému.

Operační systém

Operační systém, zkráceně OS — komplex vzájemně propojených programů určených pro správu zdrojů počítače a organizaci interakce uživatele s počítačem..
OS dosahuje své efektivity především prostřednictvím nejdůležitější techniky — techniky virtualizace. OS interaguje s fyzickým zdrojem (procesorem, pamětí, diskem atd.) a transformuje ho do obecnější, schopnější a uživatelsky přívětivější podoby sebe samého. Proto lze pro obecné porozumění velmi hrubě přirovnat operační systém k virtuálnímu stroji.
Aby umožnila uživatelům dávat příkazy operačnímu systému a tím využívat schopnosti virtuálního stroje (jako je: spouštění programů, přidělování paměti, přístup k souborům atd.), operační systém poskytuje určitý rozhraní, nazývané API (aplikační programovací rozhraní), ke kterému je možné provádět volání. Typický operační systém umožňuje provést stovky systémových volání.
A nakonec, protože virtualizace umožňuje mnoha programům pracovat (tímto způsobem společně sdílet CPU) a zároveň přistupovat k jejich instrukcím a datům (čímž se paměť dělí), a také přistupovat k diskům (tímto způsobem společně používat vstupně-výstupní zařízení), operační systém se také nazývá správcem zdrojů. Každý procesor, disk a paměť jsou zdrojem systému a tak jednou z rolí operačního systému je správa těchto zdrojů, a to efektivně, spravedlivě nebo v závislosti na úkolu, pro který byl tento operační systém navržen.

Virtualizace CPU

Podívejme se na následující program:
(https://www.youtube.com/watch?v=zDwT5fUcki4&feature=youtu.be)

Operační systémy: Tři snadné kousky. Část 1: Úvod (překlad)

Nedělá nic zvláštního, v podstatě pouze volá funkci spin(), jejímž úkolem je cyklické kontrolování času a návrat poté, co uplynula jedna sekunda. Takto nekonečně opakuje řetězec, který uživatel předal jako argument.
Spustíme tento program a předáme mu argumentem znak „A“. Výsledek není příliš zajímavý — systém prostě vykonává program, který periodicky na obrazovku vypisuje znak „A“.
Nyní vyzkoušíme variantu, kdy je spuštěno několik instancí stejného programu, ale vypisujících různé písmena, aby bylo jasněji. V tomto případě bude výsledek poněkud odlišný. Přestože máme pouze jeden procesor, program se vykonává současně. Jak je to možné? Je to tak, že operační systém, s pomocí schopností hardwaru, vytváří iluzi. Iluzi, že v systému existuje několik virtuálních procesorů, přeměňující jeden fyzický procesor na teoreticky nekonečné množství a tím umožňující programům vypadat, jako by se vykonávaly současně. Taková iluze se nazývá Virtualizace CPU.
Takový obrázek vyvolává mnoho otázek, například pokud si přejí spustit několik programů současně, který z nich bude spuštěn? Na tuto otázku odpovídají „politiky“ operačního systému. Politiky se využívají na mnoha místech OS a odpovídají na podobné otázky, a také tvoří základní mechanismy, které OS realizuje. Odtud plyne i role OS jako správce prostředků.

Virtualizace paměti

Nyní se podívejme na paměť. Fyzický model paměti v moderních systémech se představuje jako pole bytů. Pro čtení z paměti je potřeba uvést adresu buňky, aby bylo možné k ní přistupovat. Pro zapsání nebo aktualizaci dat je také potřeba uvést data a adresu buňky, kam je zapisovat.
Přístupy do paměti probíhají neustále během provozu programu. Program uchovává v paměti celou svou strukturu dat a přistupuje k ní, provádějíc různé instrukce. Instrukce, jak se ukazuje, jsou také uchovány v paměti, proto k ní dochází při každém požadavku na následující instrukci.

Volání malloc()

Podíváme se na následující program, který alokuje oblast paměti pomocí volání malloc() (https://youtu.be/jnlKRnoT1m0):

Operační systémy: Tři snadné kousky. Část 1: Úvod (překlad)

Program provádí několik úkonů. Nejprve alokuje určité množství paměti (řádek 7), poté vypisuje adresu alokované buňky (řádek 9) a zapíše nulu do první slotu alokované paměti. Dále program vstupuje do cyklu, ve kterém inkrementuje hodnotu zapsanou v paměti na adrese ve proměnné "p". Také vypisuje identifikátor svého vlastního procesu. Identifikátor procesu je unikátní pro každý spuštěný proces. Když spustíme několik kopií, narazíme na zajímavý výsledek: V první řadě, pokud nic neuděláme a jednoduše spustíme několik kopií, adresy budou různé. Ale to neodpovídá naší teorii! Správně, protože v moderních distribucích je zapnuta funkce randomizace paměti. Pokud ji vypneme, získáme očekávaný výsledek — adresy paměti dvou současně běžících programů se budou shodovat.

Operační systémy: Tři snadné kousky. Část 1: Úvod (překlad)

Nakonec dostaneme to, že dvě nezávislé programy pracují se svými vlastními privátními adresními prostory, které jsou na druhou stranu mapovány operačním systémem do fyzické paměti. Proto použití adres paměti v rámci jednoho programu nijak neovlivňuje ostatní a každému programu se zdá, že má svůj vlastní kus fyzické paměti, zcela přidělený k jeho dispozici. Realita však je taková, že fyzická paměť je sdílený zdroj, jehož správu provádí operační systém.

Konzistence

Dalším důležitým tématem v rámci operačních systémů je konzistence. Tento termín se používá, když se jedná o problémy v systému, které mohou vzniknout při práci s mnoha věcmi najednou v rámci jednoho programu. Problémy konzistence se vyskytují i v samotném operačním systému. V předchozích příkladech s virtualizací paměti a procesoru jsme pochopili, že OS spravuje mnoho věcí zároveň — spouští první proces, poté druhý a tak dále. Jak se ukázalo, takové chování může vést k určitým problémům. Například moderní vícítková (multithreaded) programy zažívají takové potíže.

Podívejme se na následující program:

Operační systémy: Tři snadné kousky. Část 1: Úvod (překlad)

Program ve funkci main vytváří dva vlákna pomocí volání Pthread_create(). V tomto příkladu lze na vlákno pohlížet jako na funkci spuštěnou ve stejném paměťovém prostoru vedle dalších funkcí, přičemž počet současně spuštěných funkcí je jasně větší než jedna. V tomto příkladu každé vlákno začíná a provádí funkci worker(), která na oplátku pouze inkrementuje proměnnou,.

. Spustíme tuto aplikaci s argumentem 1000. Jak už asi tušíte, výsledkem by mělo být 2000, protože každé vlákno inkrementovalo proměnnou 1000krát. Ale všechno není tak jednoduché. Zkusíme spustit aplikaci s číslem opakování o řád více.

Operační systémy: Tři snadné kousky. Část 1: Úvod (překlad)

Když zadáme číslo, například 100000, očekáváme, že na výstupu uvidíme číslo 200000. Nicméně, když spustíme číslo 100000 několikrát, nejenže neuvidíme správnou odpověď, ale dostaneme i různé nesprávné odpovědi. Rozluštění spočívá v tom, že pro zvýšení čísla jsou potřeba tři operace — načtení čísla z paměti, inkrementace a následné zapsání čísla zpět. Protože všechny tyto instrukce nejsou prováděny atomárně (vše najednou), mohou nastávat takové podivné věci. Tento problém se v programování nazývá race condition — stav závodu. Kdy neznámé síly v neznámém okamžiku mohou ovlivnit provádění jakýchkoliv vašich operací.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster