69773

Керування процесами в UNIX і Linux

Лекция

Информатика, кибернетика и программирование

Образ процесу В UNIXсистемах образ процесу містить такі компоненти: керуючий блок процесу; код програми яку виконує процес; стек процесу де зберігаються тимчасові дані параметри процедур повернені значення локальні змінні тощо; глобальні дані спільні для всього процесу.

Украинкский

2014-10-10

50.5 KB

9 чел.

Тема 3. Керування процесами в UNIX і Linux.

3.1. Образ процесу

В UNIX-системах образ процесу містить такі компоненти:

керуючий блок процесу;

код програми, яку виконує процес;

стек процесу, де зберігаються тимчасові дані (параметри процедур, повернені значення, локальні змінні тощо);

глобальні дані, спільні для всього процесу.

Для кожного компонента образу процесу виділяють окрему ділянку пам'яті. У розділі 9 буде докладно розглянуто структуру різних ділянок пам'яті процесу та особливості їхнього використання.

3.2. Ідентифікаційна інформація та атрибути безпеки процесу.

Із кожним процесом у системі пов'язана ідентифікаційна інформація.

Ідентифікатор процесу (pid) є унікальним у межах усієї системи, і його використовують для доступу до цього процесу. Ідентифікатор процесу і nit завжди дорівнює одиниці.

Ідентифікатор процесу-предка (ppid) задають під час його створення. Будь-який процес має мати доступ до цього ідентифікатора. Так в UNIX-системах обов'язково підтримується зв'язок «предок-нащадок». Якщо предок процесу Р завершує виконання, предком цього процесу автоматично стає і nit, тому ppid для Р дорівнюватиме одиниці.

Із процесом також пов'язаний набір атрибутів безпеки.

♦ Реальні ідентифікатори користувача і групи процесу (uid, gid) відповідають
користувачеві, що запустив програму, внаслідок чого в системі з'явився відпо
відний процес.

Ефективні ідентифікатори користувача і групи процесу (euid, egid) використовують у спеціальному режимі виконання процесу — виконанні з правами власника. Цей режим буде розглянуто у розділі 16.

3.3. Керуючий блок процесу

Розглянемо структуру керуючого блоку процесу в Linux і відмінності його реалізації у традиційних UNIX-системах [58, 95].

Керуючий блок процесу в Linux відображається структурою даних task_struct. До найважливіших полів цієї структури належать поля, що містять таку інформацію:

ідентифікаційні дані (зокрема pid — ідентифікатор процесу);

стан процесу (виконання, очікування тощо);

покажчики на структури предка і нащадків;

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

стан процесора (вміст регістрів і лічильник інструкцій);

атрибути безпеки процесу (uid, gid, euid, egid).

Зазначимо, що в ядрі Linux відсутня окрема структура даних для потоку, тому інформація про стан процесора міститься в керуючому блоці процесу.

Крім перелічених вище, task_struct має кілька полів спеціалізованого призначення, необхідних для різних підсистем Linux:

відомості для обробки сигналів;

інформація для планування процесів;

♦ інформація про файли і каталоги, пов'язані із процесом;

структури даних для підсистеми керування пам'яттю.

Дані полів task_struct можуть спільно використовувати декілька процесів спеціалізованого призначення, у цьому випадку такі процеси фактично є потоками. Докладніше дане питання буде розглянуте під час вивчення реалізації багатопотоковості в Linux.

Керуючі блоки процесу зберігаються в ядрі у спеціальній структурі даних. До появи ядра версії 2.4 таку структуру називали таблицею процесів системи; це був масив, максимальна довжина якого не могла перевищувати 4Кбайт. У ядрі версії 2.4 таблиця процесів була замінена двома динамічними структурами даних, що не мають такого обмеження на довжину:

♦ хеш-таблицею (де в ролі хеша виступає pid процесу), ця структура дає змогу швидко знаходити процес за його ідентифікатором;

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

Тепер обмеження на максимальну кількість процесів перевіряється тільки всередині реалізації функції fork () і залежить від обсягу доступної пам'яті (наприклад, є відомості [58], що у системі з 512 Мбайт пам'яті можна створити близько 32 000 процесів).

Реалізація керуючого блоку в Linux відрізняється від його традиційної реалізації в UNIX-системах. У більшості версій UNIX (System V, BSD) керуючий блок процесу складається з двох структур даних — структури процесу (ргос) і структури користувача (и).

Структура процесу містить інформацію, необхідну протягом усього часу існування процесу (зокрема, коли він вивантажений на диск). Це такі дані, як pid, ефективний uid, пріоритет, покажчик на структуру користувача. Структури процесу поєднуються в черзі процесів у системі. Структура користувача містить інформацію, необхідну тільки під час виконання процесу (стан процесора, uid, gid, поточний каталог, інформацію про відкриті файли).

3.4. Створення процесу

Реалізація fork() в Linux

В UNIX-сумісних системах процеси створює вже відомий нам системний виклик fork(). Розглянемо його реалізацію в Linux.

Виділяють пам'ять для нового керуючого блоку процесу (task_struct). Якщо пам'яті недостатньо, повертається помилка.

Усі значення зі структури даних предка копіюють у структуру даних нащадка. Після цього поля, значення яких мають відрізнятися від вихідних, будуть змінені.

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

Для процесу генерується ідентифікатор (pid), при цьому використовують спеціальний алгоритм, що гарантує унікальність.

Для нащадка копіюють необхідні додаткові структури даних предка (таблицю дескрипторів файлів, відомості про поточний каталог, таблицю оброблювачів сигналів тощо).

Формують адресний простір процесу.

Структуру даних процесу поміщають у список і хеш-таблицю процесів системи.

Процес переводять у стан готовності до виконання.

Використання fork() у прикладних програмах

Розглянемо приклад використання системного виклику fork () для створення процесу. Опис fork () відповідно до POSIX виглядає так:

#include <um'std.h>

pid_t forkO;     // тип pid_t є цілим

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

Для нащадка fork() повертає нуль, а для предка - ідентифікатор (pid) створеного процесу-нащадка. Коли з якоїсь причини нащадок не був створений, forkO поверне -1. Тому звичайний код роботи з fork() має такий вигляд:

pid_t pid;

if ((pid = fork()) == -1) { /* помилка, аварійне завершення */ }

if (pid - 0) { // це нащадок

}

else {

//це предок

printf ("нащадок запущений з кодом %d/п".  pid);

}

Після створення процесу він може дістати доступ до ідентифікаційної інформації за допомогою системного виклику getpidO, який повертає ідентифікатор поточного процесу, і getppidO, що повертає ідентифікатор процесу-предка:

#include <iinistd.h>

pid_t mypid, parent_pid;

mypid = getpid();

parent_pid = getppid();

3.5. Завершення процесу

Для завершення процесу в UNIX-системах використовують системний виклик _exit(). Розглянемо реалізацію цього системного виклику в Linux. Під час його виконання відбуваються такі дії.

Стан процесу стає TASK_ZOMBIE (зомбі, про цей стан див. нижче).

Процес повідомляє предків і нащадків про те, що він завершився (за допомогою спеціальних сигналів).

Звільняються ресурси, виділені під час виклику fork().

Планувальника повідомляють про те, що контекст можна перемикати.

У прикладних програмах для завершення процесу можна використати безпосередньо системний виклик _exit() або його пакувальник - бібліотечну функцію exit(). Ця функція закриває всі потоки процесу, коректно вивільняє всі ресурси і викликає _exit() для фактичного його завершення:

#і псіude<unistd.п>

void _exit(int status); // status задає код повернення

#include<stdlib.h>

void exit(int status); // status задає код повернення

exit (128);        // вихід з кодом повернення 128

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

Контрольні питання:

1. Образ процесу.

2. Ідентифікаційна інформація та атрибути безпеки процесу.

3. Керуючий блок процесу UNIX.

4. Створення процесу UNIX.

5. Завершення процесу UNIX.


 

А также другие работы, которые могут Вас заинтересовать

17117. Розробка програм зі складеними типами даних 334.5 KB
  Лабораторна робота № 26 Тема: Розробка програм зі складеними типами даних Ціль: виробити практичні навички в написанні програм з використанням комбінованих типів даних. Обладнання: ПКПО Borland C Теоретичні відомості Структури З підтримує визначений корист
17118. Використання покажчиків для роботи зі складеними типами даних 98 KB
  Лабораторна робота № 27 Тема: Використання покажчиків для роботи зі складеними типами даних Ціль роботи: виробити практичні навички у використанні покажчиків при роботі зі складеними комбінованими типами даних. Обладнання: ПКПО Borland C Теоретичні відомості ...
17119. Використання покажчиків для роботи з функціями 95.5 KB
  Лабораторна робота № 28 Тема: Використання покажчиків для роботи з функціями Ціль роботи: виробити практичні навички в написанні програм з функціями й у використання покажчиків для роботи з функціями. Обладнання: ПКПО Borland C Теоретичні відомості З дозволяє вик
17120. Розробка програм із багатофайлової структурою. Заголовні файли. Класи пам'яті перемінних і функцій 88.5 KB
  Лабораторна робота № 29 Тема: Розробка програм із багатофайлової структурою. Заголовні файли. Класи пам'яті перемінних і функцій. Ціль роботи: ознайомитися з написанням програм із багатофайлової структурою заголовними файлами вивчити класи пам'яті перемінних і функц
17121. Розробка програм з використанням класів 112 KB
  Лабораторна робота № 30 Тема: Розробка програм з використанням класів Ціль роботи: вивчити синтаксичні конструкції для оголошення визначення і використання класів. Розібратися з особливостями використання класів у мові С. Обладнання: ПКПО Borland C Теоретичні відо...
17122. Використання конструкторів і деструкторів 58 KB
  Лабораторна робота № 31 Тема: Використання конструкторів і деструкторів Ціль роботи: вивчити і навчитися використовувати механізм роботи з конструкторами і деструкторами. Обладнання: ПКПО Borland C Теоретичні відомості Конструктори і деструктори Існує кільк
17123. Використання спадкування для створення ієрархії класів 80.5 KB
  Лабораторна робота № 32 Тема: Використання спадкування для створення ієрархії класів Ціль роботи: одержати навички у використанні спадкування для створення похідних класів при простому спадкуванні. Обладнання: ПКПО Borland C Теоретичні відомості При оголошенні п...
17124. Використання віртуальних і покажчиків для роботи з об'єктами класів 51.5 KB
  Лабораторна робота № 33 Тема: Використання віртуальних і покажчиків для роботи з об'єктами класів Ціль роботи: вивчити і навчитися використовувати віртуальні функції в мові С. Обладнання: ПКПО Borland C Теоретичні відомості Віртуальні функціїчлени з'являються в к...
17125. Задачі курсу. Історичний огляд розвитку обчислювальної техніки. Операційна система (ОС) та її функції. Структура ОС 72 KB
  Лекція №1 Тема: Задачі курсу. Історичний огляд розвитку обчислювальної техніки. Операційна система ОС та її функції. Структура ОС. План Мета і задачі курсу. Призначення операційних систем. Функції операційних систем. Поняття операційного середовища. ...