- •Вариант 1 Вопрос 1 Взаимодействие процессов в unix.
- •Вопрос2
- •Вопрос1 Синхронизация процессов
- •Вопрос2
- •Вопрос1
- •Применение семафоров
- •Вопрос2 Задача виробника/споживача
- •Void Produce() { /* Тут реалізація виробництва елементу chin */ }
- •Void Consume() { /* Тут реалізація використання елементу chout */ }
- •Void Producer() { // Це «оболонка безпеки» для процедури виробника
- •Void Consumer() { // Це «оболонка безпеки» для процедури споживача
- •Вопрос1 Засоби взаємних виключень та синхронізації процесів
- •3.9.1. Програмний підхід
- •3.9.2. Апаратна підтримка
- •Вопрос2
- •Механізми захисту ресурсів
- •Вопрос2
Вопрос1
Семафор - это защищенная переменная, значение которой можно опрашивать и менять только при помощи специальных операций wait и signal и операции инициализации init. Двоичные семафоры могут принимать только значения 0 и 1. Семафоры со счетчиками могут принимать неотрицательные целые значения.
Семафоры могут использоваться для контролирования доступа к ресурсам: число в семафоре представляет собой количество процессов, которые могут получить доступ к данным. Каждый раз, когда процесс обращается к данным, значение в семафоре, должно быть уменьшено на единицу, и увеличено, когда работа с данными будет прекращена. Если ресурс эксклюзивный, то есть к данным должен иметь доступ только один процесс, то начальное значение в семафоре следует установить единицей.
Семафоры можно использовать и для других целей, например для счётчика ресурсов. В этом случае число в семафоре — количество свободных ресурсов (например количество свободных ячеек памяти).
Применение семафоров
Вот некоторые из проблем, которые могут решать семафоры.
запрет одновременного выполнения заданных участков кода;
поочерёдный доступ к критическому ресурсу (важному ресурсу, для которого невозможен одновременный доступ).
Следующий пример показывает, как наладить поочерёдный доступ к консоли.
semaphore.init(1);
Поток 1:
semaphore.enter();
cout << "Состояние массива: ";
for (int i=0; i<n; i++)
cout << a[i] << ' ';
cout << '\n';
semaphore.leave();
Поток 2:
semaphore.enter();
cout << "Нажато Esc.\n";
semaphore.leave();
Этот код поможет предотвратить появление листинга наподобие
Состояние массива: 1 2 3 Нажато Esc.
4 5 6
Семафори в мовах програмування і ОС
Семафори — високорівневий механізм взаємних виключень, який може надаватися мовою програмування або ОС. Здається першою мовою програмування, що отримала семафори, став Algol-68. Примітиви, які ми назвали wait і signal, в Algol-68 отримали імена down і up відповідно.
Інша класична мова програмування, що підтримує синхронізацію процесів за
допомогою семафорів, – Modula-2. Рекомендований автором мови Н. Віртом як стандартний модуль визначень Processes приведений в ліст. 3.7:
Лістинг 3.7.
DEFINITION MODULE Processes;
TYPE SIGNAL;
PROCEDURE StartProcess(P:PROC; n:CARDINAL); (* Почати паралельний процес, що задається програмою Р з робочою областю розміром n *)
PROCEDURE SEND(VAR s:SIGNAL); (* Відновлює один з процесів,
що чекають на s *)
PROCEDURE WAIT(VAR s:SIGNAL); (* Чекати поки не пришлють сигнал s *)
PROCEDURE Awaited(VAR s:SIGNAL): BOOLEAN; (* Якщо TRUE –
хоча б один процес чекає на s *)
PROCEDURE Init(VAR s:SIGNAL); (* Обов'язкова ініціалізація *)
END Processes.
Відзначимо наявність процедури обов'язкової ініціалізації семафора Init і неблокуючу процедуру перевірки черги процесів, що очікують на семафор Awaited.
Що стосується сучасних систем програмування на мовах C/C++, то вони, як правило, мають в своєму складі бібліотеки підтримки засобів синхронізації процесів які спираються на можливості, що надаються ОС. Так наприклад, бібліотека MFC фірми Microsoft містить класи CSemaphore і CMutex, що надають механізми семафорів і м'ютексів для багатопотокових застосувань.
Розгляд підтримки взаємних виключень засобами ОС почнемо з систем сімейства UNIX.
Системні виклики для управління потоками в UNIX-подібних ОС стандартизовані в частині стандарту POSIX (P1003.1c). Стандартом не обумовлюється спосіб реалізації викликів, так що вони можуть бути як справжніми викликами сервісів ядра системи, так і викликами бібліотечних функцій, що працюють в просторі користувача.
Деякі виклики стандарту POSIX для роботи з семафорами
Таблиця 3.2. Виклик |
Опис |
pthread_mutex_init |
Створює новий м'ютекс |
pthread_mutex_destroy |
Знищує м'ютекс |
pthread_mutex_lock |
Захоплення м'ютекса (див. wait) |
pthread_mutex_unlock |
Звільнення м'ютекса (див. signal) |
sem_init |
Ініціалізація семафору |
sem_wait |
Зменшує значення лічильника (див. wait) |
sem_post |
Збільшує значення лічильника (див. signal) |
sem_getvalue |
Читає поточне значення лічильника семафору |
