Operatsioonisüsteemid: kolm lihtsat osa. 3. osa: protsessi API (tõlge)

Sissejuhatus operatsioonisüsteemidesse

Tere Habr! Juhin teie tähelepanu artiklite sarjale-tõlketele ühest minu arvates huvitavast kirjandusest - OSTEP. Selles materjalis käsitletakse üsna põhjalikult unixi-laadsete operatsioonisüsteemide tööd, nimelt tööd protsesside, erinevate ajakavade, mälu ja muude sarnaste komponentidega, mis moodustavad kaasaegse OS-i. Kõikide materjalide originaale näed siit siin. Pange tähele, et tõlge on tehtud ebaprofessionaalselt (üsna vabalt), kuid loodan, et säilitasin üldise tähenduse.

Selle teema laboritööd leiate siit:

Muud osad:

Võite vaadata ka minu kanalit aadressil telegramm =)

Äratus! Selle loengu jaoks on labor olemas! Vaata github

Protsessi API

Vaatame näidet protsessi loomisest UNIX-süsteemis. See toimub kahe süsteemikõne kaudu kahvel () и exec().

Helista fork ()

Operatsioonisüsteemid: kolm lihtsat osa. 3. osa: protsessi API (tõlge)

Mõelge programmile, mis teeb fork()-kõne. Selle täitmise tulemus on järgmine.

Operatsioonisüsteemid: kolm lihtsat osa. 3. osa: protsessi API (tõlge)

Kõigepealt sisestame funktsiooni main() ja prindime stringi ekraanile. Rida sisaldab protsessi identifikaatorit, mida originaalis nimetatakse PID või protsessi identifikaator. Seda identifikaatorit kasutatakse UNIXis protsessile viitamiseks. Järgmine käsk kutsub esile fork(). Sel hetkel luuakse protsessist peaaegu täpne koopia. OS-i puhul tundub, et süsteemis töötab sama programmi 2 koopiat, mis omakorda väljub funktsioonist fork(). Äsja loodud alamprotsessi (seoses selle loonud vanemprotsessiga) enam ei käivitata, alustades funktsioonist main(). Tuleb meeles pidada, et alamprotsess ei ole emaprotsessi täpne koopia; eelkõige on sellel oma aadressiruum, oma registrid, oma osuti käivitatavatele käskudele jms. Seega on funktsiooni fork() kutsujale tagastatav väärtus erinev. Eelkõige saab vanemprotsess tagastusena alamprotsessi PID-väärtuse ja alamprotsess saab väärtuse, mis on võrdne 0-ga. Neid tagastuskoode kasutades saate seejärel protsessid eraldada ja sundida igaüks neist oma tööd tegema. . Selle programmi täitmine pole aga rangelt määratletud. Pärast kaheks protsessiks jagamist hakkab OS neid jälgima ja nende tööd planeerima. Kui käivitada ühetuumalisel protsessoril, jätkab üks protsessidest, antud juhul vanemprotsess, tööd ja seejärel saab alamprotsess kontrolli alla. Taaskäivitamisel võib olukord olla erinev.

Kõne ootama ()

Operatsioonisüsteemid: kolm lihtsat osa. 3. osa: protsessi API (tõlge)

Kaaluge järgmist programmi. Selles programmis kõne olemasolu tõttu oota () Vanemprotsess ootab alati, kuni alamprotsess lõpeb. Sel juhul saame ekraanile rangelt määratletud tekstiväljundi

Operatsioonisüsteemid: kolm lihtsat osa. 3. osa: protsessi API (tõlge)

exec() kõne

Operatsioonisüsteemid: kolm lihtsat osa. 3. osa: protsessi API (tõlge)

Kaaluge väljakutset exec(). See süsteemikutse on kasulik, kui tahame käivitada täiesti erinevat programmi. Siin me helistame execvp() wc-programmi käivitamiseks, mis on sõnade loendusprogramm. Mis juhtub, kui kutsutakse exec()? See kõne edastatakse argumentidena käivitatava faili nimi ja mõned parameetrid. Pärast seda laaditakse selle käivitatava faili kood ja staatilised andmed ning selle segment koos koodiga kirjutatakse üle. Ülejäänud mälualad, nagu virn ja hunnik, lähtestatakse uuesti. Pärast mida OS lihtsalt käivitab programmi, edastades sellele argumentide komplekti. Seega ei loonud me uut protsessi, vaid muutsime praegu töötava programmi lihtsalt teiseks jooksvaks programmiks. Pärast exec() kutse täitmist järeltulijas tundub, et algne programm ei käivitunud üldse.

See käivitamise komplikatsioon on Unixi kesta puhul täiesti tavaline ja võimaldab sellel kestil käivitada koodi pärast helistamist kahvel (), kuid enne kõnet exec(). Sellise koodi näide oleks kestakeskkonna kohandamine käivitatava programmi vajadustega enne selle käivitamist.

Shell - lihtsalt kasutajaprogramm. Ta näitab sulle kutserida ja ootab, kuni sa sinna midagi kirjutad. Enamikul juhtudel, kui kirjutate sinna programmi nime, leiab shell selle asukoha, kutsub esile meetodi fork() ja seejärel kutsub välja teatud tüüpi exec(), et luua uus protsess ja oodata selle lõpuleviimist. oota() kõne. Kui alamprotsess väljub, naaseb kest ootamise () kõnest ja prindib viipa uuesti ning ootab järgmise käsu sisestamist.

Fork() & exec() split võimaldab kestil teha näiteks järgmisi asju:
wc-fail > uus_fail.

Selles näites suunatakse wc-programmi väljund faili. See, kuidas kest selle saavutab, on üsna lihtne – luues enne helistamist alamprotsessi exec(), sulgeb kest standardväljundi ja avab faili uus_fail, seega kogu edasise töötava programmi väljund wc suunatakse ekraani asemel faili.

Unixi toru on rakendatud sarnaselt, selle erinevusega, et nad kasutavad pipe()-kutset. Sel juhul ühendatakse protsessi väljundvoog tuumas asuva torujärjekorraga, millega ühendatakse teise protsessi sisendvoog.

Allikas: www.habr.com

Lisa kommentaar