};
Init (semaphore)
struct semaphore semaphore;
{
semaphore.lock = 1;
}
Pprim (semaphore)
struct semaphore semaphore;
{
while (read_and_clear (semaphore.lock));
}
Vprim (semaphore)
struct semaphore semaphore;
{
semaphore.lock = 1;
}
Процес повторює інструкцію read and clear в циклі до тих пір, поки не буде лічено значення, відмінне від нуля. Початкове значення компоненти семафора, пов'язаної з блокуванням, має дорівнювати 1. Як таку, дану семафорної конструкцію не можна реалізувати у складі ядра операційної системи, оскільки працює з ній процес не виходить з циклу, поки не досягне своєї мети. Якщо семафор використовується для блокування структури даних, процес, виявивши семафор заблокованим, призупиняє своє виконання, щоб ядро ​​мало можливість переключитися на контекст іншого процесу і виконати іншу корисну роботу. За допомогою функцій Pprim і Vprim можна реалізувати більш складний набір семафорних операцій, відповідний тому складу, який визначено у розділі "Визначення семафорів". Для початку дамо визначення семафора як структури, складається з поля блокування (керуючого доступом до семафора), значення семафора і черги процесів, призупинених по семафору. Поле блокування містить інформацію, що відкриває під час виконання операцій типу P і V доступ до інших полів структури тільки одному процесу. По завершенні операції значення поля скидається. Це значення визначає, чи дозволений процесу доступ до критичного ділянці, захищаємий семафора.
Алгоритм операції P:
/*
Операція над семафором типу P
вхідна інформація:
(1) семафор;
(2) пріоритет;
вихідна інформація:
0 - у разі нормального завершення;
1 - у разі аварійного виходу зі стану приостанова по cігналу, прийнятому в режимі ядра;
*/
{
Pprim (semaphore.lock);
зменшити (semaphore.value);
якщо (semaphore.value> = 0)
{
Vprim (semaphore.lock); повернути (0);
}
/* слід перейти в стан приостанова */
якщо (перевіряються сигнали)
{
якщо (мається сигнал, перериваючий знаходження в стані приостанова)
збільшити (semaphore.value);
якщо (сигнал прийнятий в режимі ядра)
{
Vprim (semaphore.lock);
повернути (-1);
}
в іншому випадку
{
Vprim (semaphore.lock);
longjmp;
}
}
}
поставити процес в кінець списку призупинених по семафору;
Vprim (semaphore.lock);
виконати перемикання контексту;
перевірити сигнали (див. вище);
повернути (0);
}
На початку виконання алгоритму операції P ядро ​​за допомогою функції Pprim надає процесу право виключного доступу до семафора і зменшує значення семафора. Якщо семафор має невід'ємне значення, поточний процес отримує доступ до критичного ділянці. По завершенні роботи процес скидає блокування семафора (за допомогою функції Vprim), відкриваючи доступ до семафора для інших процесів, і повертає ознака успішного завершення. Якщо ж в результаті зменшення значення семафора стає негативним, ядро ​​призупиняє виконання процесу, використовуючи алгоритм, подібний алгоритмом sleep: грунтуючись на значенні пріоритету, ядро перевіряє надійшли сигнали, включає поточний процес у список призупинених процесів, в якому останні представлені в порядку надходження, і виконує перемикання контексту.
Алгоритм V
/*
Операція над семафором типу V
вхідна інформація: адреса семафора
вихідна інформація: відсутня
*/
{
Pprim (semaphore.lock);
збільшити (semaphore.value);
якщо (semaphore.value <= 0)
{
видалити з списку процесів, призупинених по семафору, перший за рахунком процес;
перевести його в стан готовності до запуску;
}
Vprim (semaphore.lock);
}
Операція V отримує винятковий доступ до семафора через функцію Pprim і збільшує значення семафора. Якщо чергу призупинених по семафору процесів непорожній, ядро вибирає з неї перший процес і переводить його в стан "готовності до запуску ". Операції P і V по своїй дії схожі на функції sleep і wakeup. Головна відмінність між ними полягає в тому, що семафор є структурою даних, тоді як використовуваний функціями sleep і wakeup адресу являє собою всього лише число. Якщо початкове значення семафора - нульове, при виконанні операції P над семафором процес завжди призупиняється, тому операція P може замінювати функцію sleep. Операція V, проте, виводить зі стану приостанова тільки один процес, тоді як однопроцесорна функція wakeup відновлює всі процеси, припинені за адресою, пов'язаному з подією. З точки зору семантики ви...