Оперативни системи: Три лесни парчиња. Дел 3: Процес API (превод)

Вовед во оперативни системи

Здраво, Хабр! Би сакал да ви претставам низа написи-преводи на една според мене интересна литература - ОСТЕП. Овој материјал прилично длабоко ја испитува работата на оперативните системи слични на Unix, имено, работата со процеси, различни распоредувачи, меморија и други слични компоненти кои го сочинуваат модерен оперативен систем. Оригиналот на сите материјали можете да го видите овде тука. Имајте предвид дека преводот е направен непрофесионално (сосема слободно), но се надевам дека го задржав општото значење.

Лабораториска работа на оваа тема може да се најде овде:

Други делови:

Можете исто така да го проверите мојот канал на телеграма =)

Аларм! Има лабораторија за ова предавање! Погледнете github

Процес API

Ајде да погледнеме пример за создавање процес во UNIX систем. Тоа се случува преку два системски повици вилушка () и exec ().

Call fork()

Оперативни системи: Три лесни парчиња. Дел 3: Процес API (превод)

Размислете за програма што прави повик fork(). Резултатот од неговото извршување ќе биде како што следува.

Оперативни системи: Три лесни парчиња. Дел 3: Процес API (превод)

Прво, ја внесуваме функцијата main() и ја печатиме низата на екранот. Линијата го содржи идентификаторот на процесот кој во оригиналот се нарекува PID или идентификатор на процес. Овој идентификатор се користи во UNIX за да се однесува на процес. Следната команда ќе повика fork(). Во овој момент, се создава речиси точна копија од процесот. За ОС, изгледа дека има 2 копии од истата програма што работат на системот, што пак ќе излезе од функцијата fork(). Новосоздадениот дете процес (во однос на матичниот процес кој го создал) повеќе нема да се извршува, почнувајќи од функцијата main(). Треба да се запомни дека детето процес не е точна копија на родителскиот процес, тој има сопствен адресен простор, свои регистри, свој покажувач кон извршни инструкции и слично. Така, вредноста вратена на повикувачот на функцијата fork() ќе биде различна. Особено, матичниот процес ќе ја добие PID вредноста на детето процес како враќање, а детето ќе добие вредност еднаква на 0. Користејќи ги овие шифри за враќање, потоа можете да ги одделите процесите и да го принудите секој од нив да ја врши својата работа . Сепак, извршувањето на оваа програма не е строго дефинирано. Откако ќе се подели на 2 процеси, ОС почнува да ги следи, како и да ја планира нивната работа. Ако се изврши на еднојадрен процесор, еден од процесите, во овој случај родителот, ќе продолжи да работи, а потоа процесот дете ќе добие контрола. При рестартирање, ситуацијата може да биде различна.

Повик на чекање ()

Оперативни системи: Три лесни парчиња. Дел 3: Процес API (превод)

Размислете за следната програма. Во оваа програма, поради присуството на повик чекај () Родителскиот процес секогаш ќе чека да заврши процесот на дете. Во овој случај, ќе добиеме строго дефиниран излез на текст на екранот

Оперативни системи: Три лесни парчиња. Дел 3: Процес API (превод)

exec() повик

Оперативни системи: Три лесни парчиња. Дел 3: Процес API (превод)

Размислете за предизвикот exec (). Овој системски повик е корисен кога сакаме да извршиме сосема друга програма. Еве ние ќе се јавиме execvp () да ја стартувате програмата wc која е програма за броење зборови. Што се случува кога се повикува exec()? Овој повик го пренесува името на извршната датотека и некои параметри како аргументи. По што кодот и статичките податоци од оваа извршна датотека се вчитуваат и неговиот сопствен сегмент со кодот се препишува. Останатите мемориски области, како што се оџакот и купот, се реиницијализираат. По што оперативниот систем едноставно ја извршува програмата, пренесувајќи ѝ збир на аргументи. Значи, не создадовме нов процес, туку едноставно ја трансформиравме тековната програма во друга програма што работи. По извршувањето на повикот exec() во потомокот, се чини дека оригиналната програма воопшто не работи.

Оваа компликација за стартување е сосема нормална за Unix школка и дозволува таа школка да изврши код по повикување вилушка (), но пред повикот exec (). Пример за таков код би бил прилагодувањето на околината на школка на потребите на програмата што се стартува, пред да се стартува.

Школка - само корисничка програма. Таа ти ја покажува линијата за покана и чека да напишеш нешто во неа. Во повеќето случаи, ако го напишете името на програмата таму, школка ќе ја најде нејзината локација, ќе го повика методот fork() и потоа ќе повика некој тип на exec() за да создаде нов процес и ќе чека да заврши со користење на чекај() повик. Кога ќе излезе процесот на дете, школката ќе се врати од повикот на чекање() и повторно ќе го испечати промптот и ќе чека да се внесе следната команда.

Поделбата на fork() и exec() и дозволува на школката да ги прави следниве работи, на пример:
wc датотека > new_file.

Во овој пример, излезот од програмата wc е пренасочен во датотека. Начинот на кој школката го постигнува ова е прилично едноставен - со креирање дете процес пред да се јави exec (), школка го затвора стандардниот излез и ја отвора датотеката нова_датотека, на тој начин, целиот излез од понатамошната програма која работи wc ќе се пренасочи кон датотека наместо на екран.

Unix цевка се имплементирани на сличен начин, со таа разлика што користат повик pipe(). Во овој случај, излезниот тек на процесот ќе се поврзе со редот на цевки лоциран во јадрото, на кој ќе се поврзе влезниот тек на друг процес.

Извор: www.habr.com

Додадете коментар