- •Курсовая работа
- •2012Г. Оглавление
- •Введение
- •1. Теоретические сведения
- •1.1 Основные определения
- •1.2 Синхронизация
- •1.3 Методы синхронизации
- •1.4 Постановка задания
- •1.5 Подход к решению задачи
- •2. Использованные api-функции
- •3. Структура разработанной программы
- •3.1 Модульная схема
- •4. Результаты тестирования программы
- •Заключение
- •Использованная литература
- •Приложение
3. Структура разработанной программы
3.1 Модульная схема
Описание основных модулей (подпрограмм)
T1Rotate – движение первого поезда по окружности;
T2Rotate – движение второго поезда по окружности;
Timer1Timer – проверка занятости семафоров и, при необходимости, изменение их состояния;
Paint – перерисовка всех примитивов на форме;
4. Результаты тестирования программы
Начальное состояние программы
Поезда в движении после запуска
Первый поезд ждёт проезда второго
Второй поезд ждёт проезда первого
Заключение
Синхронизация потоков - это обобщенный термин, относящийся к процессу взаимодействия и взаимосвязи потоков. Синхронизация потоков требует привлечения в качестве посредника самой операционной системы. Потоки не могут взаимодействовать друг с другом без ее участия.
Правильная синхронизация доступа к ресурсам, общедоступным множеству потоков - один из самых важных аспектов многопоточного программирования. Отсутствие или недостаточная синхронизация приведут к непредсказуемым результатам, и в самом худшем случае - аварийном отказе приложения.
В то же самое время, слишком сложная или ненадлежащим образом используемая синхронизация заставляет потоки тратить слишком много времени, блокируя и таким образом значительно сокращая выгоду многопоточности.
Результатом курсовой работы стала программа, которая регулирует движение поездов через перекрёстки при помощи семафоров. Эту задачу можно решить и иным способом, используя мьютексы, так как семафоры предполагают хоть и ограниченные, но не единичные ресурсы, а в данной задаче по каждому перекрёстку (через каждый семафор) может проезжать только один из существующих поездов.
Для разработки приложения использовались функции Win32 API, содержащиеся в модуле Windows.
Использованная литература
Таненбаум Э. Современные операционные системы. 2-е изд. – СПБ.:Питер, 2002. – 1040 с., ил.
Рихтер Дж. Windows для профессионалов: создание эффективных Win32 приложений с учетом специфики 64-разрядной версии Windows/Пер, англ - 4-е изд. - СПб; Питер; М.: Издательско-торговый дом "Русская Редакция", 2001. - 752 с.; ил.
Михелев В.М. Курс лекций по ОС
Михелёв В.М. Задания к лабораторным работам №2, №3
Приложение
unit Kurs_Os;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
OpenGL, Menus, ExtCtrls, StdCtrls, ComCtrls,
XPMan, Spin, Buttons, ImgList, uTrainParams;
const
sColor: array [0..3] of GLfloat = (1, 0.75, 0, 1);
black: array [0..3] of GLfloat = (0, 0, 0, 1);
type
TForm1 = class(TForm)
Timer1: TTimer;
bbExit: TBitBtn;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure FormResize(Sender: TObject);
procedure FormPaint(Sender: TObject);
procedure MakeVan;
procedure Timer1Timer(Sender: TObject);
procedure bbExitClick(Sender: TObject);
procedure FormClick(Sender: TObject);
private
DC : HDC;
hrc: HGLRC;
quadObj : GLUquadricObj;
public
end;
TState =(tMoving, tWaiting);
var
Form1: TForm1;
tm1, tm2 : integer;
T1 : Real = -1;//127.6;
T2 : Real = 180;
vnorm : GLdouble;
pos : Array [0..3] of GLFloat;
hSemaphore1, hSemaphore2 : THandle;
implementation
{$R *.dfm}
//--------------- Движение левого поезда ----------------
procedure T1Rotate (f: boolean);
begin
if not f then begin
T1 := (T1 - 0.1*tSpeed1);
If T1 < -360 then T1 := 0;
end;
end;
//--------------- Движение правого поезда ----------------
procedure T2Rotate (f: boolean);
begin
if not f then begin
T2 := (T2 + 0.1*tSpeed2);
If T2 > 540 then T2 := 180;
end;
end;
//--------------- Прорисовка вагона ---------------
procedure TForm1.MakeVan;
begin
glBegin(GL_QUADS);
glNormal3f(0,-1,0);
glvertex3f(-0.5,-0.2,-1.0);
glvertex3f(-0.5,-0.2,1.0);
glvertex3f(0.5,-0.2,1.0);
glvertex3f(0.5,-0.2,-1.0);
glEnd;
end;
procedure TForm1.Timer1Timer(Sender: TObject);
procedure S1Train1;
begin
hSemaphore1 := CreateSemaphore(nil,1,1,'MySemaphore1');
f1 := false;
f2:= true;
if (T1>-135) then ReleaseSemaphore(hSemaphore1,1,nil);
case WaitForSingleObject(hSemaphore1, 0)of
Wait_Object_0:
begin
f2:=false;
end;
end;
end;
var sa: SECURITY_ATTRIBUTES;
begin
sa.nLength := sizeof(sa);
sa.lpSecurityDescriptor:= nil;
sa.bInheritHandle := TRUE;
tm1 := (tm1 + 1) mod 360;
T1rotate(f1);
T2rotate(f2);
//----- 1й семафор для левого поезда
if (T1<-125)and(T1>-125-tLength1) then
begin
hSemaphore1 := CreateSemaphore(@sa,1,1,'MySemaphore1');
f1 := false;
if abs(305-T2) < 20 then f2:= true
else f2:=false;
end
else
begin
ReleaseSemaphore(hSemaphore1,1,nil);
if abs(305-T2) < 20 then
case WaitForSingleObject(hSemaphore1, 0)of
Wait_Object_0:
begin
f2:=false;
end;
end;
end;
//----- 2й семафор для левого поезда
if (T1<-185)and(T1>-185-tLength1) then
begin
hSemaphore2 := CreateSemaphore(@sa,1,1,'MySemaphore2');
f1 := false;
if abs(305-T2) < 20 then f2:= true
else f2:=false;
end
else
begin
ReleaseSemaphore(hSemaphore2,1,nil);
if abs(305-T2) < 20 then
case WaitForSingleObject(hSemaphore2, 0)of
Wait_Object_0:
begin
f2:=false;
end;
end;
end;
//----- 1й семафор для правого поезда
if (T2>305)and(T2<305+tLength2){and(tlength2<>20)} then
begin
hSemaphore1 := CreateSemaphore(@sa,1,1,'MySemaphore1');
f2 := false;
if abs(-T1-125) < 20 then f1:= true
else f1:=false;
end
else
begin
ReleaseSemaphore(hSemaphore1,1,nil);
if abs(-T1-125) < 20 then
case WaitForSingleObject(hSemaphore1, 0)of
Wait_Object_0:
begin
f1:=false;
end;
end;
end;
//----- 2й семафор для правого поезда
if (T2>375)and(T2<375+tLength2) then
begin
hSemaphore2 := CreateSemaphore(@sa,1,1,'MySemaphore2');
f2 := false;
if abs(-T1-125) < 20 then f1:= true
else f1:=false;
end
else
begin
ReleaseSemaphore(hSemaphore2,1,nil);
if abs(T1-125) < 20 then
case WaitForSingleObject(hSemaphore2, 0)of
Wait_Object_0:
begin
f2:=false;
end;
end;
end;
Paint;
end;
//--------------- Прорисовка формы ---------------
procedure TForm1.FormPaint(Sender: TObject);
var i : integer;
begin
glClear (GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT );
glClearCOlor(0.0,1.0,0.5,0);
glPushMatrix;
glLightfv (GL_LIGHT0, GL_POSITION, @pos);
gluQuadricDrawStyle (quadObj, GLU_FILL);
// Левый поезд
glscalef (0.5,0.5,0.5);
glTranslatef (-3,0,0);
for i := 0 to tVansCount1 -1 do
begin
glpushmatrix;
glcolor3f (1.0,0.0,0.0);
glRotatef (T1,0,1,0);
glRotatef (20*i,0,1,0); //смещение вагонов
glTranslatef (-5,0,0);
MakeVan;
glpopmatrix;
end;
// траектория левого поезда
glPushMatrix;
for i := 1 to 360 do
begin
glColor (1.0, 0.0, 0.0);
glrotate (1, 0, 1, 0);
glBegin (GL_POINTS);
glVertex3f (-5,-0.5,0);
glEnd;
glBegin (GL_POINTS);
glVertex3f (-5.2,-0.5,0);
glEnd;
end;
glPopMatrix;
// траектория правого поезда
gltranslatef (8,0,0);
glPushMatrix;
for i := 1 to 360 do
begin
glColor (0.0, 0.0, 1.0);
glrotate (1, 0, 1, 0);
glBegin (GL_POINTS);
glVertex3f (-5,-0.5,0);
glEnd;
glBegin (GL_POINTS);
glVertex3f (-5.2,-0.5,0);
glEnd;
end;
glPopMatrix;
// правый поезд
for i := 0 to tVansCount2 - 1 do
begin
glpushmatrix;
glcolor3f (0.0,0.0,1.0);
glRotatef (T2,0,1,0);
glRotatef (-20*i,0,1,0);
glTranslatef (-5,0,0);
MakeVan;
glpopmatrix;
end;
glpopmatrix;
SwapBuffers(DC);
end;
//--------------- Формат пиксела ---------------
procedure SetDCPixelFormat (hdc : HDC);
var
pfd : TPixelFormatDescriptor;
nPixelFormat : Integer;
begin
FillChar (pfd, SizeOf (pfd), 0);
pfd.dwFlags := PFD_DRAW_TO_WINDOW or PFD_SUPPORT_OPENGL or PFD_DOUBLEBUFFER;
nPixelFormat := ChoosePixelFormat (hdc, @pfd);
SetPixelFormat (hdc, nPixelFormat, @pfd);
end;
//--------------- Создание формы ---------------
procedure TForm1.FormCreate(Sender: TObject);
begin
DC := GetDC (Handle);
SetDCPixelFormat(DC);
hrc := wglCreateContext(DC);
wglMakeCurrent(DC, hrc);
tm1 := 0;
tm2 := 0;
f1 := true;
f2 := true;
// задаём начальные параметры
tVansCount1 := 4;
tVansCount2 := 5;
tLength1 := 20*tVansCount1;
tLength2 := 20*tVansCount2;
tSpeed1 := 10;
tSpeed2 := 10;
glEnable (GL_POLYGON_SMOOTH);
glEnable (GL_LIGHTING);
glEnable (GL_LIGHT0 );
glEnable (GL_DEPTH_TEST);
glEnable (GL_COLOR_MATERIAL);
quadObj := gluNewQuadric;
glShadeModel (GL_SMOOTH);
vnorm := 120;
pos[0]:= -1;
pos[1]:= 0;
pos[2]:= 0;
pos[3]:= 2;
end;
//--------------- Уничтожение формы ---------------
procedure TForm1.FormDestroy(Sender: TObject);
begin
gluDeleteQuadric (quadObj);
wglMakeCurrent(0, 0);
wglDeleteContext(hrc);
ReleaseDC (Handle, DC);
DeleteDC (DC);
end;
//--------------- Изменение размеров формы ---------------
procedure TForm1.FormResize(Sender: TObject);
begin
glViewport(0, 0, ClientWidth, ClientHeight);
glMatrixMode(GL_PROJECTION);
glLoadIdentity;
gluPerspective(vnorm, ClientWidth / ClientHeight, 1.0, 20.0);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity;
glTranslatef (0.0, 0, -4.0);
glrotatef (90,1,0,0);
InvalidateRect(Handle, nil, False);
end;
//--------------- Выход ---------------
procedure TForm1.bbExitClick(Sender: TObject);
begin
close;
end;
//--------------- Обработка нажатия кнопки мыши ---------------
procedure TForm1.FormClick(Sender: TObject);
begin
Form3.ShowModal;
end;
end.
unit uTrainParams;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Spin, Buttons;
type
TForm3 = class(TForm)
GroupBox2: TGroupBox;
Label3: TLabel;
seSpeed1: TSpinEdit;
GroupBox1: TGroupBox;
Label6: TLabel;
seSpeed2: TSpinEdit;
btnGo: TBitBtn;
btnStop: TBitBtn;
btnInfo: TButton;
bbExit: TBitBtn;
GroupBox3: TGroupBox;
procedure btnGoClick(Sender: TObject);
procedure btnStopClick(Sender: TObject);
procedure bbExitClick(Sender: TObject);
procedure seSpeed1Change(Sender: TObject);
procedure seSpeed2Change(Sender: TObject);
procedure btnInfoClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form3: TForm3;
f1, f2, f3: boolean;
tSpeed1, tSpeed2: real;
tPriority1, tPriority2: integer;
tVansCount1, tVansCount2, tVansCount3: integer;
tLength1, tLength2, tLength3 : integer;
thread1: THandle; tid:Cardinal;
implementation
{$R *.dfm}
// запуск поезда
procedure TForm3.btnGoClick(Sender: TObject);
var i: integer;
begin
tSpeed1 := seSpeed1.Value;
tSpeed2 := seSpeed2.Value;
GroupBox1.Enabled := false;
GroupBox2.Enabled := false;
f1 := false;
f2 := false;
f3 := false;
btnGo.Enabled:=false;
btnStop.Enabled:=true;
end;
// остановка поезда
procedure TForm3.btnStopClick(Sender: TObject);
begin
tSpeed1 := 0;
tSpeed2 := 0;
f1 := true;
f2 := true;
f3 := true;
btnGo.Enabled := true;
btnStop.Enabled := false;
GroupBox1.Enabled := true;
GroupBox2.Enabled := true;
end;
// закрытие панели управления
procedure TForm3.bbExitClick(Sender: TObject);
begin
CloseHandle (Thread1);
close;
end;
// Скорость первого поезда
procedure TForm3.seSpeed1Change(Sender: TObject);
begin
tSpeed1 := seSpeed1.Value;
end;
// Скорость второго поезда
procedure TForm3.seSpeed2Change(Sender: TObject);
begin
tSpeed2 := seSpeed2.Value;
end;
procedure ThreadProc;
begin
Application.MessageBox('Курсовой проект по ОС на тему "Разработка ПО для регулирования движения поездов при помощи семафора Дейкстра". Выполнила Силина Татьяна, группа ПВ-32', 'Информация об авторе', MB_OK);
end;
// Информация об авторе
procedure TForm3.btnInfoClick(Sender: TObject);
begin
thread1:=CreateThread(nil,0,@ThreadProc,nil,CREATE_SUSPENDED,tId);
ResumeThread (Thread1);
end;
// Создание формы
procedure TForm3.FormCreate(Sender: TObject);
begin
btnStop.Enabled := false;
end;
end.