- •Практичне заняття 8 Організація уведення-виведення в unix. Файли пристроїв. Апаратні переривання
- •Операції над файловими системами. Монтування файлових систем
- •Блокові, символьні пристрої. Поняття драйвера. Блокові, символьні драйвери, драйвери низького рівня. Файловий інтерфейс
- •Апаратні переривання (interrupt), виключення (exception), програмні переривання (trap, software interrupt). Їх обробка
- •Поняття сигналу. Способи виникнення сигналів і види їх обробки
- •Поняття групи процесів, сеансу, лідера групи, лідера сеансу, управляючого терміналу сеансу. Системні виклики getpgrp(), setpgrp(), getpgid(), setpgid(), getsid(), setsid()
- •Системний виклик kill() і команда kill
- •Вивчення особливостей отримання термінальних сигналів поточною і фоновою групою процесів
- •Системний виклик signal(). Установка власного обробника сигналу
- •Прогін програми, що ігнорує сигнал sigint
- •Прогін програми з призначеною для користувача обробкою сигналу sigint
- •Відновлення попередньої реакції на сигнал
- •Сигнали sigusr1 і sigusr2. Використовування сигналів для синхронізації процесів
- •Завершення породженого процесу. Системний виклик waitpid(). Сигнал sigchld
- •Прогін програми для ілюстрації обробки сигналу sigchld
- •Виникнення сигналу sigpipe при спробі запису в pipe або fifo, який ніхто не збирається читати
- •Поняття про надійність сигналів. Posix функції для роботи з сигналами
- •Питання до захисту роботи
Завершення породженого процесу. Системний виклик waitpid(). Сигнал sigchld
В матеріалах занять 3–4 (розділ "Завершення процесу. Функція exit()") при вивченні завершення процесу мовилося про те, що якщо процес-дитина завершує свою роботу раніше процесу-батька, і процес-батько явно не вказав, що він не зацікавлений в отриманні інформації про статус завершення процесу-дитини, то процес, що завершився, не зникає з системи остаточно, а залишається в стані закінчив виконання (зомбі-процес) або до завершення процесу-батька, або до того моменту, коли батько зволить одержати цю інформацію.
Для отримання такої інформації процес-батько може скористатися системним викликом waitpid() або його спрощеною формою wait(). Системний виклик waitpid() дозволяє процесу-батькові синхронно одержати дані про статус процесу-дитини, що завершився, або блокуючи процес-батько до завершення процесу-дитини, або без блокування при його періодичному виклику з опцією WNOHANG. Ці дані займають 16 біт і в рамках нашого курсу можуть бути розшифровані таким чином:
Якщо процес завершився за допомогою явного або неявного виклику функції exit(), то дані виглядають так (старший біт знаходиться зліва) :
Якщо процес був завершений сигналом, то дані виглядають так (старший біт знаходиться зліва):
Кожний процес-дитина при завершенні роботи посилає своєму процесу-батькові спеціальний сигнал SIGCHLD, на який у всіх процесів за умовчанням встановлена реакція "ігнорувати сигнал". Наявність такого сигналу сумісна з системним викликом waitpid() дозволяє організувати асинхронний збір інформації про статус породжених процесів, що завершилися, процесом-батьком.
Системні виклики wait() і waitpid()
#include <sys/types.h>
#include <wait.h>
pid_t waitpid(pid_t pid, int *status int options);
pid_t wait(int *status);
Опис системних викликів
Цей опис не є повним описом системних викликів, а адаптовано стосовно нашого курсу. Для отримання повного опису звертайтеся до UNIX Manual.
Системний виклик waitpid() блокує виконання поточного процесу до тих пір, поки або не завершиться породжений їм процес, визначуваний значенням параметра pid, або поточний процес не одержить сигнал, для якого встановлена реакція за умовчанням "завершити процес" або реакція обробки призначеною для користувача функцією. Якщо породжений процес, заданий параметром pid, до моменту системного виклику знаходиться в змозі закінчив виконання, то системний виклик повертається негайно без блокування поточного процесу.
Параметр pid визначає породжений процес, завершення якого чекає процес-батько, таким чином:
Якщо pid > 0 чекаємо завершення процесу з ідентифікатором pid.
Якщо pid = 0, то чекаємо завершення будь-якого породженого процесу в групі, до якої належить процес-батько.
Якщо pid = -1, то чекаємо завершення будь-якого породженого процесу.
Якщо pid < 0, але не –1, то чекаємо завершення будь-якого породженого процесу з групи, ідентифікатор якої рівний абсолютному значенню параметра pid.
Параметр options в нашому курсі може приймати два значення: 0 і WNOHANG. Значення WNOHANG вимагає негайного повернення з виклику без блокування поточного процесу у будь-якому випадку.
Якщо системний виклик знайшов породжений процес, що завершився, з числа специфікованих параметром pid, то цей процес віддаляється з обчислювальної системи, а за адресою, вказаною в параметрі status, зберігається інформація про статус його завершення. Параметр status може бути заданий рівним NULL, якщо ця інформація не має для нас значення.
При виявленні процесу, що завершився, системний виклик повертає його ідентифікатор. Якщо виклик був зроблений зі встановленою опцією WNOHANG, і породжений процес, специфікований параметром pid, існує, але ще не завершився, системний виклик поверне значення 0. У всій решті випадків він повертає негативне значення. Повернення з виклику, пов'язане з виникненням обробленого користувачем сигналу, може бути в цьому випадку ідентифіковано по значенню системної змінної errno == EINTR, і виклик може бути зроблений знову.
Системний виклик wait є синонімом для системного виклику waitpid із значеннями параметрів pid = -1, options = 0.
Використовуючи системний виклик signal(), ми можемо явно встановити ігнорування цього сигналу (SIG_IGN), тим самим проінформувавши систему, що нас не цікавить, яким чином завершаться породжені процеси. В цьому випадку зомбі-процесів виникати не буде, але і вживання системних викликів wait() і waitpid() буде заборонено.
