Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
вступ, ст 22-93.doc
Скачиваний:
5
Добавлен:
02.09.2019
Размер:
1.62 Mб
Скачать

Системні виклики для управління процессами

Перша група в табл. 1.1 управляє процесами. Почнемо розгляд з виклику

fork. Системний виклик fork (розгалуження) є єдиним способом створення нового процесу в UNIX. Він створює точну копію вихідного процесу, включаючи дескриптори файлу, регістри і т. п. Після виклику fork вихідний процес

і його копія (батьківський і дочірній) розвиваються окремо один від одного.

Всі змінні мають однакові величини під час виклику fork, але як тільки

батьківські дані скопійовані для створення дочірнього процесу, подальші зміни в одному з них вже не впливають на інший. (Текст програми, який не змінюється, розподіляється між батьківським і дочірнім процесами). Виклик fork повертає величину, рівну нулю в дочірньому процесі і рівну ідентифікатору дочірнього процесу або PID в батьківському. Використовуючи повернутий PID, два процеси можуть розрізнити, який з них батьківський, а дочірній.

У більшості випадків після виклику fork дочірньому процесу необхідно виконати програмний код, відмінний від призначеного для батьківського процесу. Розглянемо приклад оболонки. Вона читає команди з терміналу, запускає

дочірній процес, чекає, поки дочірній процес виконає команду, і читає наступну команду після завершення роботи дочірнього процесу. Чекаючи, поки дочірній процес закінчить роботу, батьківський процес виконує системний

виклик waitpid, який очікує завершення дочірнього процесу (або всіх дочірніх процесів, якщо їх на даний момент декілька). Waitpid може чекати вікон закінчення якого-небудь певного дочірнього процесу або будь-якого дочірнього

процесу, для цього потрібно задати перший параметр виклику дорівнює -1. Коли waitpid виконаний, покажчик, що задається другим параметром statloc, буде встановлений на статус завершення дочірнього процесу (нормальне або аварійне завершення і вихідне значення). Третій параметр визначає різні необов'язкові

налаштування. Тепер розглянемо, як виклик fork використовується оболонкою. Коли друкується команда, оболонка створює дочірній процес, який повинен виконати команду користувача. Він робить це за допомогою системного виклику execve, заміняє весь його образ пам'яті файлом, названим у першому параметрі. (Фактично самим системним викликом є ​​exec, але кілька різних бібліотечних

процедур викликають його з різними параметрами і незначно відрізняються

іменами. Ми тут скористаємося ними як системними викликами.) Дуже спрощена оболонка, що ілюструє використання команд fork, waitpid і execve

показана в лістингу 1.1.

Лістинг 1.1. Усічена оболочка1

У самому загальному випадку у команди execve є три параметри: ім'я файлу,

який буде виконуватися, покажчик на масив аргументів і покажчик на масив

змінних оточення. Ці параметри ми коротко обговоримо надалі.

Різні бібліотечні програми, включаючи execl, execv, execle і execve, дозволяють пропускати параметри або визначати їх іншими способами. У книзі ми скористаємося назвою exec для того, щоб представити системний виклик, що викликається всіма цими процедурами.

Розглянемо наступну команду:

ср filel file2

яка використовується для копіювання файлу filel в файл file2. Після створення

оболонкою дочірнього процесу останній знаходить і виконує файл ср і передає йому імена вихідного та цільового файлів.Основний модуль програми ср (як і більшість інших головних програмна С) містить визначення:

main (argc, argv. envp)в якому в параметр argc входить кількість записів в командному рядку, включаючи ім'я програми. Наприклад, для рядка вгорі argc дорівнює 3.

Другий параметр argv є покажчиком на масив покажчиків. Елемент i

масиву вказує на г-ю запис в командному рядку. У нашому прикладі argv[0]

повинен вказувати на слово «ср», a argv[l] и argv[2] — на слова «filel» и «file2» відповідно.

Третій параметр функції main, envp, є покажчиком на масив строкових

змінних оточення виду ім'я = величина, які використовуються для передачі

програмі такої інформації, як тип терміналу або ім'я домашнього каталогу.

У лістингу 1.1 третій параметр дорівнює нулю, оскільки нічого не передається

дочірньому процесу. Якщо команда exec здається складною, не засмучуйтесь, бо це один знайбільш складних системних викликів в POSIX. Всі інші набагато простіше. В якості ще одного прикладу розглянемо exit, процеси повинні використовувати його при завершенні роботи. У нього є всього один параметр, статус виходу, змінюється від 0 до 255. Він повертається батьківському процесові через парамет statloc в системному виклику waitpid.

У UNIX під процеси відводиться частина пам'яті, яка, в свою чергу, ділиться

на три сегменти: текстовий (тобто код програми), сегмент даних (змінних

(Змінні) і сегмент стека. Сегмент даних зростає знизу вверх, а стек збільшується

зверху вниз, як показано на рис 1.18. Між ними існує частина невикористаного адресного простору. Стек автоматично займає таку частину цього ділянки пам'яті, яку необхідно, але розширення сегмента даних виконується явно. Для цього використовується спеціальний системний виклик brk, задає нову адресу для межі сегменту даних. Однак цей виклик не визначено стандартами POSIX, так як програмістам для динамічного розподілу озподілу пам'яті рекомендується використовувати бібліотечну процедуру malloc. Було вирішено, що низкоуровневу реалізацію процедури malloc не слід стандартизувати, бо мало хто викликає її безпосередньо.

Рис. 1.18. Під процеси відводиться три сегменти: текст, дані і стек