Stýrikerfi: Þrjú auðveld stykki. Hluti 3: Process API (þýðing)

Kynning á stýrikerfum

Halló, Habr! Mig langar að kynna þér röð greina-þýðinga á einni bókmenntum sem er áhugaverð að mínu mati - OSTEP. Þetta efni skoðar nokkuð djúpt vinnu unix-líkra stýrikerfa, nefnilega vinnu með ferlum, ýmsum tímaáætlunum, minni og öðrum álíka íhlutum sem mynda nútíma stýrikerfi. Þú getur séð frumrit allra efnis hér hér. Vinsamlegast athugaðu að þýðingin var gerð ófagmannlega (alveg frjálslega), en ég vona að ég hafi haldið almennri merkingu.

Vinnustofur um þetta efni má finna hér:

Aðrir hlutar:

Þú getur líka skoðað rásina mína á símskeyti =)

Viðvörun! Það er rannsóknarstofa fyrir þennan fyrirlestur! Sjáðu github

Process API

Skoðum dæmi um að búa til ferli í UNIX kerfi. Það gerist í gegnum tvö kerfissímtöl gaffal() и exec().

Call fork()

Stýrikerfi: Þrjú auðveld stykki. Hluti 3: Process API (þýðing)

Íhugaðu forrit sem gerir fork() kall. Niðurstaða framkvæmdar þess verður sem hér segir.

Stýrikerfi: Þrjú auðveld stykki. Hluti 3: Process API (þýðing)

Fyrst af öllu förum við inn í main() aðgerðina og prentum strenginn á skjáinn. Línan inniheldur ferli auðkenni sem í frumritinu er kallað PID eða ferli auðkenni. Þetta auðkenni er notað í UNIX til að vísa til ferlis. Næsta skipun kallar fork(). Á þessum tímapunkti er næstum nákvæm afrit af ferlinu búið til. Fyrir stýrikerfið lítur út fyrir að það séu 2 eintök af sama forriti í gangi á kerfinu, sem aftur mun hætta í fork() aðgerðinni. Nýlega stofnað undirferlið (í tengslum við yfirferlið sem bjó það til) verður ekki lengur keyrt, byrjað á main() aðgerðinni. Það ætti að hafa í huga að undirferli er ekki nákvæm afrit af yfirferlinu; sérstaklega hefur það sitt eigið vistfang, eigin skrár, eigin bendil á keyranlegar leiðbeiningar og þess háttar. Þannig mun gildið sem er skilað til þess sem hringir í fork() fallinu vera annað. Sérstaklega mun foreldraferlið fá PID-gildi undirferlisins sem skil og barnið fær gildi sem jafngildir 0. Með því að nota þessa skilakóða geturðu síðan aðskilið ferla og þvingað hvert þeirra til að vinna sína eigin vinnu. . Hins vegar er framkvæmd þessa forrits ekki nákvæmlega skilgreind. Eftir að hafa skipt í 2 ferla byrjar stýrikerfið að fylgjast með þeim og skipuleggja vinnu þeirra. Ef það er keyrt á einskjarna örgjörva mun eitt af ferlunum, í þessu tilviki foreldri, halda áfram að virka og þá fær undirferlið stjórn. Þegar endurræst er getur staðan verið önnur.

Símtal bið()

Stýrikerfi: Þrjú auðveld stykki. Hluti 3: Process API (þýðing)

Hugleiddu eftirfarandi forrit. Í þessu forriti, vegna tilvistar símtals bíddu() Foreldraferlið mun alltaf bíða eftir að barnferlinu ljúki. Í þessu tilviki munum við fá stranglega skilgreindan textaúttak á skjánum

Stýrikerfi: Þrjú auðveld stykki. Hluti 3: Process API (þýðing)

exec() kalla

Stýrikerfi: Þrjú auðveld stykki. Hluti 3: Process API (þýðing)

Hugleiddu áskorunina exec(). Þetta kerfiskall er gagnlegt þegar við viljum keyra allt annað forrit. Hér munum við hringja execvp() að keyra wc forritið sem er orðatalningarforrit. Hvað gerist þegar exec() er kallað? Þetta símtal fær nafnið á keyrsluskránni og nokkrum breytum sem rök. Eftir það er kóðinn og kyrrstöðugögnin úr þessari keyrsluskrá hlaðin og eigin hluti hennar með kóðanum er skrifaður yfir. Minnissvæðin sem eftir eru, eins og staflan og haugurinn, eru endurræst. Eftir það keyrir stýrikerfið einfaldlega forritið og sendir því safn af rökum. Þannig að við bjuggum ekki til nýtt ferli, við breyttum einfaldlega forritinu sem er í gangi í annað forrit sem er í gangi. Eftir að hafa keyrt exec() kallið í descendant, virðist sem upprunalega forritið hafi alls ekki keyrt.

Þessi ræsingarflækja er fullkomlega eðlileg fyrir Unix skel og gerir þeirri skel kleift að keyra kóða eftir að hafa hringt gaffal(), en fyrir símtalið exec(). Dæmi um slíkan kóða væri að laga skel umhverfið að þörfum forritsins sem verið er að ræsa, áður en það er ræst.

Shell - bara notendaforrit. Hún sýnir þér boðslínuna og bíður eftir að þú skrifir eitthvað í hana. Í flestum tilfellum, ef þú skrifar nafn forrits þar, mun skelin finna staðsetningu þess, kalla fork() aðferðina og kalla síðan einhverja tegund af exec() til að búa til nýtt ferli og bíða eftir að því ljúki með því að nota a. bíddu() hringja. Þegar barnaferlið lýkur mun skelin snúa aftur úr wait() símtalinu og prenta vísunina aftur og bíða eftir að næsta skipun sé slegin inn.

Fork() & exec() skiptingin gerir skelinni kleift að gera eftirfarandi hluti, til dæmis:
wc skrá > ný_skrá.

Í þessu dæmi er úttak wc forritsins vísað á skrá. Leiðin sem skelin nær þessu er frekar einföld - með því að búa til barnaferli áður en hringt er exec(), skelin lokar venjulegu úttakinu og opnar skrána ný_skrá, þannig, öll framleiðsla frá áframhaldandi forriti wc verður vísað á skrá í stað skjás.

Unix pípa eru útfærðar á svipaðan hátt, með þeim mun að þeir nota pipe() kall. Í þessu tilviki verður úttaksstraumur ferlisins tengdur við pípuröð sem staðsett er í kjarnanum, sem inntaksstraumur annars ferlis verður tengdur við.

Heimild: www.habr.com

Bæta við athugasemd