Operativni sistemi: tri laka komada. Dio 3: Procesni API (prevod)

Uvod u operativne sisteme

Hej Habr! Skrećem vam pažnju na seriju članaka-prevoda jedne po meni zanimljive literature - OSTEP. U ovom materijalu se prilično duboko raspravlja o radu operativnih sistema sličnih unixu, odnosno radu sa procesima, raznim planerima, memorijom i drugim sličnim komponentama koje čine moderni OS. Original svih materijala možete pogledati ovdje ovdje. Napominjemo da je prevod urađen neprofesionalno (prilično slobodno), ali se nadam da sam zadržao opšte značenje.

Laboratorijski rad na ovu temu možete pronaći ovdje:

Ostali dijelovi:

Takođe možete pogledati moj kanal na telegram =)

Alarm! Za ovo predavanje postoji laboratorija! Pogledaj github

Procesni API

Pogledajmo primjer kreiranja procesa u UNIX sistemu. To se dešava kroz dva sistemska poziva viljuška() и exec().

Call fork()

Operativni sistemi: tri laka komada. Dio 3: Procesni API (prevod)

Razmotrite program koji vrši poziv fork(). Rezultat njegovog izvršenja bit će sljedeći.

Operativni sistemi: tri laka komada. Dio 3: Procesni API (prevod)

Prije svega, ulazimo u funkciju main() i ispisujemo string na ekranu. Red sadrži identifikator procesa koji se u originalu zove PID ili identifikator procesa. Ovaj identifikator se koristi u UNIX-u za upućivanje na proces. Sljedeća komanda će pozvati fork(). U ovom trenutku se kreira gotovo tačna kopija procesa. Za OS, izgleda da postoje 2 kopije istog programa pokrenute na sistemu, koji će zauzvrat izaći iz funkcije fork(). Novokreirani podređeni proces (u odnosu na roditeljski proces koji ga je kreirao) više se neće izvršavati, počevši od funkcije main(). Treba imati na umu da podređeni proces nije tačna kopija roditeljskog procesa; posebno, ima svoj adresni prostor, svoje registre, svoj pokazivač na izvršne instrukcije i slično. Stoga će vrijednost vraćena pozivaocu funkcije fork() biti drugačija. Konkretno, roditeljski proces će primiti PID vrijednost podređenog procesa kao povrat, a dijete će dobiti vrijednost jednaku 0. Koristeći ove povratne kodove, onda možete razdvojiti procese i prisiliti svaki od njih da radi svoj vlastiti posao . Međutim, izvođenje ovog programa nije striktno definirano. Nakon podjele na 2 procesa, OS počinje da ih prati, kao i da planira njihov rad. Ako se izvršava na procesoru s jednom jezgrom, jedan od procesa, u ovom slučaju roditeljski, nastavit će s radom, a potom će nadređeni proces dobiti kontrolu. Prilikom ponovnog pokretanja situacija može biti drugačija.

čekaj poziv()

Operativni sistemi: tri laka komada. Dio 3: Procesni API (prevod)

Razmotrite sljedeći program. U ovom programu, zbog prisustva poziva čekaj() Roditeljski proces će uvijek čekati da se dovrši proces podređen. U ovom slučaju, na ekranu ćemo dobiti striktno definisan tekst

Operativni sistemi: tri laka komada. Dio 3: Procesni API (prevod)

exec() poziv

Operativni sistemi: tri laka komada. Dio 3: Procesni API (prevod)

Razmotrite izazov exec(). Ovaj sistemski poziv je koristan kada želimo da pokrenemo potpuno drugačiji program. Evo mi ćemo zvati execvp() za pokretanje programa wc koji je program za brojanje riječi. Šta se dešava kada se pozove exec()? Ovom pozivu se prosljeđuje ime izvršne datoteke i neki parametri kao argumenti. Nakon toga se kod i statički podaci iz ove izvršne datoteke učitavaju i njegov vlastiti segment sa kodom se prepisuje. Preostala memorijska područja, kao što su stek i hrpa, ponovo se inicijaliziraju. Nakon toga OS jednostavno izvršava program, prosljeđujući mu skup argumenata. Dakle, nismo kreirali novi proces, jednostavno smo transformisali trenutno pokrenuti program u drugi pokrenuti program. Nakon izvršenja exec() poziva u potomku, izgleda kao da se originalni program uopće nije pokrenuo.

Ova komplikacija pri pokretanju je potpuno normalna za Unix ljusku i omogućava toj ljusci da izvrši kod nakon pozivanja viljuška(), ali prije poziva exec(). Primjer takvog koda bi bio prilagođavanje okruženja ljuske potrebama programa koji se pokreće prije pokretanja.

školjka - samo korisnički program. Ona vam pokazuje liniju pozivnice i čeka da u njoj nešto napišete. U većini slučajeva, ako tamo upišete ime programa, ljuska će pronaći njegovu lokaciju, pozvati metodu fork(), a zatim pozvati neku vrstu exec() da kreira novi proces i pričekati da se završi pomoću čekaj() poziv. Kada podređeni proces izađe, ljuska će se vratiti iz wait() poziva i ponovo ispisati prompt i čekati da se unese sljedeća naredba.

Fork() & exec() split omogućava ljusci da radi sljedeće stvari, na primjer:
wc fajl > nova_datoteka.

U ovom primjeru, izlaz wc programa je preusmjeren na datoteku. Način na koji ljuska to postiže je prilično jednostavan - kreiranjem podređenog procesa prije pozivanja exec(), ljuska zatvara standardni izlaz i otvara datoteku nova_datoteka, dakle, sav izlaz iz daljeg pokrenutog programa wc će biti preusmjeren na datoteku umjesto na ekran.

Unix cijev implementirani su na sličan način, s tom razlikom što koriste poziv pipe(). U ovom slučaju, izlazni tok procesa će biti povezan sa redom cijevi koji se nalazi u kernelu, na koji će biti povezan ulazni tok drugog procesa.

izvor: www.habr.com

Dodajte komentar