최근에 프로그래밍책을 통하여 순서동기화에 대해 공부하였습니다.
순서동기화는 멀티쓰레드환경에서 실행이 순서대로 실행되도록 합니다.
예를들어 투표장소에 들어갈 수 있는 인원이 1인데 투표자가 들어가 투표하는 동안 다른 기다리는 인원은 앞선사람이 투표를 끝낸이후 투표장소가 비워졌을 때 투표를 할 수 있습니다.이것을 이용하여 투표프로그램을 만들었습니다.
프로그램에 대해 간단히 설명하자면 투표공간 2군대를 만들고 10명의 사람이 투표를 하는 프로그램입니다.
핵심은!!! 투표공간 한군데에 1명만 들어가야한다는 것!에 중점을 두고 진행하였습니다.
#include<stdio.h>
#include<tchar.h>
#include<Windows.h>
#include<process.h>
#include<conio.h>
#include<locale.h>
//투표자수 10명
#define voter_num 10
//투표장소 숫자
#define vote_area 2
//투표함수
unsigned int WINAPI voter(LPVOID lpParam);
//투표장소 선언
HANDLE hvote[vote_area] = { "", };
int _tmain(int argc, TCHAR *argv[])
{
HANDLE hThread[voter_num];
//한글을 사용하기위함
setlocale(LC_ALL, "");
//투표장소 할당
for (int i = 0; i < vote_area; i++)
{
hvote[i] = CreateEvent(
NULL, // 상속 불가
TRUE, // auto-reset off
FALSE,// non-signaled
NULL //이름없는 event
);
if (hvote[i] == NULL)
{
_tprintf(_T("Create Event %d fail : %d"), i, GetLastError());
return -1;
}
}
//투표자 생성
for (int i = 0; i < voter_num; i++)
{
hThread[i] = (HANDLE)_beginthreadex(NULL, 0,
voter, (LPVOID)i,
0, NULL);
if (hThread[i] == NULL)
{
_tprintf(_T("_beginthreadex %d fail : %d"), i, GetLastError());
return -1;
}
}
//투표시작
for (int i = 0; i < vote_area; i++)
{
SetEvent(hvote[i]);
}
_fputts(_T("투표가 시작되었습니다.\n"), stdout);
//모든사람이 투표가 끝날때까지 대기
WaitForMultipleObjects(voter_num,
hThread,
TRUE, //모든 Thread가 종료될때 리턴
INFINITE// signaled상태까지 무한정 대기
);
_fputts(_T("투표가 종료되었습니다.\n"), stdout);
for (int i=0; i < voter_num; i++)
{
CloseHandle(hThread[i]);
CloseHandle(hvote[i]);
}
return 0;
}
///투표하기 함수
unsigned int WINAPI voter(LPVOID lpParam)
{
WaitForMultipleObjects(
vote_area,
hvote,
FALSE, // 투표장소중 한 곳이라도 빈 경우 리턴
INFINITE // signaled상태까지 무한정 대기
);
_tprintf(_T("투표자번호 %d가 투표를 완료하였습니다\n"), (int)lpParam +1);
return 0;
}
위 코드에서 빨간색은 주목해야 할 부분이다. 사용된 API를 간단히 살펴보자.
HANDLE WINAPI CreateEvent( |
- lpEventAttributes : 보안속성구조체이다. 하위프로세스에게 핸들값을 상속가능여부를 결정.
- bManualReset : 자동 RESET을 ON/OFF시킨다. 이를 설정함으로 WaitForSingObjects나 WaitForMultipleObjects가 리턴될 경우 Event가 자동으로
non-signaled가 될지를 결정(True : OFF , FALSE : ON)
- bInitialState : 초기값상태를 signaled/non-signaled상태 결정 (TRUE : signaled , FALSE : non-signaled)
- lpName : Event이름(NULL의 경우 이름 없는 Event)
* RETURN : 반환값
-이벤트의 핸들값을 반환한다.
DWORD WINAPI WaitForMultipleObjects( |
- nCount : 관찰할 커널오브젝트 숫자
- lpHandles : 커널오브젝트 핸들배열정보포함
- bWaitAll : 모든 커널 오브젝트가 signaled상태가 되기까지 대기( TRUE : 모든 커널오브젝트 ,FALSE : 관찰오브젝트중 하나)
- dwMilliseconds : 대기할 시간을 결정
* RETURN : 반환값
- WaitForMultipleObjects가 리턴된 이유를 설명
위코드에는 없지만 WaitForSingleObject를 잠깐 설명한다.
DWORD WINAPI WaitForSingleObject( |
-hHandle : 관찰할 커널 오브젝트 핸들
-dwMilliseconds : 대기할 시간 결정
* RETURN : 반환값
- WaitForMultipleObjects가 리턴된 이유를 설명
한가지 커널오브젝트만을 관찰하기때문에 심플하다.
※실행결과
|
'Programming > System Programming' 카테고리의 다른 글
[WIN32 / C]모든 프로세스 모듈 스캔 코드 (0) | 2017.05.04 |
---|---|
[WIN32 / C] 권한상승 코드 (0) | 2017.05.03 |
[WIN32 / C]프로세스 하위 Thread Entry Point (EP) 코드 출력 (0) | 2017.05.02 |
[WIN32/C] Driver Loader (0) | 2017.03.27 |
[WIN32 / C] pipe를 통한 command prompt연결(console) - Remote Shell (0) | 2016.11.16 |
댓글