Úvod do operačných systémov
Ahoj, Habr! Chcem vám predstaviť sériu článkov-prekladu zaujímavej literatúry, ktorú považujem za zaujímavú — OSTEP. V tomto materiáli sa podrobne zaoberá fungovaním unixových operačných systémov, konkrétne prácou 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:
Ďalšie časti:
A môžete sa pozerať aj na môj kanál v =)
Pozrime sa na najzákladnejšiu abstrakciu, ktorú operačný systém poskytuje používateľom: proces. Definícia procesu je celkom jednoduchá — je to bežiaci program. Program sám o sebe je neživá vec, nachádzajúca sa na disku — je to súbor pokynov a možno nejakých statických údajov, čakajúcich na okamih spustenia. To je presne to, čo operačný systém berie tieto bajty a spúšťa ich, premení program na niečo užitočné.
Najčastejšie chcú používatelia spúšťať viac ako jeden program súčasne, napríklad môžete spustiť vo vašom notebooku prehliadač, hru, mediálny prehrávač, textový editor a podobne. V skutočnosti typický systém môže spúšťať desiatky a stovky procesov súčasne. Tento fakt uľahčuje používanie systému, nikdy sa nemusíte obávať, či je CPU voľný, jednoducho spúšťate programy.
Odtiaľ vyplýva problém: ako zabezpečiť ilúziu mnohých CPU? Ako môže operačný systém vytvoriť ilúziu prakticky nekonečného počtu CPU, aj keď máte len jeden fyzický CPU?
Operačný systém vytvára túto ilúziu prostredníctvom virtualizácie CPU. Spúšťaním jedného procesu, potom jeho zastavením, spúšťaním ďalšieho procesu a tak ďalej, môže operačný systém udržiavať ilúziu, že existuje množstvo virtuálnych CPU, hoci v skutočnosti to bude jeden alebo niekoľko fyzických procesorov. Táto technika sa nazýva delenie CPU podľa času. Táto technika umožňuje používateľom spúšťať toľko súbežných procesov, koľko chcú. Cenu takejto voľby je výkon – pretože ak CPU delí niekoľko procesov, každý proces bude spracovávaný pomalšie.
Na realizáciu virtualizácie CPU, a najmä na to, aby to bolo možné robiť dobre, operačný systém potrebuje aj nízkolevelovú a vysokolevelovú podporu. Nízkoúrovňová podpora sa nazýva mechanizmy — to sú nízkoúrovňové metódy alebo protokoly, ktoré implementujú potrebnú časť funkčnosti. Príkladom takejto funkčnosti je kontextové prepínanie, ktoré umožňuje OS zastaviť jednu aplikáciu a spustiť na procesore druhú aplikáciu. Toto časové rozdelenie je implementované vo všetkých moderných OS.
Na vrchole týchto mechanizmov sa nachádza istá logika, zakomponovaná v OS, vo forme „politík“. Politika — je to istý algoritmus prijímania rozhodnutí operačným systémom. Takéto politiky napríklad rozhodujú, ktorú aplikáciu treba spustiť (zo zoznamu príkazov) ako prvú. Tak napríklad túto úlohu vyrieši politika, nazývaná plánovač (scheduling policy) , a pri výbere rozhodnutia sa bude riadiť takými údajmi ako: história spustenia (ktorá aplikácia bola spustená najdlhšie za poslednú minútu), akú záťaž vykonáva daný proces (aké typy aplikácií boli spustené), metriky výkonu (či je systém optimalizovaný na interaktívnu interakciu alebo na priepustnosť) a tak ďalej.
Abstrakcia: proces
Abstrakcia fungujúcej aplikácie, vykonávaná operačným systémom, je to, čo nazývame proces. Ako už bolo spomenuté, proces je proste fungujúca aplikácia v akomkoľvek okamžiku. Aplikácia, s pomocou ktorej môžeme získať súhrnné informácie z rôznych zdrojov systému, a ku ktorým sa táto aplikácia obracia alebo ktoré táto aplikácia zasahuje v priebehu svojho vykonávania.
Na pochopenie zložiek procesu je potrebné chápať stavy systému: čo aplikácia môže čítať alebo meniť počas svojej činnosti. V akomkoľvek okamihu je potrebné chápať, ktoré prvky systému sú dôležité pre vykonávanie aplikácie.
Jedným z očividných prvkov stavu systému, ktoré proces zahŕňa, je pamäť. Inštrukcie sa nachádzajú v pamäti. Údaje, ktoré aplikácia číta alebo zapisuje, sa tiež nachádzajú v pamäti. Tým pádom, pamäť, ktorú proces môže adresovať (takzvaný adresný priestor), je súčasťou procesu.
Súčasťou stavu systému sú aj registre. Množstvo inštrukcií je zameraných na zmenu hodnôt registrov alebo na čítanie ich hodnôt, a tak sa registre stávajú dôležitou súčasťou činnosti procesu.
Je potrebné poznamenať, že stav stroja sa tiež vytvára z niektorých špeciálnych registrov. Napríklad, IP — ukazovateľ inštrukcie — ukazuje na inštrukciu, ktorú program momentálne vykonáva. Ďalej existuje ukazovateľ zásobníka a s ním súvisiaci ukazovateľ rámca, ktoré sa používajú na riadenie: parametrov funkcií, lokálnych premenných a adries návratu.
Nakoniec programy často pristupujú k ROM (permanentnému pamäťovému zariadeniu). Tieto informácie o "I/O" (vstupe-výstupe) by mali obsahovať zoznam súborov, ktoré proces momentálne otvoril.
API procesu
Aby sme zlepšili pochopenie fungovania procesu, preskúmámo príklady systémových volaní, ktoré by mali byť zahrnuté v akomkoľvek rozhraní operačného systému. Tieto API sú v tej či onej forme dostupné na akomkoľvek OS.
● Vytvoriť (vytvorenie): V OS by mala existovať nejaká metóda, ktorá umožňuje vytváranie nových procesov. Keď zadáte príkaz do terminálu alebo spustíte aplikáciu dvojitým kliknutím na ikonu, pošle sa žiadosť OS o vytvorenie nového procesu a následné spustenie uvedeného programu.
● Odstránenie: Keď existuje rozhranie na vytvorenie procesu, OS by mala tiež poskytovať možnosť núteného zrušenia procesu. Väčšina programov sa prirodzene spustí a končí sama počas ich vykonávania. Inak by chcel užívateľ mať možnosť ich zabiť, a preto by rozhranie na zastavenie procesu nebolo na škodu.
● Čakať (čakanie): Niekedy je užitočné počkať na dokončenie procesu, preto sú k dispozícii niektoré rozhrania, ktoré poskytujú možnosť čakania.
● Rôzna kontrola (rôzne riadenie): Okrem zabíjania a čakania na proces existujú aj ďalšie rôzne kontrolné metódy. Napríklad väčšina OS poskytuje možnosť zmrazenia procesu (pozastavenie jeho vykonávania na určitý čas) a následného obnovenia (pokračovanie vo vykonávaní).
● Stav (stav): Existujú rôzne rozhrania na získanie určitých informácií o stave procesu, ako je dĺžka jeho chodu alebo v akom stave sa práve nachádza.

Vytvorenie procesu: detaily
Jedna zaujímavá vec je, ako sa programy transformujú na procesy. Najmä, ako operačný systém spúšťa a vykonáva program. Ako sa konkrétne vytvára proces.
Na prvom mieste musí operačný systém načítať kód programu a statické dáta do pamäte (do adresného priestoru procesu). Programy sa zvyčajne ukladajú na disku alebo pevnom disku v určitom spustiteľnom formáte. Tým pádom proces načítania programu a statických dát do pamäte vyžaduje od operačného systému schopnosť prečítať tieto bajty z disku a umiestniť ich niekde do pamäte.
V raných operačných systémoch sa proces načítania vykonával netrpezlivo (eagerly), to znamená, že kód sa načítal do pamäte celý pred spustením programu. Moderné operačné systémy to robia lenivo (lazily), teda načítavajú kúsky kódu alebo dát iba vtedy, keď ich program potrebuje počas svojho vykonávania.
Po načítaní kódu a statických dát do pamäte musí operačný systém vykonať ešte niekoľko ďalších vecí predtým, než spustí proces. Musí byť uvoľnené určité množstvo pamäte pre zásobník. Programy používajú zásobník pre lokálne premenné, parametre funkcií a adresy návratu.. Operačný systém uvoľňuje túto pamäť a prideľuje ju procesu. Zásobník môže byť tiež prideľovaný s určitými argumentmi, konkrétne naplňuje parametre funkcie main(), ako je pole argc a argv.
Operačný systém môže tiež uvoľniť určité množstvo pamäte pre haldu (heap) programu. Halda sa používa programami pre explicitne požadované dynamicky alokované dáta.. Programy požadujú tento priestor volaním funkcie malloc() a explicitne ho uvoľňujú volaním funkcie free()Hromada je potrebná pre takéto dátové štruktúry ako: prepojené zoznamy, hash tabuľky, stromy a iné. Na začiatku je pre hromadu pridelené malé množstvo pamäte, ale časom môže hromada počas behu programu požiadať o väčšie množstvo pamäte prostredníctvom volania malloc() cez knižničné API. Prevádzkový systém je zapojený do procesu pridelenia väčšieho množstva pamäte, aby pomohol uspokojiť tieto požiadavky.
Prevádzkový systém tiež vykonáva úlohy inicializácie, najmä tie, ktoré sa týkajú vstupu a výstupu. Napríklad v UNIX systémoch má každý proces predvolene 3 otvorené súborové deskriptory pre štandardný vstup, výstup a chyby. Tieto deskriptory umožňujú programom čítať vstup z terminálu a tiež vypisovať informácie na obrazovku.
Takto, načítaním kódu a statických údajov do pamäte, vytváraním a inicializovaním zásobníka, a vykonávaním inej práce týkajúcej sa výkonu vstupno-výstupných úloh, OS pripravuje podmienky na vykonávanie procesu. Nakoniec zostáva posledná úloha: spustiť program na vykonávanie cez jeho vstupný bod, nazývaný funkcia main(). Prechodom k vykonaniu funkcie main() OS odovzdáva riadenie CPU novo vytvorenému procesu, čím sa program začína vykonávať.
Stav procesu
Teraz, keď máme predstavu o tom, čo je proces a ako sa vytvára, vymenovať stavy procesu, v ktorých sa môže nachádzať. V najjednoduchšej forme môže byť proces v jednom z týchto stavov:
● Running. V bežiacom stave je proces vykonávaný na procesore. To znamená, že dochádza k vykonávaniu inštrukcií.
● Pripravené. V stave pripravenosti je proces pripravený spustiť, ale z nejakých dôvodov OS ho v danom okamihu nevykonáva.
● Blocked. V zablokovanom stave proces vykonáva nejaké operácie, ktoré mu neumožňujú byť pripraveným na vykonanie, kým sa neudeje nejaká udalosť. Jeden z bežných príkladov - keď proces inicializuje operáciu IO, stáva sa zablokovaným, a tak môže nejaký iný proces využiť procesor.

Predstavte si tieto stavy ako graf. Ako môžeme vidieť na obrázku, stav procesu sa môže meniť medzi RUNNING a READY na základe rozhodnutia OS. Keď sa stav procesu zmení z READY na RUNNING, znamená to, že proces bol naplánovaný. Naopak, ak je pozastavený z plánovania. V momente, keď sa proces stane BLOCKED, napríklad keď iniciuje operáciu IO, OS ho drží v tomto stave až do nastania nejakého udalosti, napríklad dokončenia IO. V tomto momente dôjde k prechodu do stavu READY a môže okamžite prejsť do stavu RUNNING, ak sa tak rozhodne OS.
Pozrime sa na príklad toho, ako dva procesy prechádzajú týmito stavmi. Na začiatok si predstavme, že oba procesy sú spustené a každý využíva iba CPU. V tomto prípade budú ich stavy vyzerať nasledovne.

V nasledujúcom príklade prvý proces po určitom čase práce požiada o IO a prejde do stavu BLOCKED, pričom poskytne druhému procesu možnosť spustenia (OBR. 1.4). OS vidí, že proces 0 nevyužíva CPU a spúšťa proces 1. Počas vykonávania procesu 1 sa IO dokončí a stav procesu 0 sa zmení na READY. Nakoniec proces 1 skončil a po jeho skončení sa proces 0 spúšťa, vykonáva a končí svoju prácu.

Štruktúra dát
OS je sama o sebe programom, a rovnako ako akýkoľvek iný program má niektoré kľúčové štruktúry dát, ktoré sledujú rôzne relevantné kusy informácií. Na sledovanie stavu každého procesu bude OS udržiavať nejaký process list pre všetky procesy v stave READY a nejaké ďalšie informácie na sledovanie procesov, ktoré sú momentálne vykonávané. OS tiež musí sledovať a zablokované procesy. Po dokončení IO je OS povinná prebudiť potrebný proces a previesť ho do stavu pripravenosti na spustenie.
Tak, napríklad, OS musí uchovať stav registrov procesora. V momente zastavenia procesu sa stav registrov uloží do adresného priestoru procesu, a pri pokračovaní jeho práce — obnoví hodnoty registrov a takto pokračuje vo vykonávaní tohto procesu.
Okrem stavov ready, blocked, running existujú aj niektoré iné stavy. Niekedy môže byť proces pri vytváraní v stave INIT. Nakoniec môže byť proces umiestnený do stavu FINAL, keď už skončil, ale informácie o ňom ešte neboli vymazané. V systémoch UNIX sa tento stav nazýva proces-zombie. Tento stav je užitočný v prípadoch, keď rodičovský proces chce zistiť návratový kód potomka, napríklad obyčajne 0 signalizuje úspešné dokončenie a 1 chybu, avšak programátori môžu vytvárať ďalšie návratové kódy, ktoré signalizujú rôzne problémy. Pri dokončení rodičovský proces vykonáva posledný systémový volanie, napríklad wait(), aby počkal na dokončenie práce procesu-potomka a signalizoval OS, že je možné vyčistiť akékoľvek údaje súvisiace so skončeným procesom.

Kľúčové body prednášky:
● Proces — hlavná abstrakcia pracujúceho programu v OS. V akomkoľvek momente času môže byť proces popísaný podľa jeho stavu: obsahom pamäte vo svojom adresnom priestore, obsahom registrov CPU, vrátane instruction pointer a stack pointer, ako aj informáciou o IO, napríklad otvorenými súbormi, ktoré sa čítajú alebo zapisujú.
● API procesu sú zvyčajne systémové volania, ktoré môžu programy vykonávať vo vzťahu k procesom. Zvyčajne ide o volania na vytvorenie, odstránenie alebo iné.
● Proces sa nachádza v jednom z mnohých stavov, vrátane running, ready, blocked. Rôzne udalosti, ako plánovanie, vylúčenie z plánovania alebo čakanie môžu previesť stav procesu z jedného do druhého.
● Zoznam procesov obsahuje informácie o všetkých procesoch v systéme. Každý záznam v ňom sa nazýva process control block, ktorý je v skutočnosti štruktúrou obsahujúcou všetky potrebné informácie o konkrétnom procese.
Zdroj: habr.com
