Синхронизация с использованием семафоров

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

Семафор может находиться в отмеченном либо неотмеченном состоянии. Приложение делает ожидание семафора с помощью функций WaitForS-ingleObject либо WaitForMultipleObject. С каждым семафором связывается счетчик, изначальное и наибольшее значение которого задается при разработке семафора. Значение этого счетчика миниатюризируется, когда задачка вызывает для семафора функции WaitForSingleObject либо WaitForMultipleObject, и увеличи Синхронизация с использованием семафоров­вается при вызове специально созданной для этого функции Release-Semaphore.

Для сотворения семафора приложение должно вызвать функцию Create-Semaphore:

HANDLE CreateSernaphore(

LPSECURITYATreBUTES IpSemaphoreAttributes, // атрибуты защиты

LONG llnitialCount, // изначальное значение счетчика семафора

LONG lMaximiupCount, // наибольшее значение счетчика

LPCTSTR IpName); // адресок строчки с именованием семафора

В качестве атрибутов защиты вы сможете передать NULL.

Через характеристики Синхронизация с использованием семафоров UnitialCount и lMaximumCount передается соответст­венно изначальное и наибольшее значение счетчика семафора.

Имя семафора указывается аналогично именам рассмотренных ранее объектов.

Если семафор употребляется для синхронизации задач, сделанных в рам­ках 1-го процесса, вы сможете сделать безымянный семафор, указав в каче­стве параметра IpName функции CreateSemaphore значение NULL Синхронизация с использованием семафоров. В том слу­чае, когда необходимо синхронизировать задачки различных процессов, следует опре­делить имя семафора. При всем этом один процесс делает семафор при помощи функции CreateSemaphore, а 2-ой открывает его.

Функция возвращает идентификатор семафора либо NULL в случае ошибки.

Имеющийся семафор можно открыть функцией OpenSemaphore:

HANDLE OpenSemaphore(

DWORD fdwAccess, // требуемый доступ

BOOL Синхронизация с использованием семафоров . flnherit, // флаг наследования

LPCTSTR IpszSemaphoreName); // адресок имени семафора

Предназначение всех характеристик функции аналогично рассмотренному ра­нее для функций OpenEvent, OpenMutex.

Для роста счетчика семафора приложение должно использовать функцию ReleaseSemaphore:

BOOL ReleaseSemaphore(

HANDLE hSemaphore, // идентификатор семафора

LONG cReleaseCount, // значение инкремента

LPLONG IplPreviousCount); // адресок переменной для записи

предшествующего значения счетчика семафора.

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

При успешном окончании функция возвращает значение TRUE.

Варианты заданий

l. Показать возможность управления задачками в мультизадачной ОС WINDOWS, используя пример мультизадачного приложения MiltiSDI, приведенного ниже, и функции управления задачками SetThreadPriority, GetThreadPriority, Sllep, SuspendThread, ResumeThread.

2. Видоизменять приложение Синхронизация с использованием семафоров MultiSDI таким макаром, чтоб в качестве средства синхронизации задач заместо "критичных секций" использова­лись бы средства синхронизации типа "объект-событие".

3. Видоизменять приложение MultiSDI таким макаром, чтоб в качестве средства синхронизации задач заместо "критичных секций" использова­лись бы средства синхронизации типа "объект Mutex".

4. Видоизменять приложение MultiSDI таким макаром, чтоб в Синхронизация с использованием семафоров качестве средства синхронизации задач заместо "критичных секций" использова­лись бы средства синхронизации типа "семафор".

5. Видоизменять приложение MultiSDI таким макаром, чтоб подсчиты-валось общее число воззваний к задачкам, рисующим изображение в глав­ном окне приложения. Для подсчета числа воззваний использовать гло­бальную переменную и "блокирующие функции".

Пример мультизадачного Синхронизация с использованием семафоров приложения

Основная задачка приложения отрисовывают в основном окне приложения во время обработки сообщения WM_PAINT. Не считая того, она делает еще три зада­чи, которые отрисовывают в окне приложения соответственно эллипсы, прямоуголь­ники и текстовую строчку TEXT. Цвет и размеры фигур, также цвет текстовой строчки и цвет фона, на котором отображается эта Синхронизация с использованием семафоров строчка, выбирается случайным образом.

Потому что все задачки отрисовывают в одном окне для обеспечения поочередного доступа к этому ресурсу - окну для рисования- употребляется про­стейшее средство синхронизации - критичная секция.

Главный файл начальных текстов приложения MultiSDI приведен в лис­тинге 1.

Лис­тинг 1.

#include

#include

#include

#include "resource.h Синхронизация с использованием семафоров"

#include "afxres.h"

#include "multisdi.h"

HINSTANCE hInst;

char szAppName[] = "MulniSDI";

char szAppTitle[] = "MultiThead SDI Application";

CRITICAL_SECTION csWindowPaint; // критичная секция для рисования

в окне

BOOL fTerminate = FALSE; // признак окончания всех задач

HANDLE hThreads[3]; // массив идентификаторов запущенных задач

DWORD dwIDThread; // переменная для хранения системного идентификатора задачки

//Функция WinMain

int APIENTRY

WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,

LPSTR Синхронизация с использованием семафоров lpCmdLine, int nCmdShow)

{ WNDCLASSEX wc;

HWND hWnd;

MSG msg;

hInst = hInstance; // сохраняем идентификатор приложения

// Проверяем, не было ли это приложение запущено ранее

hWnd = FindWindow(szAppName, NULL);

if(hWnd)

{ // Если было, выдвигаем окно приложения на фронтальный план

if(IsIconic(hWnd))

ShowWindow(hWnd, SW_RESTORE);

SetForegroundWindow(hWnd);

return FALSE; }

// Регистрируем класс окна

memset(&wc, 0, sizeof Синхронизация с использованием семафоров(wc));

wc.cbSize = sizeof(WNDCLASSEX);

wc.hIconSm = LoadImage(hInst,

MAKEINTRESOURCE(IDI_APPICONSM),

IMAGE_ICON, 16,16,0);

wc.style = 0;

wc.lpfnWndProc = (WNDPROC)WndProc;

wc.cbClsExtra = 0;

wc.cbWndExtra = 0;

wc.hInstance = hInst;

wc.hIcon = LoadImage(hInst,

MAKEINTRESOURCE(IDI_APPICON),

IMAGE_ICON, 32, 32, 0);

wc.hCursor = LoadCursor(NULL, IDC_ARROW);

wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);

wc.lpszMenuName Синхронизация с использованием семафоров = MAKEINTRESOURCE(IDR_APPMENU);

wc.lpszClassName =szAppName;

if(!RegisterClassEx(&wc))

if(!RegisterClass((LPWNDCLASS)&wc.style))

return FALSE;

// Создаем главное окно приложения

hWnd = CreateWindow(s2AppName, s2AppTitle, WS_OVERLAPPEDWINDOW,

CW_USEDEFAULT, 0, CW_USEDEFAULT, 0,

NULL, NULL, hInst, NULL);

if(!hWnd) return(FALSE);

// Отображаем окно и запускаем цикл обработки сообщений ShowWindow(hWnd, nCmdShow);

UpdateWindow(hWnd Синхронизация с использованием семафоров);

while(GetMessage(&msg, NULL, 0, 0))

{ TranslateMessage(&msg);

DispatchMessage(&msg); }

return msg.wParam;

}

// Функция WndProc

LRESULT WINAPI

WndProc(HWND hWnd, UINT msg, WPARAM wParam,

LPARAM lParam)

{ switch(msg)

{

HANDLE_MSG(hWnd, WM _CREATE, WndProc _OnCreate); HANDLE_MSG(hWnd, WM_DESTROY, WndProc_OnDestroy); HANDLE_MSC(hWnd, WM_PAINT, WndProc _OnPaint);

HANDLE_MSG(hWnd, WM Синхронизация с использованием семафоров_COMMAND, WndProc_ OnCommand);

default:

return(DefWindowProc(hWnd, msg, wParam, lParam));

}

}

//Функция WndProc_OnCreate

BOOL WndProc_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreat-

eStruct)

{ // Инициализируем критичную секцию

InitializeCriticalSection(&csWindowPaint);

fTerminate = FALSE; // сбрасывает флаг окончания задач

//Запускаем три задачки, сохраняя их идентификаторы в массиве

hThreads[0] = CreateThread(NULL, 0,

(LPTHREAD_START_ROUTINE)PaintEllipse, (LPVOID)hWnd, 0, (LPDWORD)&dwIDThread);

hThreads[l Синхронизация с использованием семафоров] = CreateThread(NULL, 0,

(LPTHREAD_START_ROUTINE)PaintRect, (LPVOID)hWnd, 0, (LPDWORD)&dwIDThread);

hThreads[2] = CreateThread(NULL, 0,

(LPTHREAD_START_ROUTINE)PaintText, (LPVOID)hWnd, 0, (LPDWORD)&dwIDThread);

return TRUE; }

// Функция WndProcOnDestroy

#pragma warning(disable: 4098)

void WndProc_OnDestroy(HWND hWnd)

{ fTerminate = TRUE; // устанавливает флаг окончания задач

// Дожидаемся окончания всех 3-х задач

WaitForMultipleObjects(3, hThreads, TRUE, INFINITE);

// Перед окончанием работы удаляем Синхронизация с использованием семафоров критичную секцию

DeleteCriticalSection(&csWindowPaint);

// Останавливаем цикл обработки сообщений

PostQuitMessage(O);

return 0L; }

// Функция WndProc_OnPaint

#pragma warning(disable: 4098)

void WndProc_OnPaint(HWND hWnd)

DT_VCENTER);

EndPaint(hWnd, &ps);

// Выходим из критичной секции

LeaveCriticalSection(&csWindowPaint);

return 0;

// Функция WndProc_OnCommand

#pragma warning(disable: 4098)

void WndProc_OnCommand(HWND hWnd, int id,

HWND hwndCtl, UINT codeNotify)

{ switch(id Синхронизация с использованием семафоров)

{ case ID_FILE_EXIT:

{ // Завершаем работу приложения

PostQuitMessage(0);

return 0L;

breaк; }

case ID_HELP_ABOUT:

MB_ICONINFORMATION);

return OL;

break;

default:

break;

}

return FORWARD_WM_COMMAND(hWnd, id, hwndCtl, codeNotify, DefWindowProc); }

// Функция задачки PaintEllipse

void PaintEllipse(void *hwnd)

{ HDC hDC;

RECT rect;

LONG xLeft, xRight, yTop, yBotton;

short Синхронизация с использованием семафоров nRed, nGreen, nBlue;

HBRUSH hBrush, hOldBrush;

// Инициализация генератора случайных чисел

srand((unsigned int)hwnd);

// Задачка будет работать в нескончаемом цикле

while(! fTerminate)

{// Входим в критичную секцию

EnterCriticalSection(&csWindowPaint);

// Отображаем эллипс, который имеет случайный цвет, форму и размещение

hDC = GetDC(hwnd); // получаем контекст отображения

// Получаем случайные цветовые составляющие

nRed = rand()% 255;

nGreen = rand() % 255;

nBlue = rand()% 255;

// Получаем случайные размеры эллипса

GetWindowRect Синхронизация с использованием семафоров(hwnd, &rect);

xLeft = rand() % (rect.left + 1);

xRight = rand() % (rect.right + 1);

уТор = rand() %,(rect.top + 1);

yBotton = rand() % (rect.bottom + 1);

// Создаем кисть на базе случайных цветов

hBrush = CreateSolidBrush(RGB(nRed, nGreen, nBlue));

// Избираем кисть в контексте отображения

hOldBrush = SelectObject(hDC, hBrush);

// Рисуем эллипс

Ellipse(hDC, min(xLeft, xRight), min(yTop, yBotton),

max(xLeft, xRight Синхронизация с использованием семафоров), max(yTop, yBotton));

// Избираем старенькую кисть в контексте отображения

SelectObject(hDC, hOldBrush);

// Удаляем сделанную кисть

DeleteObject(hBrush);

// Освобождаем контекст отображения

ReleaseDC(hwnd, hDC);

// Выходим из критичной секции

LeaveCriticalSection(&csWindowPaint);

// Исполняем задержку на 500 миллисекунд

Sleep(500); }

}

// Функция задачки Paint Rect

void PaintRect(void *hwnd)

{ HDC hDC;

RECT rect;

LONG xLeft, xRight, yTop, yBotton;

short nRed Синхронизация с использованием семафоров, nGreen, nBlue;

HBRUSH hBrush, hOldBrush;

srand((unsigned int)hwnd + 1);

while(!fTerminate)

{ EnterCriticalSection(&csWindowPaint);

hDC = GetDC(hwnd);

nRed = rand() % 255;

nGreen = rand() % 255;

nBlue = rand() % 255;

GetWindowRect(hwnd, &rect);

xLeft =rand() % (rect.left + 1);

xRight = rand() % (rect.right + 1);

yTop = rand() % (rect.top + 1);

yBotton = rand() % (rect.bottom + 1);

hBrush =CreateSolidBrush(RGB(nRed, nGreen, nBlue));

hOldBrush = SelectObject(hDC, hBrush);

Rectangle Синхронизация с использованием семафоров(hDC, min(xLeft, xRight), min(yTop, yBotton),

max(xLeft, xRight), max(yTop, yBotton));

SelectObject(hDC, hOldBrush);

DeleteObject(hBrush);

ReleaseDC(hwnd, hDC);

LeaveCriticalSection(&csWindowPaint);

Sleep(500); }

}

// Функция задачки PaintText

void PaintText(void *hwnd)

{ HDC hDC;

RECT rect;

LONG xLeft, xRight, yTop, yBotton;

short nRed, nGreen, nBlue;

srand((unsigned int)hwnd Синхронизация с использованием семафоров + 2);

while(!fTerminate)

{ EnterCriticalSection(&csWindowPaint);

hDC = GetDC(hwnd); GetWindowRect(hwnd, &rect);

xLeft = rand() % (rect.left + 1);

xRight« rand() % (rect.right + 1);

yTop = rand() % (rect.top +1);

yBotton = rand() % (rect.bottom + 1);

// Устанавливаем случайный цвет текста

nRed = rand() % 255;

nGreen = rand()% 255;

nBlue = rand() % 255;

SetTextColor(hDC, RGB(nRed, nGreen, nBlue));

// Устанавливаем случайный цвет фона

nRed = rand()% 255;

nGreen = rand() % 255;

nBlue = rand Синхронизация с использованием семафоров()% 255;

SetBkColor(hDC, RGB(nRed, nGreen, nBlue));

TextOut(hDC, xRight - xLeft,

yBotton - yTop, "TEXT", 4);

ReIeaseDC(hwnd, hDC);

LeaveCriticalSection(&csWindowPaint);

Sleep(500); }

}

Файл Multisdi.h (листинг 2) содержит макеты функции, определенных в приложении MuitiSD.Это функция головного окна приложения WndProc.Функция обработки сообщений WM_COMMAND, WM_DESTROY,WM_PAINT,WM_CREATE с именами Синхронизация с использованием семафоров WndProc_OnCommand, WndProc_OnDestroy, WndProc_OnPAINT, WndProc_OnCREATE, также функции задач PaintEclipse,PaintRect и PaintText.

Листинг 2.

LRESULT WINAPI.

WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParamV

BOOL WndProc_OnCreate(HWND hWnd, LPCREATESTRUCT lpCreateStruct);

void WndProcJ3nDestroy(HWND hWnd);

void WndProc_OnPaint(HWND hWnd);

void WndProc_OnCommand(HWND hWnd Синхронизация с использованием семафоров, int id,

HWND hwndCtl, UINT codeNotify);

void PaintEllipse(void *hwnd);

void PaintRect(void *hwnd);

void PaintText(void *hwnd);

Файлы resorse.h и multisdi.rc создаются автоматом с использовани­ем редактора ресурсов системы разработки приложений Visual C++.

Литература

1. Фролов А.В., Фролов Г.В. Программирование для WINDOWS NT. Биб­лиотека системного Синхронизация с использованием семафоров программера; Т. 26.- М.: ДИАЛОГ-МИФИ, 1996.

2. Фролов А.В., Фролов Г.В. Программирование для WINDOWS NT. Биб­лиотека системного программера; Т. 27.- М.: ДИАЛОГ-МИФИ, 1996.

3. Кастер Х. Базы WINDOWS NT и NTFS. - M:Microsoft Press, 1996.

4. Дженнингс P. Windows 95 в подлиннике. Спб.: BHV - Санкт-Петер­бург, 1995.


simvolika-sinego-cveta-v-odezhde.html
simvolika-triedinoj-energii.html
simvolika-vrat-statya.html