Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
5. ОC.docx
Скачиваний:
6
Добавлен:
01.05.2025
Размер:
397 Кб
Скачать
☆
  1. Сигнали. Функція wait, waitpid. Функція exec.

Сигнал в UNIX, Unix-подібних и других POSIX-сумісніх операційніх системах є одним з способів взаємодії между процесами. Фактично, сигнал - це асинхронним ПОВІДОМЛЕННЯ процеса про будь-яку подію. Колі сигнал послань процеса, операційна система переріває Виконання процеса. Если процес ВСТАНОВИВ власний обробнік сигналом, операційна система запускає цею обробнік, передавши Йому інформацію про сигнал. Если процес НЕ ВСТАНОВИВ обробнік, то віконується обробнік за умовчанням.

Назви сігналів «SIG ...» є числові константи (макровізначень Сі) Зі значень, обумовлених в заголовному файлі signal.h. Чіслові Значення сігналів могут змінюватіся від системи до системи, хочай основна їх частина має в різніх системах одні й ті ж значення. Утіліта kill дозволяє задаваті сигнал як числом, так и символьних позначені.

Оброблювач за замовчуванням для більшості сігналів завершує Виконання процеса. Для альтернатівної ОБРОБКИ всех сігналів, за вінятком SIGKILL и SIGSTOP, процес может Призначити свой обробнік або ігноруваті їх Виникнення модіфікацією своєї сігнальної маски.

Безпека - процес (або користувач з шелла) з ефективного UID, что НЕ рівнім 0 (UID суперкорістувача), может посілаті сигналі Тільки процесам з тим же UID.

Сигнал Дає можлівість Завдання реагуваті на подію, Джерелом Якого может буті операційна система або Інша задача. Сигнал віклікають переривані Завдання и Виконання заздалегідь Передбачення Дій. Сигнал могут віроблятіся синхронно, тоб як результат роботи самого процеса, а могут буті спрямовані процеса іншім процесом; тоб віроблятіся асинхронно. Сінхронні сигналі найчастіше приходять від системи переривані процесора и свідчать про Дії процеса, заблокованості апаратурою, Наприклад Розподіл на нуль, помилка адресації, Порушення захисту пам'яті и т.д.

Прикладом асинхронного сигналу є сигнал з терміналу. У багатьох ОС передбачається оперативніше зняття процеса з Виконання. Для цього користувач может натиснута Деяк комбінацію клавіш (Ctrl + C, Ctrl + Break), в результаті чого ОС віробляє сигнал и Направляє его активного процеса. Сигнал может надійті в будь-який момент Виконання процеса (тоб ВІН є асинхронним), вімагаючі від процеса негайного Завершення роботи. У даним випадка реакцією на сигнал є безумовна Завершення процеса.

Сигнал Забезпечують логічний зв'язок между процесами, а такоже между процесами та Користувачами (терміналамі). Оскількі посилка сигналу передбачає знання ідентіфікатора процеса, то Взаємодія помощью сігналів Можливо Тільки между спорідненімі процесами, Які могут отріматі дані про ідентіфікаторі один одного.

У розподіленіх системах, что складаються з декількох процесорів, шкірні з якіх має ВЛАСНА оперативну пам'ять, блокуючі змінні, семафор, сигналі та Другие аналогічні засоби, засновані на пам'яті, что розділяється, віявляються непригодна. У таких системах сінхронізація может буті реалізована Тільки за помощью обміну повідомленнями.

Функція wait, waitpid

Батьківський процес використовує системні виклики wait і waitpid для переходу в режим очікування завершення породженого процесу і для вибірки його статусу завершення (присвоєного породженим процесом за допомогою функції exit). Крім того, ці виклики звільняють клітинку таблиці процесів породженого процесу з тим, щоб вона могла використовуватися новим процесом. Прототипи цих функцій виглядають так:

# Include <sys/wait.h> pid t wait (int * status p);

pid t waitpid (pid t child pid, int * status p, int options)

Функція wait призупиняє виконання батьківського процесу до тих пір, поки йому не буде посланий сигнал, або поки один з його породжених процесів не завершиться, чи не буде зупинений (а його статус ще буде повідомлений). Якщо породжений процес вже завершився або був зупинений до виклику wait, функція wa/f негайно повернеться зі статусом завершення породженого процесу (його значення міститься в аргументі statusjp), а повертається значенням функції буде PID породженого процесу. Якщо, проте, батьківський процес не має породжених процесів, завершення яких він очікує, або був перерваний сигналом при виконанні wait, функція повертає значення -1, а змінна еггпо буде містити код помилки. Слід зазначити, що якщо батьківський процес створив більше одного породженого, функція wait буде очікувати завершення будь-якого з них.

Функція waitpid є більш універсальною порівняно з wait. Як і wait, функція waitpid повідомляє код завершення і ідентифікатор породженого процесу по його завершенні. Однак у випадку з waitpid в зухвалій

Функция exec

Системний виклик exec змушує викликає процес змінити свій контекст і виконати іншу програму. Є шість версій системного виклику exec. Всі вони виконують одну й ту ж функцію, але відрізняються один від одного аргументами.

Ось Прототипи функцій exec;

# Include <unistd.h>

int exec / (const char * path, const char * arg, ...);

int exec / {o (const char * file, const char * arg, ...);

int exec / e (const char * path, const char * arg, const char ** env);

int execv (const char * path, const char ** argv, ...);

int exectp (const char * file, const char ** argv, ...);

int execve (const char * path, const char ** argv, const char ** env);

Перший аргумент функції є або повним колійним ім'ям, або ім'ям файлу програми, що підлягає виконанню. Якщо виклик проходить успішно, дані і команди викликає процесу, що зберігаються в пам'яті, перекриваються даними і командами нової програми. Процес починає виконання нової програми з її перших рядків. Після завершення виконання нової програми код завершення процесу передається назад батьківському процесу. Слід звернути увагу, що на відміну від fork, що створює породжений процес, який виконується незалежно від батьківського, exec лише змінює зміст викликає процесу для виконання іншої програми.

Виклик exec може бути невдалим, якщо до програми, яка підлягає виконанню, немає доступу або якщо вона не має дозволу на вьшолненіе. Далі, програма, зазначена у першому аргументі виклику exec, повинна бути виконуваним файлом (які мають, наприклад, формат a.out). У UNIX, однак, можна вказати ім'я сценарію shell для викликів execlp і execvp, щоб я ipo UNIX для інтерпретації сценарію shell активізувало Bourne-shell i/bin/sh). Так як в POSIX. 1 shell не визначений, застосування execlp або execvp для виконання сценаріїв shell не припустимо. Насправді це не є проблемою, тому що користувачі завжди можуть активізувати-hell викликом exec, вказавши при цьому ім'я того сценарію, який потрібно виконати.

Суфікс р у викликах execlp і execvp вказує, що якщо фактичне значення аргументу fde починається не з /, то функції при пошуку підлягає виконанню файлу будуть використовувати змінну середовища PATH. Для всіх інших функцій exec фактичним значенням їх першого аргументу повинно бути колійне ім'я файлу, що підлягає виконанню.

Аргументи arg і argv є аргументами також для програми, викликаної функцією exec. Вони відображаються в змінну argv функції main нової програми. Для функцій execl, execlp і execle аргумент arg Відображається в argvfOJ, значення, вказане після arg, - у argvflj і т.д. Список аргументів, наявний у виклику exec, повинен завершитися значенням NULL, щоб вказати функції, де необхідно припинити пошук значень аргументу. Для функцій execv, execvp і execve аргумент argv є масивом (вектором) покажчиків на символьні рядки, де кожен рядок являє собою одне значення аргументу. Аргумент argv відображається безпосередньо в змінну argv функції main нової програми. Так, символ / в імені функції exec вказує на те, що значення аргументу передаються у вигляді списку, а символ v в цьому імені означає, що аргументи передаються у векторному форматі.

Слід зауважити, що в кожному виклику exec необхідно вказувати принаймні два значення аргументів. Перше значення (arg або argv [0]) - це ім'я програми, яка підлягає виконанню; воно відображається в argvfOJ функції main нової програми. Другий обов'язковий аргумент - значення NULL, заверщают список аргументів (для execl, execlp і execle) або вектор аргументів (для execv, execvp і execve).

Суфікс е функції exec {execle або execve) вказує, що останній аргумент {env) виклику функції є масивом (вектором) покажчиків на символьні рядки. Тут кожен рядок визначає одну змінну середовища і її значення в форматі Bourne-shell:

<Ім'я змінної середовища> = <значення>

Останній елемент env повинен бути NULL, що сигналізує про закінчення списку. У середовищі, відмінної від ANSI С, значення env буде присвоєно третій параметру функції main виконуваної програми. У середовищі ANSI З функція main може мати тільки два аргументи {argc і argv), а env відображається в глобальну змінну environ виконуваної програми. При виклику в процесі функцій execl, execlp і execvp глобальна змінна environ не змінюється (слід зазначити, що значення змінної environ можна оновити, використовуючи функцію putenv).

Якщо виклик exec успещен, сегменти стека, даних і тексту первісного процесу замінюються новими сегментами, що відносяться до виконуваної програмі. Однак таблиця дескрипторів файлів процесу залишається незмінною. Ті з файлових дескрипторів, чиї прапори close-on-exec були встановлені (системним викликом fcntl), будуть закриті перед виконанням нової програми. Під час виконання програми за допомогою API exec можливі такі зміни атрибутів процесу:

Ефективний ідентифікатор користувача: змінюється, якщо для виконуваної програми встановлений біт зміни ідентифікатора користувача set-UID.

Ефективний ідентифікатор групи: змінюється, якщо для виконуваної програми встановлений біт зміни ідентифікатора групи set-GID.

Встановлений код користувача: змінюється, якщо для виконуваної програми встановлений set-UID.

Параметри обробки сигналів: для сигналів, визначених у процесі як перехоплювали, встановлюється режим обробки за замовчуванням, коли процес починає виконання нової програми. Визначаються користувачем функції-обробники сигналів у виконуваній програмі відсутні.

Більшість програм викликають exec у породженому процесі, так як виконання батьківського процесу після виклику exec бажано продовжувати. Однак виклики fork і exec реалізуються в якості двох роздільних функцій. Це відбувається з наступних причин:

Реалізувати / ог /: і exec роздільно простіше.

Програма може викликати exec без fork, а fork без exec. Це забезпечує гнучкість у використанні цих функцій.

Багато програм будуть виробляти певні операції в породжених процесах, наприклад такі, як перепризначення стандартного вводу-виводу у файли перед викликом exec. Це стає можливим завдяки поділу API fork і exec.

Использование API exec демонстрируется на примере ТТрограммы test exec.C:

finclude <iostream.hWib, о

tinclude <stdio.h>

#include <stdlib.h>

♦include <errno.h>

tinclude <sys/types.h>

tinclude <sys/wait.h>

tincludS<unistd.h>

эмуляция С-функции system

int System( const char *cmd) {

pid t pid; int status; switch (pid=fork())

i =; , .case -1: return -1;

;.caseO: execl ( /bin/sh , sh , -c , cmd, 0);

perrot( execl ) ; exit(errno);

Ьу.л;

if (waitpid(pid,&status,0)==pid && WIFEXITED(status;

return WEXITSTATUS(status); return -1;

int main() {

int char

do -

rc = 0; buf[256];

printf( sh> ); if (.gets (buf)) rc = System(buf! } while (!rc); return (rc);

fflush,(stdout) break;

наведена вище програма є простою програмою, емулює shell UNIX. Вона запрошує користувача подавати команди shell на стандартне введення і виконує кожну команду за допомогою функції System. Програма завершується, коли користувач вводить або ознака кінця файлу ([Ctrl + D]) в командному рядку shell, або коли статус повернення виклику System не дорівнює нулю. Ця програма відрізняється від shell UNIX тим, що не підтримує команду cd і операції з змінними shell.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]