핸들(Handle)이란 무엇인가?


우리가 흔히 핸들이라고 생각하면 자동차의 핸들(Steering Wheel)을 떠올리기 마련인데요,

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


윈도우의 핸들이 바로 이 자동차의 핸들과 개념이 유사합니다. (갖다 붙이기 나름이죠?)


좌회전을 한다고 가정해봅시다.

그러면 운전자는 바퀴를 움직이기 위해 직접 손으로 바퀴를 움켜잡고 돌리지 않고 핸들이라는 조향 장치를 이용해 간접적으로 바퀴의 방향을 제어하게 됩니다.


마찬가지로 윈도우의 핸들도 커널 오브젝트(혹은 GDI, 사용자 오브젝트)를 사용하기 위해 필요한 하나의 장치라고 보시면 됩니다.


프로세스가 초기화되면 운영체제는 프로세스가 커널 오브젝트를 사용할 수 있게 하려고 핸들 테이블을 할당하게 됩니다.

(GDI, User 오브젝트는 핸들 테이블을 할당하지 않습니다, 고유의 핸들 값만 받아서 바로 사용)

핸들 테이블은 

- 커널 오브젝트의 메모리 블록을 가리키는 포인터

- 액세스 마스크(Access Mask) : 접근 권한

- 플래그(Flag)

로 구성된 데이터 구조체 배열입니다.


이처럼 프로세스가 직접 커널 오브젝트를 사용하지 않고 OS로부터 핸들을 할당받는데에는 다 이유가 있습니다.

- 관리적 측면

- 프로세스가 직접 커널 오브젝트에 접근해 사용하게 된다면 어떤 프로세스가 커널 오브젝트를 사용하는지, 프로세스가 접근해서는 안될 커널 오브젝트에 접근하는지 등을 OS가 파악하기 위해서입니다. -> 요래야 잘못된 변경으로부터 안정성이 확보됩니다.


우선 이 포스팅에서는 커널 오브젝트에만 한정지어서 핸들을 설명하도록 하겠습니다.


커널 오브젝트를 생성하는 함수들 중 CreateFile을 예로 들어보면..


CreateFile은 파일 Create, Open, Write 등의 동작을 할 때 호출되는 함수로

리턴형이 HANDLE입니다.

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

요 리턴받은 일련번호(HANDLE)를 호출하면 최초 명시한 파일에 대한 동작(Open, Create, Write 등)을 할 수 있게 되는 것입니다.

(나머지 인자들은 접근 권한, 다른 프로세스와의 핸들 공유여부 등을 나타내는 인자들로 우선 생략하도록 하겠습니다.)


이렇게 리턴된 HANDLE 값을 사용하게 되면 실제 사용하고자 하는 커널 오브젝트의 주소를 얻어내 사용하게 됩니다.



핸들 삭제 (CloseHandle)

프로세스에서 핸들을 할당받아 커널 오브젝트를 사용하고나면 반드시 핸들을 반납해야합니다.

- 매 사용시가 아니라 프로세스가 종료되는 등 프로세스 생명주기 내 더 이상 해당 기능을 사용할 필요가 없을 시점


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

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

- 유효한 핸들인지 확인 (유효하지 않으면 ERROR_INVALID_HANDLE 리턴)

- 커널 오브젝트의 사용 카운트 감소

- 프로세스 핸들 테이블에서 해당 항목 삭제

의 동작을 진행하게 됩니다.


그리고 삭제 후에는 CloseHandle로 반납된 HANDLE 객체도 NULL로 초기화 해주는게 좋습니다.

- 혹시라도 중복된 HANDLE 값을 다른 프로세스가 할당받는다면 의도한 동작이 일어나지 않을 수 있습니다.

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


CloseHandle을 하지 않는다면?

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

일반적으로 프로세스가 종료되면 사용했던 모든 핸들을 정리하는 동작을 하기 때문에 괜찮지만!

윈도우가 종료될 때까지 종료되지 않는 프로그램들(백신, 그래픽 드라이버 등)이 Handle Leak을 유발하게 된다면 지속적으로 메모리를 잡아먹는 현상이 생길 것입니다.

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

'Windows > Windows Programming' 카테고리의 다른 글

프로세스의 생성 2 - CreateProcess()  (2) 2016.02.13
프로세스의 생성 1 - CreateProcess()  (0) 2016.02.09
프로세스간 커널 오브젝트 공유  (0) 2016.01.02
에러 핸들링  (0) 2015.09.28
윈도우 메세지  (0) 2014.11.16
Posted by 긍정왕오킹