Ціль: засвоєння способів використання сигналів для
синхронізації процесів.
Модель, реалізована в даній роботі, що випливає:
Ктулху "створює" Вантажівки й
відправляє їх на навантаження товару. Кожній Вантажівці Ктулху дає при
цьому випадкове виправлення до пріоритету. Кожна Вантажівка діє незалежно
від інших.
Умови навантаження й доставки - такі ж, як й
у попередній роботі.
Після закінчення 30-секундного інтервалу
Ктулху перевіряє стан породжених їм Вантажівок. Якщо Вантажівка завершила
свою діяльність, Ктулху виводить повідомлення про нормальне завершення
Вантажівки. Якщо Вантажівка ще не завершила свою діяльність, відбувається
перевірка, у якому стані перебуває Вантажівка. Якщо Вантажівці для закінчення
водопою потрібно не більше 1 сек процесорного часу, Вантажівка одержує
можливість закінчити доставку. У противному випадку Вантажівка
розбивається.
синхронізація дій процесів виконується в такий спосіб:
На самому початку свого виконання
процесс-Ктулху встановлює (за допомогою системного виклику signal власний оброблювач
сигналів SIGUSR1 й SIGUSR2 (один оброблювач на обидва
типи сигналу. Далі він працює так само, як і лабораторній роботі N1 - до
"занурення в сон" на 30 сек включно. Кожна процес-вантажівка на
початку виконання встановлюють власні оброблювачі сигналів SIGUSR1 й SIGTERM.
Повністю витримавши 30-секундний інтервал
процесс-Ктулху перебирає наявний у нього список процесів-вантажівок. Для
тих процесів, які були успішно запущені Ктулху виконує системний виклик waitpid. Якщо процес-вантажівка
до цього моменту вже завершився (успішно), то системний виклик поверне
його PID, по якому батьківський процес пізнає Вантажівки, що завершилося,
виведе повідомлення про його успішне завершення й позначить його у своєму
списку як завершився.
Якщо дочірній процес ще не завершився, то
процесс-Ктулху відправляє йому сигнал SIGUSR1. Оброблювач цього сигналу в процесі-вантажівці аналізує поточний
стан програми процесу. Якщо програма ще виконує операцію
"завантаження", процес-вантажівка відповідає батьківському
процесу сигналом SIGUSR1, якщо програма вже перейшла в стан "доставка" -
сигналом SIGUSR2.
Процесс-Ктулху (у своєму оброблювачі цих
сигналів) аналізує сигнал, отриманий від дочірнього процесу, і залежно від
типу сигналу встановлює в себе індикатор стану даного процесу. Потім
процесам, від яких був отриманий сигнал SIGUSR1, Ктулху відправляє сигнал SIGKILL, а процесам, від яких отриманий сигнал SIGUSR2, - сигнал SIGTERM.
Дочерний процес, що одержав сигнал SIGKILL, природно, примусово
завершується. Сигнал же SIGTERM попадає у відповідний оброблювач процесу-вантажівки. В
оброблювачі аналізується значення статичної змінної waitFactor, що у функції a0wait використається
як лічильник циклів зайнятого очікування. Якщо значення цієї змінної більше
1000 (що приблизно відповідає 1 сек), то оброблювач сигналу SIGTERM завершує процес системним
викликом exit с кодом
завершення 8. Якщо ж значення waitFactor менше 1000, оброблювач сигналу цього не робить, після обробки
сигналу процес-вантажівка продовжує працювати звичайним образом і
закінчується з кодом завершення 0.
Відправивши сигнали всім ще що не
завершилися дочірнім процесам, батьківський процес очікує їхнього завершення
за допомогою системного виклику wait
цей виклик повідомляє про завершення кожного з дочірніх процесів. При
виході з очікування батьківський процес визначає, який із процесів-нащадків
завершився, і по коду завершення визначає, чи завершилася
процес-вантажівка успішно (код завершення 0) або загинув (код, відмінний
від 0).
Системний виклик waitpid повторюється в циклі
доти, поки залишаються незавершені процеси.