Introduktion till operativsystem
Hej, Habr! Jag vill presentera för er en serie översĂ€ttningsartiklar av en intressant litteratur â OSTEP. I detta material behandlas djupgĂ„ende hur unix-liknande operativsystem fungerar, nĂ€mligen arbetet med processer, olika schemalĂ€ggare, minne och andra liknande komponenter som utgör ett modernt OS. Originalet av allt material kan du se hĂ€r . Observera att översĂ€ttningen Ă€r utförd oprofessionellt (relativt fritt), men jag hoppas att jag har bevarat den övergripande meningen.
Laborationsarbeten för detta Àmne kan hittas hÀr:
Andra delar:
Och du kan ocksÄ kolla in min kanal pÄ =)
Introduktion till schemalÀggaren
KÀrnan i problemet: Hur man utvecklar en schemalÀggarpolicy
Hur bör de grundlÀggande ramverken för schemalÀggarpolicyer utvecklas? Vilka bör vara nyckelförutsÀttningarna? Vilka mÀtvÀrden Àr viktiga? Vilka grundlÀggande tekniker anvÀndes i tidiga datorsystem?
Arbetslastantaganden
Innan vi diskuterar möjliga policyer, lÄt oss först göra nÄgra förenklade avstickare om de processer som körs i systemet, tillsammans kallade arbetslast. Att definiera arbetslasten Àr en kritisk del av att bygga policyer, och ju mer du vet om lasterna, desto bÀttre policy kan du skriva.
LÄt oss göra följande antaganden om processerna som körs i systemet, ibland Àven kallade jobs (uppgifter). Praktiskt taget alla dessa antaganden Àr orealistiska, men de behövs för att frÀmja tankegÄngen.
- Varje uppgift körs under samma tid,
- Alla uppgifter sÀtts samtidigt,
- En inlagt uppgift körs till den Àr fÀrdig,
- Alla uppgifter anvÀnder endast CPU,
- Körtiden för varje uppgift Àr kÀnd.
SchemalÀggarens mÀtvÀrden
Förutom vissa antaganden om belastningen behövs ocksÄ ett verktyg för att jÀmföra olika schemalÀggarpolicyer: schemalÀggarens mÀtvÀrden. En mÀtvÀrde Àr helt enkelt ett mÄtt pÄ nÄgot. Det finns ett antal mÀtvÀrden som kan anvÀndas för att jÀmföra schemalÀggare.
Som exempel ska vi anvÀnda en mÀtning som kallas vÀndtid (turnaround time). VÀndtiden för en uppgift definieras som skillnaden mellan tiden dÄ uppgiften avslutas och tiden dÄ uppgiften anlÀnde till systemet.
Tturnaround=TcompletionâTarrival
Eftersom vi antog att alla uppgifter anlÀnde samtidigt, sÄ Àr Ta=0 och dÀrmed Tt=Tc. Detta vÀrde kommer naturligtvis att Àndras nÀr vi Àndrar de ovanstÄende antagandena.
En annan mÀtvÀrde Àr rÀttvisa (fairness). Prestanda och rÀttvisa Àr ofta motstridiga egenskaper inom schemalÀggning. Till exempel kan en schemalÀggare optimera prestanda, men pÄ bekostnad av att andra uppgifter fÄr vÀnta, vilket dÀrmed minskar rÀttvisan.
FĂRST IN FĂRST UT (FIFO)
Den mest grundlÀggande algoritmen som vi kan implementera kallas FIFO eller first come (in), first served (out). Denna algoritm har flera fördelar: den Àr mycket enkel att implementera och den passar alla vÄra antaganden, vilket gör att den fungerar ganska bra.
LÄt oss titta pÄ ett enkelt exempel. Anta att 3 uppgifter stÀllts samtidigt. Men anta att uppgift A kom lite tidigare Àn de andra, sÄ den kommer att stÄ först i kö, precis som B i förhÄllande till C. LÄt oss anta att var och en av dem kommer att utföras pÄ 10 sekunder. Vad blir dÄ den genomsnittliga tiden för att slutföra dessa uppgifter?

Genom att rĂ€kna vĂ€rdena â 10+20+30 och dela med 3 fĂ„r vi den genomsnittliga tiden för programmet som Ă€r 20 sekunder.
Nu ska vi försöka Àndra vÄra antaganden. Speciellt antagande 1 och sÄ vi inte lÀngre antar att varje uppgift tar lika lÄng tid. Hur kommer FIFO att fungera denna gÄng?
Det visar sig att olika exekveringstider för uppgifter har en extremt negativ pÄverkan pÄ FIFO-algoritmens produktivitet. Anta att uppgift A kommer att exekveras i 100 sekunder, medan bÄde B och C fortfarande kommer att vara 10 sekunder var.

Som man kan se frÄn bilden, kommer den genomsnittliga tiden för systemet att bli (100+110+120)/3=110. Denna effekt kallas karavaneffekten, dÀr vissa kortvariga resurskonsumenter stÄr i kö efter en tung konsument. Det liknar en kö i en livsmedelsbutik, dÀr du stÄr bakom en kund med en full kundvagn. Den bÀsta lösningen pÄ problemet Àr att försöka byta kassa eller att slappna av och andas djupt.
Kortaste jobb först
Finns det nĂ„got sĂ€tt att lösa en sĂ„dan situation med tunga processer? SjĂ€lvklart. En annan typ av schemalĂ€ggning kallasKortaste jobb först (SJF). Dess algoritm Ă€r ocksĂ„ ganska primitiv â som namnet antyder, kommer de kortaste uppgifterna att startas först en efter en.

I det hÀr exemplet kommer resultatet av att köra samma processer att förbÀttra den genomsnittliga genomströmningstiden för programmen och den kommer att vara 50 istÀllet för 110, vilket Àr nÀstan 2 gÄnger bÀttre.
SÄledes, baserat pÄ antagandet att alla uppgifter anlÀnder samtidigt, verkar SJF-algoritmen vara den mest optimala. Men vÄra antaganden verkar fortfarande inte realistiska. Denna gÄng Àndrar vi antagande 2 och förestÀller oss att uppgifter kan anlÀnda nÀr som helst, snarare Àn alla samtidigt. Vilka problem kan detta leda till?

LÄt oss förestÀlla oss att uppgift A (100s) anlÀnder först och pÄbörjar körningen. Vid tidpunkten t=10 anlÀnder uppgifter B, C, som var och en tar 10 sekunder. DÀrmed berÀknas genomsnittlig exekveringstid till (100+(110-10)+(120-10))/3 = 103. Vad skulle schemalÀggaren kunna göra för att förbÀttra situationen?
Shortest Time-to-Completion First (STCF)
För att förbĂ€ttra situationen slĂ€pper vi antagande 3 om att programmet körs och arbetar till dess avslut. Dessutom behöver vi hĂ„rdvarustöd och som ni kan gissa, kommer vi att anvĂ€nda en timer för att avbryta en körande uppgift och vĂ€xla kontexter. SĂ„ledes kan schemalĂ€ggaren vid ankomsten av uppgifter B, C â avbryta uppgift A och börja bearbeta uppgifter B och C, och efter deras slutförande fortsĂ€tta köra process A. En sĂ„dan schemalĂ€ggare kallas STCFeller Preemptive Job First.

Resultatet av detta schemalÀggarens arbete blir: ((120-0)+(20-10)+(30-10))/3=50. DÀrmed blir denna schemalÀggare Ànnu mer optimal för vÄra uppgifter.
Metrik Svarstid (Response Time)
SĂ„, om vi kĂ€nner till bearbetningstiden för uppgifterna och att dessa uppgifter bara anvĂ€nder CPU, skulle STCF vara det bĂ€sta beslutet. I de tidiga dagarna fungerade dessa algoritmer ganska bra. Men nu tillbringar anvĂ€ndaren större delen av sin tid vid terminalen och förvĂ€ntar ett produktivt interaktivt samspel. SĂ„ föddes den nya metrik â svarstid (response time).
Svarstid berÀknas enligt följande:
Tresponse=TfirstrunâTarrival
SÄledes, i det tidigare exemplet, blir svarstiden: A=0, B=0, C=10 (abg=3,33).
Och algoritmen STCF Àr faktiskt inte sÄ bra i situationer dÀr tre uppgifter anlÀnder samtidigt - den mÄste vÀnta tills de smÄ uppgifterna Àr helt avslutade. SÄledes Àr algoritmen bra för turnaround-timing, men dÄlig för interaktivitet. TÀnk dig att du sitter vid en terminal och försöker skriva tecken i en redigerare, men du mÄste vÀnta mer Àn 10 sekunder eftersom en annan uppgift ockuperar processorn. Det Àr inte sÀrskilt trevligt.

SÄ vi stöter pÄ ett annat problem - hur kan vi bygga en schemalÀggare som Àr kÀnslig för respons-tid?
Round Robin
För att lösa detta problem har en algoritm utvecklats Round Robin (RR). Grundidén Àr ganska enkel: istÀllet för att köra uppgifter tills de Àr helt avslutade, ska vi köra en uppgift under en viss tidsperiod (kallad tidskvant) och sedan vÀxla till en annan uppgift i kön. Algoritmen upprepar sitt arbete tills alla uppgifter Àr avslutade. Under tiden mÄste programmets körtid vara ett multipel av tiden dÄ timern avbryter processen. Till exempel, om timern avbryter processen var tionde millisekund, dÄ bör fönsterstorleken för processens exekvering vara ett multipel av 10 och vara 10, 20 eller x*10.
LÄt oss ta ett exempel: Uppgifterna A, B och C anlÀnder samtidigt till systemet och var och en vill köra i 5 sekunder. SJF-algoritmen kommer att utföra varje uppgift till slutet innan den startar en annan. Till skillnad frÄn detta kommer RR-algoritmen med en körfönster pÄ 1 sekund att gÄ igenom uppgifterna pÄ följande sÀtt (se bild 4.3):

(SJF Again (DÄlig för Respons-Tid)

(Round Robin (Bra För Respons-Tid)
Det genomsnittliga svarstiden för RR-algoritmen (0+1+2)/3=1, medan för SJF (0+5+10)/3=5.
Det Ă€r rimligt att anta att tidsfönstret Ă€r en mycket viktig parameter för RR; ju mindre det Ă€r, desto högre Ă€r responstiden. Dock fĂ„r man inte göra det för litet, eftersom tiden för kontextbyte ocksĂ„ kommer att spela sin roll i den övergripande prestandan. DĂ€rför stĂ€lls tidsfönstret in av operativsystemets arkitekt och beror pĂ„ de uppgifter som planeras att köras. Kontextbyte Ă€r inte den enda systemoperation som tar tid â det körda programmet interagerar med mĂ„nga andra saker, till exempel olika cacher, och vid varje byte mĂ„ste denna miljö sparas och Ă„terstĂ€llas, vilket ocksĂ„ kan ta mycket tid.
RR Àr en utmÀrkt schemalÀggare om det endast handlar om responstidsmetrik. Men hur beter sig metrik för uppgiftens omsÀttningshastighet med denna algoritm? LÄt oss titta pÄ exemplet ovan, dÀr A, B, C = 5s och de kommer in samtidigt. Uppgift A avslutas vid 13, B vid 14, C vid 15s, och den genomsnittliga omsÀttningstiden blir 14s. DÀrför Àr RR den sÀmsta algoritmen för omsÀttningsmetrik.
Mer generellt kan man sÀga att varje algoritm av RR-typ Àr rÀttvis; den delar CPU-arbetstiden jÀmnt mellan alla processer. Och pÄ sÄ sÀtt stÄr dessa metrikar konstant i konflikt med varandra.
SĂ„ledes har vi flera motsatta algoritmer och det kvarstĂ„r ocksĂ„ flera antaganden â att uppgiftens tid Ă€r kĂ€nd och att uppgiften endast anvĂ€nder CPU.
Blandning med I/O
Först och frÀmst ska vi ta bort antagandet 4, att processen bara anvÀnder CPU; det Àr naturligtvis inte sÄ, och processerna kan ocksÄ begÀra annan hÄrdvara.
Vid den tidpunkt dÄ en process begÀr en in- och utmatningsoperation gÄr processen in i ett blockerat tillstÄnd och vÀntar pÄ att I/O ska slutföras. Om I/O skickas till hÄrddisken kan en sÄdan operation ta flera millisekunder eller lÀngre, och CPU:n kommer vara idle under denna tid. Under denna tid kan schemalÀggaren anvÀnda CPU:n för en annan process. Den nÀsta beslutsfattning som schemalÀggaren mÄste göra Àr nÀr processen kommer att slutföra sin I/O. NÀr det hÀnder kommer ett avbrott att intrÀffa, och operativsystemet kommer att överföra den process som begÀrde I/O till ett redo-tillstÄnd.
LÄt oss betrakta ett exempel med flera uppgifter. Varje uppgift behöver 50 ms processor tid. Men den första kommer att göra ett I/O-anrop var tionde millisekund (som ocksÄ kommer att köras under 10 ms). Och process B anvÀnder helt enkelt 50 ms processor utan I/O.

I detta exempel kommer vi att anvĂ€nda STCF-schemalĂ€ggaren. Hur kommer schemalĂ€ggaren att bete sig om vi kör process A? Den kommer att agera pĂ„ följande sĂ€tt â först fullföljer den helt process A, och sedan process B.

Den traditionella metoden för att lösa detta problem Ă€r att tolka varje 10 ms deluppgift av process A som en separat uppgift. DĂ€rför, nĂ€r man startar med algoritmen STJF, Ă€r valet mellan en 50 ms uppgift och en 10 ms uppgift uppenbart. NĂ€r deluppgiften A Ă€r slutförd kommer process B och I/O att köras. Efter att I/O Ă€r slutfört kommer vi Ă„terigen att starta process A pĂ„ 10 ms istĂ€llet för process B. PĂ„ sĂ„ sĂ€tt Ă€r det möjligt att realisera överlappning, dĂ€r CPU anvĂ€nds av en annan process medan den första vĂ€ntar pĂ„ I/O. Resultatet Ă€r att systemet utnyttjas bĂ€ttre â nĂ€r interaktiva processer vĂ€ntar pĂ„ I/O kan andra processer köras pĂ„ processorn.
Oraklet finns inte lÀngre
LÄt oss nu försöka göra oss av med antagandet att uppgiftens körtid Àr kÀnd. Detta Àr i stort sett det sÀmsta och mest orealistiska antagandet pÄ hela listan. Faktiskt vet den genomsnittliga vanliga operativsystemet vanligtvis mycket lite om körtiden för uppgifter, hur skulle vi dÄ bygga en schemalÀggare utan att veta hur lÀnge en uppgift kommer att köras? Kanske skulle vi kunna anvÀnda vissa principer frÄn RR för att lösa detta problem?
Resultat
Vi har tittat pÄ grundlÀggande idéer om uppgiftsschemalÀggning och granskat tvÄ familjer av schemalÀggare. Den första kör den kortaste uppgiften först och ökar dÀrmed genomloppstiden, medan den andra fördelar tiden jÀmnt mellan alla uppgifter, vilket ökar svarstiden. BÄda algoritmerna Àr dÄliga dÀr de andra familjens algoritmer Àr bra. Vi har ocksÄ sett hur parallell anvÀndning av CPU och I/O kan förbÀttra prestandan, men vi har inte löst problemet med operativsystemets clairvoyance. PÄ nÀsta lektion kommer vi att titta pÄ en schemalÀggare som ser till det nÀrmaste förflutet och försöker förutsÀga framtiden. Den kallas multi-level feedback queue.
KĂ€lla: habr.com
