Operativni sustavi: tri laka komada. Dio 3: Proces API (prijevod)

Uvod u operacijske sustave

Hej Habr! Predstavljam vam seriju članaka-prijevoda jedne po meni zanimljive literature - OSTEP. Ovaj materijal prilično duboko raspravlja o radu operativnih sustava nalik unixu, naime o radu s procesima, raznim planerima, memorijom i drugim sličnim komponentama koje čine moderan OS. Izvornike svih materijala možete vidjeti ovdje ovdje. Napominjem da je prijevod urađen neprofesionalno (sasvim slobodno), ali se nadam da sam zadržao opći smisao.

Laboratorijske radove iz ove teme možete pronaći ovdje:

Ostali dijelovi:

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

Alarm! Za ovo predavanje postoji laboratorij! Izgled github

API procesa

Pogledajmo primjer kreiranja procesa u UNIX sustavu. To se događa kroz dva sistemska poziva vilica () и exec().

Call fork()

Operativni sustavi: tri laka komada. Dio 3: Proces API (prijevod)

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

Operativni sustavi: tri laka komada. Dio 3: Proces API (prijevod)

Prije svega, ulazimo u funkciju main() i ispisujemo string na ekran. Redak sadrži identifikator procesa koji se u originalu zove PID ili identifikator procesa. Ovaj se identifikator koristi u UNIX-u za označavanje procesa. Sljedeća naredba će pozvati fork(). U ovom trenutku stvara se gotovo točna kopija procesa. Za OS, izgleda da postoje 2 kopije istog programa koji se izvode na sustavu, koji će izaći iz funkcije fork(). Novostvoreni podređeni proces (u odnosu na nadređeni proces koji ga je kreirao) više se neće izvršavati, počevši od funkcije main(). Treba imati na umu da proces dijete nije točna kopija procesa roditelja, posebno ima svoj vlastiti adresni prostor, svoje registre, svoj pokazivač na izvršne instrukcije i slično. Stoga će vrijednost vraćena pozivatelju funkcije fork() biti drugačija. Konkretno, nadređeni proces će primiti PID vrijednost procesa djeteta kao povrat, a dijete će dobiti vrijednost jednaku 0. Koristeći ove povratne kodove, možete zatim odvojiti procese i natjerati svakog od njih da radi svoj posao . Međutim, izvođenje ovog programa nije strogo definirano. Nakon podjele na 2 procesa, OS ih počinje nadzirati, kao i planirati njihov rad. Ako se izvrši na jednojezgrenom procesoru, jedan od procesa, u ovom slučaju roditelj, nastavit će raditi, a potom će proces dijete dobiti kontrolu. Prilikom ponovnog pokretanja situacija može biti drugačija.

Poziv na čekanju()

Operativni sustavi: tri laka komada. Dio 3: Proces API (prijevod)

Razmotrite sljedeći program. U ovom programu, zbog prisutnosti poziva čekati() Roditeljski proces će uvijek čekati da se dijete završi. U ovom slučaju dobit ćemo strogo definiran izlaz teksta na zaslonu

Operativni sustavi: tri laka komada. Dio 3: Proces API (prijevod)

exec() poziv

Operativni sustavi: tri laka komada. Dio 3: Proces API (prijevod)

Razmotrite izazov exec(). Ovaj sistemski poziv koristan je kada želimo pokrenuti potpuno drugačiji program. Ovdje ćemo nazvati execvp() za pokretanje wc programa koji je program za brojanje riječi. Što se događa kada se pozove exec()? Ovom se pozivu prosljeđuje ime izvršne datoteke i neki parametri kao argumenti. Nakon toga se učitavaju kod i statički podaci iz ove izvršne datoteke i prepisuje se vlastiti segment s kodom. Preostala područja memorije, kao što su stog i hrpa, ponovno se inicijaliziraju. Nakon toga OS jednostavno izvršava program, prosljeđujući mu skup argumenata. Dakle, nismo stvorili novi proces, jednostavno smo transformirali trenutno pokrenuti program u drugi pokrenuti program. Nakon izvršavanja exec() poziva u potomku, čini se kao da se izvorni program uopće nije pokrenuo.

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

Ljuska - samo korisnički program. Pokazuje vam pozivnicu i čeka da u njoj nešto napišete. U većini slučajeva, ako ondje napišete naziv programa, ljuska će pronaći njegovu lokaciju, pozvati metodu fork(), a zatim pozvati neku vrstu exec() za stvaranje novog procesa i pričekati da završi pomoću čekaj() poziv. Kada podređeni proces izađe, ljuska će se vratiti s poziva wait() i ponovno ispisati upit i čekati da se unese sljedeća naredba.

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

U ovom primjeru, izlaz wc programa je preusmjeren na datoteku. Način na koji ljuska to postiže prilično je jednostavan - stvaranjem procesa djeteta prije poziva exec(), ljuska zatvara standardni izlaz i otvara datoteku nova_datoteka, dakle, sav izlaz iz programa koji se dalje izvodi wc bit će preusmjeren na datoteku umjesto na zaslon.

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

Izvor: www.habr.com

Dodajte komentar