Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекція № 4_МЗКІТ (10 ТП).docx
Скачиваний:
1
Добавлен:
01.07.2025
Размер:
2 Мб
Скачать
☆

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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