Листинг 7.9. Реализация операций Р и V для однопроцессорной системы

type Semaphore = record

счетчик :integer:

указатель :pointer; продолжение


228________ Глава 7. Организация параллельных взаимодействующих вычислений

Листинг 7.9(продолжение)

end; var S :Semaphore;

procedure P ( var S : Semaphore); begin ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ; Б.счетчик:= Б.счетчик-].: if S.счетчик < 0 then

WAIT(S); { вставить обратившийся процесс в список по S.указатель и передать

на процессор готовый к выполнению процесс } РАЗРЕШИТЬ_ПРЕРЫВАНИЯ end;

procedure V ( var S : Semaphore): begin ЗАПРЕТИТЬ ПРЕРЫВАНИЯ;

З.счетчик::= S.счетчик+1;

if S.счетчик <= 0 then RELEASE (S); { деблокировать первый процесс из списка по S.указатель }

РАЗРЕШИТЬ_ПРЕРЫВАНИЯ end:

procedure InitSem (var S ; Semaphore): begin

5.счетчик:=1;

5.указатель:=nil: end;

Реализация семафоров в мультипроцессорных системах сложнее, чем в однопро­цессорных. Одновременный доступ к семафору S двух процессов, выполняющих­ся на однопроцессорной вычислительной системе, предотвращается запретом пре­рываний. Однако этот механизм не подходит для мультипроцессорных систем, так как он не препятствует двум или более процессам одновременно обращаться к од­ному семафору. В силу того что такой доступ должен реализовываться через кри­тическую секцию, необходимо дополнительное аппаратное взаимное исключение доступа для различных процессоров. Одним из решений является использование уже знакомых нам неделимых команд проверки и установки (TS). Двухкомпонент-ный семафор в этом случае расширяется включением третьего компонента — ло­гического признака взаимоискл (листинг 7.10).

Листинг 7.10.Реализация операций Р и V для мультипроцессорной системы

type Semaphore = record

счетчик : integer;

указатель : pointer;

взаимоискл : boolean: end; var S : Semaphore;

procedure InitSem (var S : Semaphore): begin With S do begin

счетчик:=1; указатель:=nil; взаимоискл:=true: end; end:


Средства синхронизации и связи взаимодействующих процессов_______________ 229

procedure Р ( var S : Semaphore): var разрешено : boolean: begin

ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;

repeat ТS(разрешено, S.взаимоискл) until разрешено:

S.счетчик:=S.счетчик-1:

if S.счетчик < 0 then WAIT(S): { вставить обратившийся процесс в список по S.указатель

и передать на процессор готовый к выполнению процесс }

S.взаимоискл:=true;

РАЗРЕШИТЬ_ПРЕРЫВАНИЯ end:

procedure V ( var S : Semaphore ):

var разрешено : boolean:

begin

ЗАПРЕТИТЬ_ПРЕРЫВАНИЯ;

repeat ТS(разрешено.S.взаимоискл) until разрешено:

5.Счетчик:=5.Счетчик+1;

if S.счетчик <= 0 then RELEASE(S): { деблокировать первый процесс из списка

по S.указатель }

S. взаимоискл:=true:

РАЗРЕШИТЬ__ПРЕРЫВАНИЯ: end:

Обратите внимание, что в данном тексте команда проверки и установки — TS(pa3-решено,S.взаимоискл) — работает не с целочисленными, а с булевыми значениями. Практически это ничего не меняет, ибо текст программы и ее машинная (двоич­ная) реализация — это разные вещи.

Мьютексы

Одним из вариантов реализации семафорных механизмов для организации вза­имного исключения является так называемый мьютекс (mutex). Термин «mutex» произошел от словосочетания «mutual exclusion semaphore», что дословно перево­дится с английского как «семафор взаимного исключения». Мьютексы реализова­ны во многих операционных системах, их основное назначение — организация вза­имного исключения для задач (потоков выполнения) одного или нескольких процессов. Мьютексы — это простейшие двоичные семафоры, которые могут на­ходиться в одном из двух состояний — отмеченном и неотмеченном (открыт и за­крыт соответственно). Когда какая-либо задача, принадлежащая любому процес­су, становится владельцем объекта мьютекс, последний переводится в неотмеченное состояние. Если задача освобождает мьютекс, его состояние становится отмечен­ным.

Организация последовательного (а не параллельного) доступа к ресурсам с ис­пользованием мьютексов становится несложной, поскольку в каждый конкрет­ный момент только одна задача может владеть этим объектом. Для того чтобы мьютекс стал доступен задачам (потокам выполнения), принадлежащим разным процессам, при создании ему необходимо присвоить имя, впоследствии переда­ваемое «по наследству» задачам, которые должны его использовать для взаимо­действия. Для этого вводятся специальные системные вызовы (CreateMutex), в которых указываются начальное значение мьютекса, его имя и, возможно, атри-


230________ Глава 7. Организация параллельных взаимодействующих вычислений

буты защиты. Если начальное значение мьютекса равно true, считается, что зада­ча, создающая этот объект, сразу будет им владеть. Можно указать в качестве начального значение false — в этом случае мьютекс не будет принадлежать ни одной из задач, и только специальным обращением к нему удастся изменить его состояние.

Для работы с мьютексом имеется несколько функций. Помимо уже упомянутой функции создания такого объекта (CreateMutex), есть функции открытия (OpenMu-tex), ожидания событий (WaitForSingleObject и WaitForMultipleObjects) и, наконец, ос­вобождения этого объекта (ReleaseMutex).

Конкретные обращения к этим функциям и перечни передаваемых и получае­мых параметров имеются в документации на соответствующую операционную систему.








Дата добавления: 2016-09-20; просмотров: 431;


Поиск по сайту:

При помощи поиска вы сможете найти нужную вам информацию.

Поделитесь с друзьями:

Если вам перенёс пользу информационный материал, или помог в учебе – поделитесь этим сайтом с друзьями и знакомыми.
helpiks.org - Хелпикс.Орг - 2014-2024 год. Материал сайта представляется для ознакомительного и учебного использования. | Поддержка
Генерация страницы за: 0.004 сек.