Семафор — це універсальний механізм для організації взаємодії процесів (в термінології операційних систем сімейства Windows — потоків).
Розв'язує задачі взаємного виключення та синхронізації потоків. Він є одним з найстаріших засобів розподілення доступу процесів, що працюють паралельно, до критичних ресурсів. Семафори використовуються для контролю доступу до спільного ресурсу, або для синхронізації процесів (потоків).
Визначення семафору зроблено нідерландським вченим Едсгером Дейкстрою, деякий час використовувався термін Семафор Дейкстри.
Загальні дані
Семафор — це об'єкт ядра ОС, який можна розглядати як лічильник, що містить ціле число в діапазоні від 0 до заданого при його створенні максимального значення. При досягненні семафором значення 0 він переходить у несигнальний стан, при будь-яких інших значеннях лічильника — його стан сигнальний.
Традиційне позначення семафора: S. Операції, які можна виконати над семафором:
- Ініціалізація — встановлення початкового значення семафору.
- Операція P(S): Вона перевіряє стан семафору. Якщо семафор не рівний нулю, то виконується операція S:=S-1. Інакше, процес блокується, поки S=0.
- Операція V(S): Ця операція збільшує значення семафору на 1. Тобто виконується операція S:=S+1.
Типи семафорів
В залежності від значень, які може приймати семафор він поділяється на:
- Двійковий: здатний приймати значення 0 та 1.
- Трійковий: здатний приймати значення 0, 1 та 2.
- і т. д.
Задачі, що розв'язуються з допомогою семафорів
З допомогою семафорів можна розв'язати задачі синхронізації потоків та використання спільного ресурсу багатьма потоками.
Задача синхронізації
- Постановка задачі: є два потоки, що виконуються паралельно. Перший потік (назвемо його А), виконується і в певному місці коду (критична ділянка коду) має відправити повідомлення другому потоку (нехай буде В). Потік В, виконується і дійшовши до певної частини коду(критична ділянка коду), блокується, поки не отримає повідомлення від потоку А. Невідомо, який з потоків першим дійде до критичної частини коду. Потрібно їх синхронізувати.
Розв"язок задачі: Для розв'язання цієї задачі достатньо використати двійковий семафор(S=0,1). На початку обов'язково семафор S встановити в нуль: S:=0 !!!
: Оскільки потоки виконуються паралельно, тобто водночас, то заздалегідь не відомо, який з потоків дійде до критичної ділянки коду першим. Існує два випадки:
- Нехай першим дійшов потік А. Операція V(S) збільшить семафор на 1 і потік А продовжить виконуватися. Тоді, коли до критичної ділянки дійде потік В, він продовжить своє виконання. При цьому операція P(S) зменшить семафор на 1.
- Нехай першим дійде потік В. Перевіривши семафор, він блокується, поки не буде повідомлення(сигналу) від потоку А. Тобто, поки семафор дорівнює нулю. Коли потік А відправить сигнал, тобто, збільшить семафор на 1, тоді продовжить виконуватися потік В, зменшивши при цьому семафор на 1.
- Прикладом такої синхронізації може бути процес: Нехай потоку В для виконання потрібен ресурс, який формує потік А. Тому потоку В доводиться чекати, поки потік А не сформує цей ресурс.
Про завдання синхронізації потоків див. також конкуренція потоків;
Семафори у Windows
Лічильник зменшується при кожному успішному завершенні функції очікування, яка використовує семафор і збільшується викликом функції Windows API ReleaseSemaphore. Тому семафор можна використовувати для обмеження доступу до ресурсу, який підтримує заздалегідь задану кількість під'єднань. На відміну від м'ютекса, стосовно семафора відсутнє поняття володіння.
Для створення семафора служить функція Windows API CreateSemaphore. Її опис мовою :
HANDLE WINAPI CreateSemaphore( __in_opt LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, __in LONG lInitialCount, __in LONG lMaximumCount, __in_opt LPCTSTR lpName );
Опис мовою Delphi виглядає так:
function CreateSemaphore( lpSemaphoreAttributes: PSecurityAttributes; // Атрибути доступу lInitialCount, // Початкове значення лічильника lMaximumCount: Longint; // Максимальне значення лічильника lpName: PChar // Ім'я об'єкта ): THandle;
Функція повертає дескриптор створеного семафора, або 0, якщо створити його не вдалося. Параметр lMaximumCount задає максимальне значення лічильника семафора, lInitialCount задає початкове значення лічильника й повинен бути в діапазоні від 0 до lMaximumCount. lpName містить ім'я семафора. Якщо в системі вже є семафор з таким ім'ям, то новий не створюється, а повертається дескриптор існуючого. При використанні семафора в середині одного процесу можна його створити без імені, передавши як lpName значення nil. Ім'я семафора не повинне збігатися з іменем уже існуючого об'єкта типу Event, Mutex, Waitable Timer, Job, або File Mapping.
Дескриптор раніше створеного семафора може бути отриманий функцією OpenSemaphore. Опис на :
HANDLE WINAPI OpenSemaphore( __in DWORD dwDesiredAccess, __in BOOL bInheritHandle, __in LPCTSTR lpName );
Опис функції мовою Delphi:
function OpenSemaphore( dwDesiredAccess: DWORD; // Задає права доступу до об'єкта bInheritHandle: BOOL; // Задає, чи може семафор успадковуватися lpName: PChar // Ім'я об'єкта ): THandle;
Для збільшення лічильника семафора використовується функція ReleaseSemaphore. Її опис на :
BOOL WINAPI ReleaseSemaphore( __in HANDLE hSemaphore, __in LONG lReleaseCount, __out_opt LPLONG lpPreviousCount );
Опис мовою Delphi:
function ReleaseSemaphore( hSemaphore: THandle; // Дескриптор семафора lReleaseCount: Longint; // Величина приросту семафора lpPreviousCount: Pointer // Адреса змінної, яка прийме // попереднє значення ): BOOL;
Якщо значення лічильника після виконання функції перевищить заданий для нього максимум, то функція ReleaseSemaphore поверне false і значення семафора не зміниться. Параметром lpPreviousCount можна передати nil, якщо це значення програмі не потрібно. На відміну від м'ютекса, семафор не можна захопити у володіння, оскільки відсутнє саме поняття прав власності над ним. Крім цього, семафор може бути звільнений будь-яким потоком.
Приклад використання семафора
Як приклад використання семафора розглянемо код, який дозволяє обмежити кількість екземплярів програми, які працюють одночасно (текст програми мовою Delphi:).
var hSem : Thandle; Cnt : integer = 0; InstLim: integer = 3; ................................................. const SemName = 'ISemaph'; ................................................. initialization hSem := CreateSemaphore(nil, InstLim, InstLim, SemName); // Якщо семафор не створено або він зайнятий if (hSem = 0) or (WaitForSingleObject(hSem, 100) <> WAIT_OBJECT_0) then begin ShowMessage('Допустима кількість програм вже працює!'); Halt; end else Inc(Cnt); finalization if hSem <> 0 then begin ReleaseSemaphore(hSem, Cnt, nil); CloseHandle(hSem); end; end.
З цією метою в секції ініціалізації модуля головного вікна за допомогою функції CreateSemaphore робиться спроба створення семафора з назвою SemName (у змінній InstLim вказано максимально допустиму кількість запущених програм — 3). Якщо ця спроба невдала чи семафор не знаходиться у сигнальному стані (тобто допустима кількість програм вже запущена), виводиться повідомлення про неможливість запуску програми і викликається процедура Halt для завершення роботи (проте секція фіналізації виконається в будь-якому випадку). Якщо ж програму можна запускати, лічильник Cnt збільшується з 0 до 1.
Для звільнення використаних ресурсів при завершенні програми значення семафора збільшується на значення Cnt викликом функції ReleaseSemaphore. Якщо програму не буде запущено, Cnt=0 і виклик ReleaseSemaphore не збільшить значення семафора. У випадку, коли програма була запущена і завершує роботу, лічильник семафору зростає на 1, і якщо він був несигнальним, переводиться у сигнальний стан, дозволяючи таким чином запуск нового екземпляра програми. Після цього викликом CloseHandle звільняється дескриптор семафора.
Джерела
- Коноваленко І. В., Федорів П. С. Системне програмування у Windows з прикладами на Delphi, Т:ТНТУ.- 2012.
- MSDN: CreateSemaphore function
- MSDN: OpenSemaphore function
- MSDN: ReleaseSemaphore function
Див. також
- Багатонитевість
- Потік
- Синхронізація процесів
- Критична секція
- М'ютекс
- Ф'ютекс, швидкий користувацький м'ютекс
- Подія (Windows)
Ця стаття потребує додаткових для поліпшення її . (січень 2016) |
Це незавершена стаття про програмування. Ви можете проєкту, виправивши або дописавши її. |
Це незавершена стаття про операційні системи. Ви можете проєкту, виправивши або дописавши її. |
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
U Vikipediyi ye statti pro inshi znachennya cogo termina Semafor znachennya Semafor ce universalnij mehanizm dlya organizaciyi vzayemodiyi procesiv v terminologiyi operacijnih sistem simejstva Windows potokiv Rozv yazuye zadachi vzayemnogo viklyuchennya ta sinhronizaciyi potokiv Vin ye odnim z najstarishih zasobiv rozpodilennya dostupu procesiv sho pracyuyut paralelno do kritichnih resursiv Semafori vikoristovuyutsya dlya kontrolyu dostupu do spilnogo resursu abo dlya sinhronizaciyi procesiv potokiv Viznachennya semaforu zrobleno niderlandskim vchenim Edsgerom Dejkstroyu deyakij chas vikoristovuvavsya termin Semafor Dejkstri Zagalni daniSemafor ce ob yekt yadra OS yakij mozhna rozglyadati yak lichilnik sho mistit cile chislo v diapazoni vid 0 do zadanogo pri jogo stvorenni maksimalnogo znachennya Pri dosyagnenni semaforom znachennya 0 vin perehodit u nesignalnij stan pri bud yakih inshih znachennyah lichilnika jogo stan signalnij Tradicijne poznachennya semafora S Operaciyi yaki mozhna vikonati nad semaforom Inicializaciya vstanovlennya pochatkovogo znachennya semaforu Operaciya P S Vona pereviryaye stan semaforu Yaksho semafor ne rivnij nulyu to vikonuyetsya operaciya S S 1 Inakshe proces blokuyetsya poki S 0 Operaciya V S Cya operaciya zbilshuye znachennya semaforu na 1 Tobto vikonuyetsya operaciya S S 1 Tipi semaforiv V zalezhnosti vid znachen yaki mozhe prijmati semafor vin podilyayetsya na Dvijkovij zdatnij prijmati znachennya 0 ta 1 Trijkovij zdatnij prijmati znachennya 0 1 ta 2 i t d Zadachi sho rozv yazuyutsya z dopomogoyu semaforivZ dopomogoyu semaforiv mozhna rozv yazati zadachi sinhronizaciyi potokiv ta vikoristannya spilnogo resursu bagatma potokami Zadacha sinhronizaciyi Postanovka zadachi ye dva potoki sho vikonuyutsya paralelno Pershij potik nazvemo jogo A vikonuyetsya i v pevnomu misci kodu kritichna dilyanka kodu maye vidpraviti povidomlennya drugomu potoku nehaj bude V Potik V vikonuyetsya i dijshovshi do pevnoyi chastini kodu kritichna dilyanka kodu blokuyetsya poki ne otrimaye povidomlennya vid potoku A Nevidomo yakij z potokiv pershim dijde do kritichnoyi chastini kodu Potribno yih sinhronizuvati Rozv yazok zadachi Dlya rozv yazannya ciyeyi zadachi dostatno vikoristati dvijkovij semafor S 0 1 Na pochatku obov yazkovo semafor S vstanoviti v nul S 0 Oskilki potoki vikonuyutsya paralelno tobto vodnochas to zazdalegid ne vidomo yakij z potokiv dijde do kritichnoyi dilyanki kodu pershim Isnuye dva vipadki Nehaj pershim dijshov potik A Operaciya V S zbilshit semafor na 1 i potik A prodovzhit vikonuvatisya Todi koli do kritichnoyi dilyanki dijde potik V vin prodovzhit svoye vikonannya Pri comu operaciya P S zmenshit semafor na 1 Nehaj pershim dijde potik V Perevirivshi semafor vin blokuyetsya poki ne bude povidomlennya signalu vid potoku A Tobto poki semafor dorivnyuye nulyu Koli potik A vidpravit signal tobto zbilshit semafor na 1 todi prodovzhit vikonuvatisya potik V zmenshivshi pri comu semafor na 1 Prikladom takoyi sinhronizaciyi mozhe buti proces Nehaj potoku V dlya vikonannya potriben resurs yakij formuye potik A Tomu potoku V dovoditsya chekati poki potik A ne sformuye cej resurs Pro zavdannya sinhronizaciyi potokiv div takozh konkurenciya potokiv Semafori u WindowsLichilnik zmenshuyetsya pri kozhnomu uspishnomu zavershenni funkciyi ochikuvannya yaka vikoristovuye semafor i zbilshuyetsya viklikom funkciyi Windows API ReleaseSemaphore Tomu semafor mozhna vikoristovuvati dlya obmezhennya dostupu do resursu yakij pidtrimuye zazdalegid zadanu kilkist pid yednan Na vidminu vid m yuteksa stosovno semafora vidsutnye ponyattya volodinnya Dlya stvorennya semafora sluzhit funkciya Windows API CreateSemaphore Yiyi opis movoyu C HANDLE WINAPI CreateSemaphore in opt LPSECURITY ATTRIBUTES lpSemaphoreAttributes in LONG lInitialCount in LONG lMaximumCount in opt LPCTSTR lpName Opis movoyu Delphi viglyadaye tak function CreateSemaphore lpSemaphoreAttributes PSecurityAttributes Atributi dostupu lInitialCount Pochatkove znachennya lichilnika lMaximumCount Longint Maksimalne znachennya lichilnika lpName PChar Im ya ob yekta THandle Funkciya povertaye deskriptor stvorenogo semafora abo 0 yaksho stvoriti jogo ne vdalosya Parametr lMaximumCount zadaye maksimalne znachennya lichilnika semafora lInitialCount zadaye pochatkove znachennya lichilnika j povinen buti v diapazoni vid 0 do lMaximumCount lpName mistit im ya semafora Yaksho v sistemi vzhe ye semafor z takim im yam to novij ne stvoryuyetsya a povertayetsya deskriptor isnuyuchogo Pri vikoristanni semafora v seredini odnogo procesu mozhna jogo stvoriti bez imeni peredavshi yak lpName znachennya nil Im ya semafora ne povinne zbigatisya z imenem uzhe isnuyuchogo ob yekta tipu Event Mutex Waitable Timer Job abo File Mapping Deskriptor ranishe stvorenogo semafora mozhe buti otrimanij funkciyeyu OpenSemaphore Opis na C HANDLE WINAPI OpenSemaphore in DWORD dwDesiredAccess in BOOL bInheritHandle in LPCTSTR lpName Opis funkciyi movoyu Delphi function OpenSemaphore dwDesiredAccess DWORD Zadaye prava dostupu do ob yekta bInheritHandle BOOL Zadaye chi mozhe semafor uspadkovuvatisya lpName PChar Im ya ob yekta THandle Dlya zbilshennya lichilnika semafora vikoristovuyetsya funkciya ReleaseSemaphore Yiyi opis na C BOOL WINAPI ReleaseSemaphore in HANDLE hSemaphore in LONG lReleaseCount out opt LPLONG lpPreviousCount Opis movoyu Delphi function ReleaseSemaphore hSemaphore THandle Deskriptor semafora lReleaseCount Longint Velichina prirostu semafora lpPreviousCount Pointer Adresa zminnoyi yaka prijme poperednye znachennya BOOL Yaksho znachennya lichilnika pislya vikonannya funkciyi perevishit zadanij dlya nogo maksimum to funkciya ReleaseSemaphore poverne false i znachennya semafora ne zminitsya Parametrom lpPreviousCount mozhna peredati nil yaksho ce znachennya programi ne potribno Na vidminu vid m yuteksa semafor ne mozhna zahopiti u volodinnya oskilki vidsutnye same ponyattya prav vlasnosti nad nim Krim cogo semafor mozhe buti zvilnenij bud yakim potokom Priklad vikoristannya semafora Yak priklad vikoristannya semafora rozglyanemo kod yakij dozvolyaye obmezhiti kilkist ekzemplyariv programi yaki pracyuyut odnochasno tekst programi movoyu Delphi var hSem Thandle Cnt integer 0 InstLim integer 3 const SemName ISemaph initialization hSem CreateSemaphore nil InstLim InstLim SemName Yaksho semafor ne stvoreno abo vin zajnyatij if hSem 0 or WaitForSingleObject hSem 100 lt gt WAIT OBJECT 0 then begin ShowMessage Dopustima kilkist program vzhe pracyuye Halt end else Inc Cnt finalization if hSem lt gt 0 then begin ReleaseSemaphore hSem Cnt nil CloseHandle hSem end end Z ciyeyu metoyu v sekciyi inicializaciyi modulya golovnogo vikna za dopomogoyu funkciyi CreateSemaphore robitsya sproba stvorennya semafora z nazvoyu SemName u zminnij InstLim vkazano maksimalno dopustimu kilkist zapushenih program 3 Yaksho cya sproba nevdala chi semafor ne znahoditsya u signalnomu stani tobto dopustima kilkist program vzhe zapushena vivoditsya povidomlennya pro nemozhlivist zapusku programi i viklikayetsya procedura Halt dlya zavershennya roboti prote sekciya finalizaciyi vikonayetsya v bud yakomu vipadku Yaksho zh programu mozhna zapuskati lichilnik Cnt zbilshuyetsya z 0 do 1 Dlya zvilnennya vikoristanih resursiv pri zavershenni programi znachennya semafora zbilshuyetsya na znachennya Cnt viklikom funkciyi ReleaseSemaphore Yaksho programu ne bude zapusheno Cnt 0 i viklik ReleaseSemaphore ne zbilshit znachennya semafora U vipadku koli programa bula zapushena i zavershuye robotu lichilnik semaforu zrostaye na 1 i yaksho vin buv nesignalnim perevoditsya u signalnij stan dozvolyayuchi takim chinom zapusk novogo ekzemplyara programi Pislya cogo viklikom CloseHandle zvilnyayetsya deskriptor semafora DzherelaKonovalenko I V Fedoriv P S Sistemne programuvannya u Windows z prikladami na Delphi T TNTU 2012 MSDN CreateSemaphore function MSDN OpenSemaphore function MSDN ReleaseSemaphore functionDiv takozhBagatonitevist Potik Sinhronizaciya procesiv Kritichna sekciya M yuteks F yuteks shvidkij koristuvackij m yuteks Podiya Windows Cya stattya potrebuye dodatkovih posilan na dzherela dlya polipshennya yiyi perevirnosti Bud laska dopomozhit udoskonaliti cyu stattyu dodavshi posilannya na nadijni avtoritetni dzherela Zvernitsya na storinku obgovorennya za poyasnennyami ta dopomozhit vipraviti nedoliki Material bez dzherel mozhe buti piddano sumnivu ta vilucheno sichen 2016 Ce nezavershena stattya pro programuvannya Vi mozhete dopomogti proyektu vipravivshi abo dopisavshi yiyi Ce nezavershena stattya pro operacijni sistemi Vi mozhete dopomogti proyektu vipravivshi abo dopisavshi yiyi