Operativsystem: Tre enkla bitar. Del 3: Process API (översÀttning)

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 ). Ett typiskt exempel pĂ„ anvĂ€ndning:. 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Ä telegram =)

Varning! det finns ett labb för denna förelÀsning! Kolla hÀr github

Process API

Vi kommer att titta pÄ ett exempel pÄ hur man skapar en process i ett UNIX-system. Detta sker genom tvÄ systemanrop. fork() och exec().

Anropet fork()

Operativsystem: Tre enkla bitar. Del 3: Process API (översÀttning)

LÄt oss övervÀga ett program som gör ett fork()-anrop. Resultatet av dess körning kommer att bli följande.

Operativsystem: Tre enkla bitar. Del 3: Process API (översÀttning)

Först gÄr vi in i funktionen main() och skriver ut en strÀng pÄ skÀrmen. StrÀngen innehÄller processens identifierare som pÄ engelska kallas PID eller process identifier. Denna identifierare anvÀnds i UNIX för att adressa processen. Den nÀsta kommandot kommer att utföra ett fork()-anrop. Vid detta tillfÀlle skapas en praktiskt taget exakt kopia av processen. För operativsystemet ser det ut som om det finns tvÄ kopior av samma program som körs, som sedan kommer att gÄ ut frÄn fork()-funktionen. Den nyss skapade processbarnet (i förhÄllande till den skapande processförÀldern) kommer inte att fortsÀtta att köras frÄn funktionen main(). Det Àr viktigt att komma ihÄg att processbarnet inte Àr en exakt kopia av processförÀldern; sÀrskilt har det sitt eget adressutrymme, egna register, sin egen pekare pÄ exekverbara instruktioner och sÄ vidare. DÀrför kommer vÀrdet som returneras av fork()-anropet att vara olika. Specifikt kommer processförÀldern att fÄ PID-vÀrdet för barnprocessen som returvÀrde, medan barnet fÄr vÀrdet 0. UtifrÄn dessa returvÀrden kan vi sedan separera processerna och fÄ varje av dem att utföra sitt arbete. Notera att körningen av detta program inte Àr strikt definierad. NÀr processerna har separerats börjar operativsystemet övervaka dem och planera deras arbete. Vid körning pÄ en enkelkÀrnig processor fortsÀtter en av processerna, i detta fall - förÀldern, medan barnprocessen fÄr kontroll efter det. Vid nÀsta körning kan situationen vara annorlunda.

Anropet wait()

Operativsystem: Tre enkla bitar. Del 3: Process API (översÀttning)

LÄt oss övervÀga följande program. I detta program, genom att inkludera anropet wait() processförÀldern kommer alltid att vÀnta pÄ att barnprocessen ska avslutas. I detta fall kommer vi att fÄ en strikt definierad utdata pÄ skÀrmen.

Operativsystem: Tre enkla bitar. Del 3: Process API (översÀttning)

Anropet exec()

Operativsystem: Tre enkla bitar. Del 3: Process API (översÀttning)

LÄt oss se pÄ anropet exec(). Detta systemanrop Àr anvÀndbart nÀr vi vill köra ett helt annat program. HÀr kommer vi att göra ett anrop till execvp() För att köra programmet wc, som Àr ett program för att rÀkna ord. Vad hÀnder nÀr exec() anropas? Detta anrop fÄr som argument namnet pÄ den körbara filen och viss information. Efter det sker en laddning av koden och statiska data frÄn den körbara filen och den egna segmentet med kod skrivs över. Andra minnesomrÄden, som stack och heap, initialiseras om. DÀrefter kör OS helt enkelt programmet och skickar en uppsÀttning argument till det. SÄledes skapade vi inte en ny process, vi transformerade helt enkelt det aktuella körande programmet till ett annat körande program. Efter att exec() anropats, har barnet intrycket av att det ursprungliga programmet knappast ens startades.

Denna komplexitet vid start Àr helt normal för Unix-skalet och gör att detta skal kan köra kod efter anropet fork(), men innan anropet exec(). Ett exempel pÄ sÄdan kod kan vara anpassning av skalets miljö till behoven hos det startande programmet, innan dess faktiska körning.

Shell — det Ă€r bara ett anvĂ€ndarprogram. Det visar en inloggningsprompt och vĂ€ntar pĂ„ att du ska skriva nĂ„got. I de flesta fall, om du skriver namnet pĂ„ ett program dĂ€r, kommer skalet att hitta dess plats, anropa fork(), och sedan, för att skapa en ny process, anropa nĂ„got av typen exec() och vĂ€nta pĂ„ att den ska köras med hjĂ€lp av anropet wait(). NĂ€r barnprocessen avslutas kommer skalet att Ă„tergĂ„ frĂ„n anropet wait() och igen visa inloggningsprompten och vĂ€nta pĂ„ nĂ€sta kommando.

Separeringen av fork() & exec() gör att skalet kan utföra följande saker, till exempel:
wc file > new_file.

I det hĂ€r exemplet har utdata frĂ„n programmet wc omdirigerats till en fil. SĂ€ttet som skalet uppnĂ„r detta pĂ„ Ă€r ganska enkelt — nĂ€r processen barnet skapas, stĂ€nger skalet den standardutgĂ„ngsströmmen och öppnar filen exec()new_file , pĂ„ sĂ„ sĂ€tt kommer all utdata frĂ„n det dĂ€refter körda programmetatt omdirigeras till filen istĂ€llet för till skĂ€rmen. wc Kommandon

Unix-pipor implementeras pÄ liknande sÀtt, med skillnaden att de anvÀnder anropet pipe(). I det hÀr fallet kommer utdataflödet frÄn processen att kopplas till en pipe-kö som ligger i kÀrnan, som ocksÄ kommer att kopplas till indataflödet frÄn en annan process.

KĂ€lla: habr.com

Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar đŸ”„ Köp pĂ„litlig webbhotell med DDoS-skydd, VPS VDS-servrar | ProHoster