Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОС_лекции.doc
Скачиваний:
2
Добавлен:
15.04.2019
Размер:
370.69 Кб
Скачать

Средства синхронизации

Делятся на:

- средства сигнализации, т е извещения о наступлении какого-либо события (события, сигналы)

- средства разделения доступа последовательно используемым ресурсом ПИР (мютексы, семафоры, критические секции)

ПИР – такой ресурс, работать с которым в каждый конкретный момент времени может только один поток или процесс. Для работы с Пир применяют специальные средства синхронизации, которые можно сравнить с флажком или семафором, который может быть в одном из 2х состояний свободен или захвачен. Перед тем, как поток начнет работать с ПИР, он обязательно должен проверить, в каком состоянии находится связанный с ПИР флажок. Если свободен, то он должен перейти в занятое состояние и только после этого начать работать с ресурсом. А после завершения работы немедленно перевести флажок в свободное состояние. Если же флажок находится в занятом состоянии, то поток должен перейти в свободное состояние.

Однако даже выполнение этих требований иногда может привести к взаимной блокировке потока.

Чтобы избежать взаимных блокировок вместе с главным правилом используют одно из 2х дополнительных:

  1. если поток одновременно работает с несколькими последовательно используемыми ресурсами, то он должен захватывать их в строго определенном порядке.

  2. Если поток, работающий с несколькими последовательно используемыми ресурсами обнаружил, что очередной ресурс занят, то он должен немедленно освободить все ранее захваченные ресурсы.

События – объект синхронизации, который может находиться в одном из 2х состояний: Set и Clear.

Для работы с событием есть набор функций:

E=CreateEvent(имя[,н.с.])

e=OpenEvent(имя)

SetEvent(e) – установление в заданный режим

ClearEvent(e)

WaitEvent(e) – переводит вызвавший ее поток в ожидание установки события, указанного в качестве параметра, пока она не переведет в установленное состояние

PulseEvent(e) – перевод события в установленное состояние и тут же сбрасывает состояние

В отличии от события сигнал является адресным средством сигнализации к какому-то определенному процессу. Сигналы в основном используются в Unix. В зависимости от того, кто является источником сигнала: ОС или прикладной процесс, сигналы подразделяются на системные и пользовательские. Значения системных сигналов заранее определены, значения пользовательских – не определены, что означает, что тот или иной пользовательский сигнал договариваются взаимодействующие процессы.

Сигнал может быть обработан процессом только в том случае, если у процесса есть обработчик этого сигнала, т е определена подпрограмма, которую ОС вызывает при посылке сигнала процессу. Для исходных системных сигналов определены стандартные обработчики сигналов по умолчанию, которые присоединяются к исполняемому модулю.

В Unix существуют 2 сигнала, которые ОС может посылать процессам для их завершения: SIGTERM, SIGKILL.

Если системе требуется завершить процесс, она сначала посылает ему сигнал SIGTERM. По умолчанию стандартный обработчик сигнала тут же завершает этот процесс, но пользователь имеет право определить собственный обработчик для сигнала SIGTERM. Для SIGKILL нельзя подменить обработчик. Если в течение некоторого времени после сигнала SIGTERM процесс не завершился, то Unix посылает в догонку SIGKILL, который без всяких условий завершает процесс.

Мютекс (mutex) представляет из себя объект синхронизации, который может находиться в одном из 2х состояний: захваченном и свободном. Мютекс создается с помощью специальной функции: m=CreateMutex(имя), в которой в качестве параметров указывается имя, присваемое мютексу. Функция возвращает описатель мютекса, который затем используется в функциях работы с мютексом.

Потоки других процессов могут получить доступ к мютексу: m=OpenMutex(имя), которая также возвращает описатель мютекса. Для работы с мютексом используется 2 функции:

  1. RequestMutex(m) – захват мютекса: если на момент вызова функции мютекс с описателем m был в свободном состоянии, функция переводит его в захваченное и возвращает управление вызвавшему ее потоку. Если же на момент вызова функции мютекс m был в захваченном состоянии, то функция переводит вызвавший ее поток в состояние ожидания до тех пор, пока мютекс не освободится, после чего переводит его в занятое состояние и возвращает управление.

  2. ReleaseMutex(m) – освобождение мютекса – освобождает мютекс и переводит его в свободное состояние

  3. Close(m) – завершает работу с мютексом. Если Close вызывается в том же процессе, где мютекс был создан, то мютекс уничтожается.

Т о с помощью мютекса очень удобно управлять доступом к ПИРам

Связать ПИР1-m1

...

RequestMutex(m1)

//работа с ПИР

ReleaseMutex(m1)

Семафор так же, как и мютекс представляет из себя объект синхронизации, который может находться в одном из 2х состояний: занятом или свободном. Однако, в отличие о мютекса, с семафором связывается еще счетчик, начальное значение которого задается при создании семафора. Каждый захват семафора уменьшает значение счетчика на 1цу, а каждое его освобождение – увеличивает.

Семафор переводится в захваченное состояние, когда счетчик становится = 0 и в свободное, когда >0. Т о семафор может допустить к одновременной работе с ресурсом столько потоков, сколько указано в начальном значении его счетчика. При значении счетчика = 1, семафор эквивалентен мютексу. Семафор удобен для использования с многоканальными системами массового обслуживания. При этом число каналов задает начальное значение счетчика.

Семафор создается: s=CreateSemaphore(имя, начально значение счетчика m)

Функция возвращает описатель созданного семафора s.

Получить доступ к семафору из другого процесса можно с помощью функции: s=OpenSemaphore(имя)

Для работы:

- RequestSemaphore(s) – вычитает 1цу из текущего значения счетчика. Если после этого счетчик остался положительным, то функция возвращает управления вызвавшему ее потоку. Если же значение счетчика стало равным 0, функция переводит вызвавший ее поток в состояние ожидания, пока семафор не перейдет в свободное состояние.

- ReleaseSemaphore(s) – увеличивает на 1 счетчик

- Close(s) – завершает работу с семафором или уничтожает семафор.

В Windows нет специальных функций захвата семафора и захвата мютекса. Вместо них используются стандартные функции ожидания объектов синхронизации:

- WaitforSingleObject(описатель)

- WaitforMultipleObject(описатель1, описатель2,..)

Эти функции проверяют указанный в качестве параметра объект синхронизации и переводят вызвавший их поток в состояние ожидания установки указанного объекта синхронизации. В случае, если в качестве описателя указан мютекс или семафор, эти функции работают как функции захвата мютекса или семафора.

2я функция выводит поток из состояния ожидания при установке хотя бы одного из перечисленных объектов синхронизации.

Семафоры и мютексы могут использоваться и для синхронизации потоков одного процесса. Однако это будет слишком накладно по времени, поскольку для создания и работы с этими объектами все время приходится вызывать функции ОС. Поэтому для работы внутри одного процесса предназначено более простое средство – критическая секция.

Критическая секция – участок кода программы, ограниченный 2мя специальными функциями:

EnterCriticalSection

//Работа с ПИР

LeaveCriticalSection

Поток, выполнивший функцию EnterCriticalSection, считается вошедшим в критическую секцию, а выполнивший LeaveCriticalSection – вышедшим. В каждый конкретный момент времени только 1 поток процесса может находиться внутри критической секции. Если 2й поток попытается выполнить функцию Enter, он тут же будет переведен в состояние ожидания до тех пор, пока 1й поток не покинет критическую секцию.