Operativsystem: Tre enkla delar. Del 1: Intro (översättning)

Introduktion till operativsystem

Hej, Habr! Jag skulle vilja presentera för din uppmärksamhet en serie artiklar-översättningar av en litteratur som är intressant enligt min mening - OSTEP. Detta material undersöker ganska djupt arbetet med unix-liknande operativsystem, nämligen arbete med processer, olika schemaläggare, minne och andra liknande komponenter som utgör ett modernt operativsystem. Du kan se originalet av allt material här här. Observera att översättningen gjordes oprofessionellt (ganska fritt), men jag hoppas att jag behöll den allmänna innebörden.

Labbarbete i detta ämne finns här:
- original: pages.cs.wisc.edu/~remzi/OSTEP/Homework/homework.html
- original: github.com/remzi-arpacidusseau/ostep-code
- min personliga anpassning: github.com/bykvaadm/OS/tree/master/ostep

Du kan också kolla in min kanal på telegram =)

Programdrift

Vad händer när ett program körs? Ett program som körs gör en enkel sak - det utför instruktioner. Varje sekund hämtas miljoner och till och med kanske miljarder instruktioner av processorn från RAM, i sin tur avkodar den dem (till exempel känner den igen vilken typ dessa instruktioner tillhör) och exekverar dem. Detta kan vara att lägga till två siffror, komma åt minnet, kontrollera ett villkor, hoppa till en funktion och så vidare. Efter exekvering av en instruktion fortsätter processorn till exekvering av en annan. Och så instruktion efter instruktion, de exekveras tills programmet slutar.
Det här exemplet anses naturligtvis vara förenklat - i själva verket, för att snabba upp processorn, tillåter modern hårdvara dig att exekvera instruktioner ur tur, beräkna möjliga resultat, exekvera instruktioner samtidigt och liknande knep.

Von Neumann beräkningsmodell

Den förenklade arbetsformen som beskrivs av oss liknar Von Neumann-modellen för beräkning. Von Neumann är en av pionjärerna inom datasystem, han är också en av författarna till spelteorin. Medan programmet körs sker en massa andra händelser, många andra processer och tredjepartslogikarbete, vars huvudsakliga syfte är att förenkla start, drift och underhåll av systemet.
Det finns en uppsättning mjukvara som är ansvarig för att göra program lätta att köra (eller till och med tillåta flera program att köras samtidigt), vilket gör att program kan dela samma minne, samt kommunicera med olika enheter. En sådan uppsättning mjukvara (mjukvara) kallas i huvudsak ett operativsystem och dess uppgifter inkluderar att övervaka att systemet fungerar korrekt och effektivt, samt att säkerställa enkel hantering av detta system.

Operativsystem

Ett operativsystem, förkortat ett OS, är en uppsättning inbördes relaterade program utformade för att hantera datorresurser och organisera användarinteraktion med en dator..
OS uppnår sin effektivitet i första hand, genom den viktigaste tekniken - tekniken virtualisering. OS interagerar med en fysisk resurs (processor, minne, disk, etc.) och omvandlar den till en mer allmän, kraftfullare och mer lättanvänd form av sig själv. Därför, för en allmän förståelse, kan du mycket grovt jämföra operativsystemet med en virtuell maskin.
För att tillåta användare att ge kommandon till operativsystemet och därmed använda funktionerna hos den virtuella maskinen (som att köra ett program, allokera minne, komma åt en fil och så vidare), tillhandahåller operativsystemet något gränssnitt som kallas API (applikationsprogrammeringsgränssnitt) och som du kan ringa till (ringa). Ett typiskt operativsystem tillåter hundratals systemsamtal att göras.
Slutligen, eftersom virtualisering tillåter flera program att köras (och därmed dela processorn) och samtidigt få åtkomst till deras instruktioner och data (och därmed dela minne) och komma åt diskar (och därmed dela I/O-enheter). ), kallas operativsystemet också en resursansvarig. Varje processor, disk och minne är en resurs i systemet, och därför blir en av operativsystemets roller uppgiften att hantera dessa resurser, göra det effektivt, ärligt eller vice versa, beroende på vilken uppgift det här operativsystemet har för är designad.

CPU-virtualisering

Tänk på följande program:
(https://www.youtube.com/watch?v=zDwT5fUcki4&feature=youtu.be)

Operativsystem: Tre enkla delar. Del 1: Intro (översättning)

Den utför inga speciella åtgärder, i själva verket är allt den gör att anropa en funktion snurra(), vars uppgift är att gå igenom tidskontrollen och återvända efter en sekund. Således upprepar den i oändlighet strängen som användaren skickade som ett argument.
Låt oss köra det här programmet och ge det tecknet "A" som ett argument. Resultatet är inte särskilt intressant - systemet kör helt enkelt ett program som med jämna mellanrum visar tecknet "A".
Låt oss nu prova alternativet när många instanser av samma program körs, men matar ut olika bokstäver för att göra det tydligare. I det här fallet blir resultatet något annorlunda. Trots att vi har en processor körs programmet samtidigt. Hur går det till? Men det visar sig att operativsystemet, inte utan hjälp av hårdvarufunktioner, skapar en illusion. Illusionen att systemet har flera virtuella processorer, vilket gör en enda fysisk processor till ett teoretiskt oändligt antal och därigenom tillåter till synes program att köras samtidigt. Denna illusion kallas CPU-virtualisering.
Den här bilden väcker många frågor, till exempel om flera program vill köra samtidigt, vilket kommer att lanseras? OS:s "policyer" är ansvariga för denna fråga. Policyer används på många ställen i operativsystemet och svarar på frågor som denna, och är de grundläggande mekanismerna som operativsystemet implementerar. Därav OS:s roll som resurshanterare.

Minnesvirtualisering

Låt oss nu titta på minnet. Den fysiska minnesmodellen i moderna system representeras som en uppsättning byte.. För att läsa från minnet måste du specificera celladressför att komma åt den. För att skriva eller uppdatera data måste du också ange data och adressen till cellen där den ska skrivas.
Minnet nås konstant under programkörning. Ett program lagrar hela sin datastruktur i minnet och kommer åt den genom att utföra olika instruktioner. Instruktionerna lagras under tiden också i minnet, så de nås också för varje begäran om nästa instruktion.

malloc() anrop

Tänk på följande program, som allokerar en minnesregion med hjälp av anropet malloc () (https://youtu.be/jnlKRnoT1m0):

Operativsystem: Tre enkla delar. Del 1: Intro (översättning)

Programmet gör flera saker. Först allokerar den lite minne (rad 7), skriver sedan ut adressen till den allokerade cellen (rad 9), skriver noll till den första luckan i det allokerade minnet. Därefter går programmet in i en slinga där det ökar värdet som är lagrat i minnet på adressen i variabeln "p". Den skriver också ut process-ID för sig själv. Process-ID:t är unikt för varje pågående process. Efter att ha lanserat flera kopior kommer vi att snubbla över ett intressant resultat: I det första fallet, om du inte gör något och bara kör flera kopior, kommer adresserna att vara annorlunda. Men detta faller inte under vår teori! Korrekt, eftersom moderna distributioner har minnesrandomisering aktiverad som standard. Om den är inaktiverad får vi det förväntade resultatet - minnesadresserna för två program som körs samtidigt kommer att matcha.

Operativsystem: Tre enkla delar. Del 1: Intro (översättning)

Som ett resultat visar det sig att två oberoende program arbetar med sina egna privata adressutrymmen, som i sin tur mappas av operativsystemet i fysiskt minne. Därför kommer användningen av minnesadresser inom ett program inte att påverka andra på något sätt, och det verkar för varje program att det har sin egen del av fysiskt minne, helt givet till det. Verkligheten är dock att fysiskt minne är en delad resurs som hanteras av operativsystemet.

Konsistens

Ett annat av de viktiga ämnena inom operativsystem är − konsistens. Denna term används när man talar om problem i systemet som kan uppstå när man arbetar med många saker samtidigt inom samma program. Konsekvensproblem uppstår även inom själva operativsystemet. I de tidigare exemplen på minnes- och processorvirtualisering insåg vi att operativsystemet hanterar många saker samtidigt - det startar den första processen, sedan den andra, och så vidare. Som det visade sig kan detta beteende leda till vissa problem. Så, till exempel, moderna flertrådiga program upplever sådana svårigheter.

Tänk på följande program:

Operativsystem: Tre enkla delar. Del 1: Intro (översättning)

Programmet i huvudfunktionen skapar två trådar med anropet pthread_create(). I det här exemplet kan en tråd ses som en funktion som körs i samma minnesutrymme tillsammans med andra funktioner, med tydligt mer än en funktion som körs samtidigt. I det här exemplet startar varje tråd och kör funktionen worker() som i sin tur helt enkelt ökar variabeln,.

Låt oss köra det här programmet med argumentet 1000. Som du kanske har gissat bör resultatet bli 2000 eftersom varje tråd ökade variabeln 1000 gånger. Allt är dock inte så enkelt. Låt oss försöka köra programmet med en storleksordning fler repetitioner.

Operativsystem: Tre enkla delar. Del 1: Intro (översättning)

Genom att mata in ett tal, till exempel 100000, förväntar vi oss att se utdata som talet 200000. Men om vi kör talet 100000 flera gånger kommer vi inte bara att inte se det korrekta svaret, utan också få olika felaktiga svar. Svaret ligger i det faktum att för att öka antalet krävs tre operationer - extrahera numret från minnet, inkrementera och sedan skriva tillbaka numret. Eftersom alla dessa instruktioner inte utförs atomärt (alla på samma gång), kan konstiga saker som detta hända. Detta problem kallas i programmering loppets skick. När okända styrkor vid ett okänt tillfälle kan påverka prestandan för någon av dina operationer.

Källa: will.com

Lägg en kommentar