WINDOWS

윈도우 핸들 (Windows Handle Object)

게임 개발 2024. 5. 24. 00:08

 

핸들이란 무엇일까?

 

우리가 흔히 핸들이라고 하면 자동차의 핸들을 떠올리기 마련이다.

자동차 바퀴의 방향을 제어하기 위해 이 핸들을 사용하게 된다.

 

갖다 붙이기 나름이지만,

윈도우의 핸들이 바로 이 자동차의 핸들과 유사하다.

 

좌회전을 한다고 가정하면

운전자는 바퀴를 움직이다가 직접 손으로 바퀴를 돌리지 않고

핸들이라는 조향 장치를 이용해 간접적으로 바퀴의 방향을 제어하게 된다.

 

마찬가지로 윈도우의 핸들도

커널 오브젝트(혹은 GDI, 사용자 오브젝트)를 사용하기 위해

필요한 하나의 장치라고 보면 된다.

 

프로세스가 초기화되면 운영체제는

프로세스가 커널 오브젝트를 사용할 수 있게 하려고

핸들 테이블을 할당하게 된다.

(GDI, User 오브젝트는 핸들 테이블을 할당하지 않는다.

고유 핸들 값만 받아서 바로 사용한다.)

 

핸들 테이블은

  • 커널 오브젝트의 메모리 블록을 가리키는 포인터
  • 액세스 마스크 (Access Mask) = 접근 권한
  • 플래그(Flag)

로 구성된 구조체 배열이다.

 

핸들을 사용하는 이유

 

이처럼 프로세스가 직접 커널 오브젝트를 사용하지 않고

OS로부터 핸들을 할당받는데에는 다 이유가 있다.

  1. 관리적 측면
  2. 잘못된 변경으로부터 안전성을 확보하기 위해서
    (프로세스가 직접 커널 오브젝트에 접근해 사용하게 된다면
    어떤 프로세스가 커널 오브젝트를 사용하는지,
    프로세스가 접근해서는 안될 커널 오브젝트에 접근하는지 등을
    OS가 파악하기 위해서이다. =이것도 결국 관리적 측면이다)

CreateFile은 파일

Create, Open, Write 등의 동작을 할 때 호출되는 함수로 리턴형이 HANDLE이다.

이 HANDLE은 OS가 할당한 일련번호를 갖게 된다.

요 리턴받은 일련번호(HANDLE)를 호출하면

최초 명시한 파일에 대한 동작(Open, Create, Write 등)을 할 수 있게 되는 것이다.

(나머지 인자들의 접근 권한, 다른 프로세스와 핸들 공유 여부는 생략하겠다.)

 

이렇게 리턴된 HANDLE 값을 사용하게 되면

실제 사용하고자 하는 커널 오브젝트의 주소를 얻어내 사용하게 된다.

 

핸들이 반환형일 때

 

이러한 핸들을 잘 사용해야 에러 핸들링이 되는 것이다.

윈도우 함수를 호출하면 호출된 함수는 먼저 인자의 유효성을 확인하고

함수의 기능을 수행하려 한다.

만일 전달된 인자가 유효하지 않다거나,

다른 이유로 인해 해당 기능을 수행할 수 없으면 함수는 실패를 반환한다.

 

자료형이 HANDLE인 것들은 Window에서 함수가 실패하면

반환 값은 대개 NULL 반환한다.

몇몇 함수들은 -1로 정의된

INVALID_HANDLE_VALUE를 반환하는 경우가 있기 때문에 주의가 필요하다.

플랫폼 SDK 문서에는 함수 호출이 실패했을 때 NULL을 반환하는지

혹은 INVALID_HANDLE_VALUE를 반환하는지에 대해 명확하기 기술되어 있다.

 

핸들 삭제

 

프로세스에서 핸들을 할당받아 커널 오브젝트르 사용하고나면

반드시 핸들을 반납해야한다.

매 사용시가 아니라 프로세스가 종료되는 등 프로세스 생명주기 내 더 이상

해당 기능을 사용할 필요가 없을 시점에 반납한다.

 

핸들을 반납하기 위해서는 CloseHandle(HANDLE hObject)함수를 호출하면 된다.

내부적으로 CloseHandle 함수가 호출되면

유효한 핸들인지 확인 한다.( 유효하지 않으면 INVALID_HANDLE_VALUE를 반환)

커널 오브젝트의 사용 카운트를 감소시킨뒤

프로세스 핸들 테이블에서 해당 항목을 삭제하는 동작을 진행한다.

 

그리고 삭제 후에는 CloseHandle로 반납된

HANDLE객체도 NULL로 초기화 해주는 게 좋다.

혹시라도 중복된 HANDLE값을 다른 프로세스가 할당받는다면

의도한 동작이 일어나지 않을 수 있다.

해제된 커널 오브젝트 주소를 가리키게 될 수도 있다.

 

만약에 CloseHandle을 하지 않는다면?

- Memory Leak(Handle Leak)이 발생할 가능성이 크다.

일반적으로 프로세스가 종료되면

사용했던 모든 핸들을 정리하는 동작을 하기 때문에 괜찮지만,

윈도우가 종료될 때까지 종료되지 않는 프로그램들이 Handle Leak을 유발한다면

지속적으로 메모리를 잡아먹는 현상이 발생한다.

따라서, 꼭 Handle을 사용한 이후에는 CloseHandle을 호출해 HANDLE 객체를 해제해준다.

'WINDOWS' 카테고리의 다른 글

영역 범위 함수  (0) 2023.02.14
WIN API (1)  (0) 2023.02.13