[Win32] 1. 개요, HINSTANCE, Event객체
김성엽님의 블로그를 따라하고 있습니다.
API, SDK
- API : OS 와 응용프로그램 사이에 운영체제가 제공한느 함수 집합체
- SDK : Software Development Kit, 소프트웨어 개발 키트
- 응용프로그램을 개발하기 위해서 필요한 프로그램 집합체
데스크톱 응용 프로그래밍
- 응용프로그램을 개발하기 위해서 필요한 프로그램 집합체
Win32 API 응용프로그래밍 을 Windows 데스크톱 응용프로그래밍이라고 한다.
응용프로그램은 어떻게 만들까?
- Windows OS는 C 기반이라서 C언어, API 기반으로 응용프로그램을 개발하는 것이 기본.
- 물론 다른언어로도 개발가능
- '.Net 프레임워크', 'Java 프레임워크' 같은 추가 개발환경을 구성하면 좀더 쉽게 개발함
- 이런 프레임워크는 버전이 중요함. 버전이 다르면 당연히 오류가 남.
초보개발자에서 벗어나기
- 수학을 할줄 아는 사람이 계산기 두드리기 vs 그냥 모르는채 계산기 두드리기 하면 당연히 전자가 이김.
- 그러니까 기초를 튼튼히 하는게 더 좋다(김성엽님 의견)
핸들(Handle)에 대해
운영체제와 리소스
- 운영체제(OS) : 컴퓨터를 유저가 쉽게 제어할 수 있게해주는 소프트웨어
- 리소스 : OS에 의해 관리되는 장치, 해당 장치를 사용하기 위해 필요한 정보들
응용프로그램은 컴퓨터 리소스에 접근을 해서 해당 작업을수행하게 된다.
응용프르로그램이 리소스에 직접 접근하면 위험하다.
- OS가 작동불능이 될수 있기 때문에, OS의 리소스는 포인터로 못 가져온다.
핸들
: OS 에서 리소스를 안전히 관리하기위해 사용하는 주소
- 이것을 API 함수를 이용하여 받거나 요청할 수 있다.
Win32 프로그램에서 핸들 값은 어떻게 저장할까?
HANDLE
자료형으로 저장 : unsigned int(32비트) 자료형 이다.
HCURSOR h_my_cursor = LoadeCursor(NULL, IDC_ARROW); // 커서 핸들 값 저장
HINCON h_my_icon = LoadIcon(NULL, IDI_APPLICATION); // 아이콘의 핸들 값 저장
HINSTANCE
H(Handle) + Instance
Instance Handle 을 저장할 때 사용.
- 윈도우즈 운영체제에서 실행되는 프로그램을 구별하기위한 정수로 된 ID 값
- 동일한 프로그램을 여러개 실행해도 같은 값임.
Process ID 와 다른 값이다.
- Process ID : 메모리에 실행 가능한 상태로 재배열 된 실행코드(Process)를 구별하기 위한 값
- Instance Handle 은 여러번 중복해서 가지게 되는 리소스(아이콘, 커서, 비트맵 등) 공유하기위해 나온 개념.
- Process ID는 그냥 모든 프로세스를 개별적으로 구별하기 위한 값
Incetance Handle 값은 어떻게 얻누?
int WINAPI_WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdlLine, int nCmdShow)
{
...
- WinMain 함수가 시작함수인데, hInstance 값이 전달된다.
hInstance 값을 잘 저장했다가 HINSTANCE형식의 값을 요구하는 API에 사용하면 됨.
HCURSOR LoadCursor(HINSTANCE hInstance, LPCWSTR lpCursorName);
Event 객체
서로 다른 스레드간 정보를 주고받거나 동기화할 때 사용하는 객체.
동기화(Synchorization)
- 연대책임으로 함께 하는걸 동기화라고 함.
- A값을 구한 사람이 다른 작업을 위해 B값을 구하는 자겁이 완료되기를 기다려주는 행위. 아무튼 이런느낌
Event 객체에 대하여
- 여러 스레드를 사용할 때 동기화작업은 필수
- 동기화작업을 쉽게하려할 때 사용하는 것이 Event 객체이다.
- 이벤트 객체는 0,1(True or False) 상태를 기억할 수 있는 커널객체(Kernel Object)이다.
CreateEvent : 이벤트객체를 만드는 함수
Handle h_event_object = CreateEvent(NULL, TRUE, FALSE, NULL);
CreateEvent 함수는 아래와 같은 함수원형을 가지고 있음
HANDLE CreateEvent(LPSECURITY_ATTRIBUTES lpEventAttributes,
BOOL bManualReset, BOOl bInitialState, LPCSTR lpName);
- lpEventAttributes
- SECURITY_ATTRIBUTES 구조체로 선언된 변수의 주소 명시.
- 이 구조체 속에 lpSecrityDescriptor에는 생성될 이벤트 객체 보안기술자(계정정보) 에 대해 명시하도록 되어있음
- 로그인 된 사용자의 로그인 정보에 있는 ACL(Access Control List)를 적용하거나, 이벤트 객체에 생성한 프로세스의 ACL가져와 사용가능
- ACL이 적용되는 객체에는 다른 사람이 해당 객체에 접근하는 것을 제한하거나 허락할 때 ACL을 변경하며 사용함.
- 특별한 보안정책을 사용하지 않거나, 공부목적이면 그냥
NULL
쓰세용
- bManualReset
TRUE
라고 적으면 해당 객체가 조건에맞춰 FALSE 일때 까지 계속 TRUE.FALSE
라고 적으면 해당 객체가 조건에맞춰 TRUE 일때 까지 계속 TRUE.
- bInitialState
- 생성될 이벤트의 초기값을 설정함.
- LPCTSTR IpName
- 이벤트 객체에 사용될 이름을 명시한다.
- 대소문자 구별함.
- 만약 다른 스레드에서 "Tipsware"를 사용하는데 "Tipsware"로 생성하면 그 이벤트 객체들은 서로 공유하게 된다.
Handle h_event_object = CreateEvent(NULL, TRUE, FALSE, L"Tipsware");
- 이렇게 중복되서 생성되면 공유하지만, 먼저 생성된 이벤트의 정보가 우선시됨(새로만든 이벤트의 bManualReset, bInitialState에 적은 매개변수 값 무시)
- 동일한 커널객체 형식에서만 값을 공유하기 때문에 이렇게 됨.
- 함수의 반환 값
- GetLastError()함수 : 이미 같은 lpName을 사용해서 이벤트객체가 공유중이라면
ERROR_ALREADY_EXISTS
가 반환됨 - Create가 실패되면 NULL값이 나온다.
- 성공적인 이벤트생성을 확인하고싶거나, 공유되는 이벤트를 사용하기 싫으면 위의
GetLastError
로 확인해보자.
- GetLastError()함수 : 이미 같은 lpName을 사용해서 이벤트객체가 공유중이라면
이벤트객체 사용이 끝나면 꼭 제거해야함
CloaseHandle(h_event_object);
이벤트 객체 상태 설정하기
- 이벤트객체의 상태값을
TRUE
로 만들고 싶으면SetEvent()
FALSE
로 만들고싶으면ResetEvent()
// 이름없는 이벤트 객체를 생성(수동해제, 초기값 FALSE)
HANDLE h_event_object = CreateEvent(NULL, TRUE, FALSE, NULL);
SetEvent(h_event_object); // 이 이벤트 객체의 상태값을 TRUE 상태로 변경한다.
CloseHandle(h_event_object); // 이벤트 객체의 사용을 중단
이벤트 객체의 상태 체크하기
- 본 이벤트는 다수의 스레드간 작업시점을 동기화하려 사용하는 것임.
WaitForSingleObject()
: 이벤트 객체의 상태값이 변경되는지 체크할 때 사용되는 함수
DWORD state = WaitForSingleObject(h_event_object, 5000); // 5000->5초
- 이벤트가 변경되면 5초까지 안기다리고 바로 함수를 빠져나온다.
- 변경되면 state 값에 WAIT_OBJECT_0 저장
- 변경이 안되면 state 값에 WAIT_TIMEOUT
// 이벤트 객체 생성 (수동해제, 초기값 FALSE)
HANDLE h_event_object = CreateEvent(NULL, TRUE, FALSE, L"Tipsaware");
DWORD state = WaitForSingleObject(h_event_object,5000);
if(WAIT_OBJECT_0 == state){
// 5초 이내 상태가 변경된 경우
} else if(WAIT_TIMEOUT == state){
// 5초 동안 상태가 변경되지 않아서 타임아웃이 발생함
}
CloseHandle(h_event_object); // 이벤트 객체의 사용을 중단.
- 시간 제한 없이 기다리고싶으면 INFINITE 값을 사용하면됨
DWORD state = WaitorSingleObjcet(h_event_object,INFINITE);
Author And Source
이 문제에 관하여([Win32] 1. 개요, HINSTANCE, Event객체), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@psh4204/Win32API-1.-기초1저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)