Операциялык системалар: үч жеңил даана. 3-бөлүк: Process API (котормо)

Операциялык системаларга киришүү

Эй Хабр! Мен сиздердин назарыңыздарга менин оюмча бир кызыктуу адабияттын бир катар макала-котормолорун келтиргим келет - OSTEP. Бул материалда Unix сыяктуу операциялык системалардын иши, тактап айтканда, процесстер, ар кандай пландоочулар, эс тутум жана заманбап ОСти түзгөн башка ушул сыяктуу компоненттер менен иштөө абдан терең талкууланат. Бардык материалдардын түп нускасын бул жерден көрө аласыз бул жерде. Көңүл буруңуз, котормо профессионалдуу эмес (абдан эркин) жасалган, бирок мен жалпы маанини сактап калдым деп ишенем.

Бул тема боюнча лабораториялык иштерди бул жерден тапса болот:

Башка бөлүктөр:

Ошондой эле менин каналымды текшере аласыз телеграмма =)

Алярм! к этой лекции есть лаба! смотри гитхаб

Process API

Рассмотрим пример создания процесса в UNIX системе. Он происходит через два системных вызова айры () и exec().

Вызов fork()

Операциялык системалар: үч жеңил даана. 3-бөлүк: Process API (котормо)

Рассмотрим программу, которая выполняет вызов fork(). Результат ее выполнения будет следующим.

Операциялык системалар: үч жеңил даана. 3-бөлүк: Process API (котормо)

В первую очередь мы входим в функцию main() и выполняем вывод строки на экран. Строка содержит идентификатор процесса который в оригинале называется PID или process identifier. Этот идентификатор применяется в UNIX для того чтобы обращаться к процессу. Следующей командой будет выполнен вызов fork(). В этот момент создается практически точная копия процесса. Для ОС это выглядит так, что в системе запущены как будто бы 2 копии одной и той же программы, которые в свою очередь выйдут из выполнения функции fork(). Вновь созданные процесс-потомок (по отношению к создавшему его процессу-родителю) уже не будет выполняться, начиная с функции main(). Следует помнить, что процесс-потомок не является точной копией процесса-родителя, в частности у него есть собственное адресное пространство, собственные регистры, свой указатель на исполняемые инструкции и тому подобное. Таким образом, значение, возвращаемое вызывателю функции fork() будет разным. В частности, процесс-родитель получит в качестве возврата значение PID процесса ребенка, а ребенок получит значение равное 0. По этим кодам возврата в дальнейшем уже можно разделять процессы и заставлять каждый из них выполнять свою работу. При этом выполнение данной программы не определено строго. После разделения на 2 процесса ОС начинает следить за ними, так же, и планировать их работу. В случае выполнения на одноядерном процессоре, работу продолжит один из процессов, в данном случае — родительский, а затем управление получит процесс-потомок. При повторном запуске ситуация может сложиться иначе.

Вызов wait()

Операциялык системалар: үч жеңил даана. 3-бөлүк: Process API (котормо)

Рассмотрим следующую программу. В этой программе за счет наличия вызова күтө () процесс-родитель всегда будет дожидаться завершения работы процесса-потомка. В этом случае мы получим строго определенный вывод текста на экран

Операциялык системалар: үч жеңил даана. 3-бөлүк: Process API (котормо)

Вызов exec()

Операциялык системалар: үч жеңил даана. 3-бөлүк: Process API (котормо)

Рассмотрим вызов exec(). Этот системный вызов полезен, когда мы хотим запустить совершенно другую программу. Здесь мы будем вызывать execvp() для запуска программы wc, которая является программой подсчета слов. Что же происходит при вызове exec()? Этому вызову передаются в качестве аргументов имя исполняемого файла и некоторые параметры. После чего происходит загрузка кода и статических данных из этого исполняемого файла и перезатирание собственного сегмента с кодом. Остальные участки памяти, такие как стек и куча переинициализируются. После чего ОС просто исполняет программу, передавая ей набор аргументов. Таким образом, мы не создавали новый процесс, мы просто трансформировали текущую запущенную программу в другую запущенную программу. После выполнения вызова exec() в потомке наступает впечатление, что изначальная программа как будто бы в принципе не запускалась.

Такое усложнение запуска абсолютно нормально для shell оболочки Unix, и позволяет этой оболочке исполнять код после вызова айры (), но до вызова exec(). Примером такого кода может быть подстройка окружения оболочки под нужды запускаемой программы, перед ее непосредственным запуском.

жумуртканын кабыгы — всего лишь пользовательская программа. Она показывает вам строку приглашения и ждет, пока вы в него что-нибудь напишете. В большинстве случаев если написать туда имя программы, shell найдет его месторасположение, вызовет метод fork(), а затем чтобы создать новый процесс вызовет какой-либо из типов exec() и дождется его выполнения с помощью вызова wait(). Когда процесс-потомок завершится shell вернется из вызова wait() и выведет снова строку приглашения и будет ждать ввода следующей команды.

Разделение fork() & exec() позволяет shell делать следующие вещи, например:
wc file > new_file.

В этом примере вывод программы wc перенаправлен в файл. Способ, которым shell достигает этого достаточно прост — при создании процесса-ребенка перед вызовом exec(), shell закрывает стандартный поток вывода и открывает файл new_file, таким образом, весь вывод из далее запущенной программы wc будет перенаправлен в файл вместо экрана.

Unix pipe реализованы похожим образом, с разницей, что они используют вызов pipe(). В этом случае поток вывода процесса будет подключен к очереди pipe, расположенной в ядре к которой же будет присоединен поток ввода другого процесса.

Source: www.habr.com

Комментарий кошуу