Автор: Пользователь скрыл имя, 17 Января 2011 в 21:52, лабораторная работа
Семафор – это защищенная переменная, значение которой можно опрашивать и изменять с помощью специальных операций. Двоичные семафоры принимают два значения («0» и «1»), считающие семафоры (семафоры со счетчиками) принимают целые неотрицательные значения.
Лабораторная работа №1
по курсу:
Системы
реального времени
«Механизм
межзадачного взаимодействия
с помощью семафоров»
Выполнила ст. группы З-245
Черныш Е.П.
Проверила
Глод О.Д.
Таганрог 2010
Семафор – это защищенная переменная, значение которой можно опрашивать и изменять с помощью специальных операций. Двоичные семафоры принимают два значения («0» и «1»), считающие семафоры (семафоры со счетчиками) принимают целые неотрицательные значения.
Если на время работы обрабатывающей программы с некоторым ресурсом доступ к нему со стороны других программ нужно запретить, то эта обрабатывающая программа перед обращением к ресурсу устанавливает соответствующий семафор в «0» и тем самым запрещает доступ к нему. По окончанию работы с ресурсом программа возвращает значение семафора в «1», тем самым снимает запрет.
С помощью семафоров можно решать задачи по синхронизации процессов. Допустим, что одному процессу (процесс A) необходимо, чтобы он получил уведомление о наступлении некоторого события для продолжения выполнения программы, и обнаружить, что данное событие произошло, может другой процесс (процесс B). Этот простой процесс синхронизации (блокирования/возобновления) реализуется с помощью семафора.
До происхождения события семафор устанавливается в «0», и, когда процесс A в ходе своего выполнения доходит до той точки, когда дальнейшее его выполнения зависит от ожидаемого события, он блокируется. Со временем процесс B обнаруживает наступление события и переводит семафор в состояние «1», сигнализируя, что событие произошло. Таким образом, первый процесс получает возможность возобновить свое выполнение, т.е. обработку произошедшего события.
Семафоры и операции над ними могут быть реализованы как программно, так и аппаратно, как правило, в ядре ОС, где осуществляется управление сменой состояния процессов.
Над семафорами вводятся операции:
Решение задачи «взаимоисключающий доступ»
с помощью механизма семафоров
Есть два процесса (процесс A и процесс B), которые во время своего выполнения обращаются к разделяемому ресурсу. Требуется исключить одновременные обращения процессов к критическому ресурсу. При этом необходимо, чтобы задержка любого процесса вне его критической секции не влияла на работу другого процесса. Решение должно быть симметричным для обоих процессов (оба процесса равноправны). Оба процесса являются циклическими и имеют 2 этапа работы:
Описание программы «взаимоисключающий доступ»
Программа реализует взаимоисключающий доступ к критическому объекту. В нашем случае под критическим объектом подразумевается некоторая переменная, которая может принимать целые положительные значения. В программе используется синхронизация двух параллельных потоков с помощью системной переменной типа Семафор. При запуске программы создаётся семафор:
Semaphore := CreateSemaphore(nil, 1,1,'NameSemaphore');
со следующими параметрами: начальное значение счётчика = 1, максимальное значение счётчика = 1.
При нажатии на кнопку «Создать потоки» создаются два потока, которые, получив соответствующие параметры, запускаются и работают, пока не выполнят функцию Execute (основная функция потока).
Процедура Execute для каждого потока содержит следующие этапы:
Все этапы сопровождаются вызовами процедур отображения хода работы в главном окне программы .
Фрагмент модуля программы, содержащий процедуру Execute, имеет вид:
procedure Thread1.Execute;
var
i,j,jj,kk: integer;
x1,x2:systemtime;
begin
i:=1;
randomize;
repeat
jj:=round(random(
sleep(jj);
getsystemtime(x1);
WaitForSingleObject(Semaphore , infinite); - 2-й этап
getsystemtime(x2);
UpdateGraphic(1,round(jj/k),
kk:=(x2.wMinute-x1.wMinute)*
if kk>0 then UpdateGraphic(1,round(kk/k),
if pos[3].X<pos[1].X then UpdateGraphic(3,(pos[1].X-pos[
j:=round(random(FWorkSemafor))
sleep(j); - 3-й этап
x:=round(random(100))+1;
inc(i);
WriteText:='---1---'+IntToStr(
UpdateGraphic(1,round(j/k),40,
UpdateGraphic(3,round(j/k),20,
ReleaseSemaphore(Semaphore, 1, nil); -4-й этап
Synchronize(UpdateListBox);
until i>10;
end;
В программе, отображающей процедуру Execute, используются переменные целого типа i, j, jj, kk, а также переменные системного времени (systemtime) x1 и x2. Переменная i=10 задает для каждого процесса по 10 обращений к критической секции.
Работа процесса вне критической секции имитируется обращением к генератору равномерно распределенных случайных чисел FSleepDuration. Число, выработанное этим генератором, присваивается переменной jj, которая и определяет длительность работы процесса перед обращением к критической секции (sleep(jj)). В окне "Числовые параметры" значение переменной jj отображает переменная Tраб.
Момент обращения к семафору фиксируется в переменной x1 вызовом функции системного времени: getsystemtime(x1).
Для
занятия критического ресурса производится
обращение к функции WaitForSin
Момент срабатывания семафора, обеспечивающего доступ процесса к критической секции, фиксируется в переменной x2 вызовом функции системного времени: getsystemtime(x2). Разность моментов времени x1 и x2 определяет интервал времени ожидания освобождения критической секции. Эта разность присваивается переменной kk и отображается в окне "Числовые параметры" с помощью переменной Tож.
Работа
процесса с критической секцией
имитируется обращением к генератору
равномерно распределенных случайных
чисел FWorkSemafor. Число, выработанное
этим генератором, присваивается переменной
j, которая и определяет длительность работы
процесса с критической секцией. В окне
"Числовые параметры" значение
переменной j отображает переменная Tраб.кр.
Новое значение переменной x, записываемое
процессом в критическую секцию, вырабатывается
обращением к генератору равномерно распределенных
случайных чисел в диапазоне от 1 до 100.
Ход
работы
Каждый
из двух взаимодействующих с
1-ый процесс | 2-ой процесс | ||||
Траб | Траб.кр. | Х | Траб | Траб.кр. | Х |
700 | 200 | 56 | 800 | 300 | 55 |
200 | 100 | 7 | 100 | 50 | 66 |
300 | 150 | 6 | 250 | 125 | 77 |
Открываем файл WriterThread.pas, содержащий исходный модуль, задающий работу процессов, и вносим изменения в процедуры Thread1.Execute и Thread2.Execute.
В исходном коде программы в процедурах
Thread1.Execute и Thread2.Execute значения переменных
Траб(jj),
Траб.кр.(j),
X задавались генератором случайных чисел
(random):
jj:=round(random(
j:=round(random(
x:=round(random(100))+1;
тело процедуры было заключено в цикл (repeat..until i>10), в результате наш процесс обращался к критическому объекту 10 раз при случайно заданных параметрах.
Так как нам по условию требовалось, чтобы
наши процессы обращались к критическому
объекту всего 3 раза (а не 10) и использовали
конкретные данные, мы внесли следующие
изменении в исходный код программы (модуль
WriterThread.pas ):
например, для 1-го процесса:
mas[1,1]:=700;mas[1,2]:=
mas[2,1]:=200;mas[2,2]:=100;
mas[3,1]:=300;mas[3,2]:=150;
jj:=mas[i,1];
j:= mas[i,2];
x:= mas[i,3].
Так
как i – это счетчик цикла, и его значения
после каждого прохода цикла инкриминируются
(увеличиваются) на 1, это значит, что после
каждого прохода цикла программа будет
брать из нашего массива (матрицы) те значения,
которые были заданы моим вариантом.
Пример работы программы
Потоки
Временная
диаграмма
Информация о работе Механизм межзадачного взаимодействия с помощью семафоров