본문 바로가기

Windows/_System Programming

커널 오브젝트(Kernel Object)

커널 오브젝트 : Windows 운영체제에서 리소스(Resource : 프로세스, 쓰레드, 파일)들을
                      관리하기 위한 데이터를 저장하는 메모리 블록



Windows에서 관리하는 리소스 특성을 변경하기 위해서는 해당 리소스의 커널 오브젝트를 조작해야한다.

해당 리소스의 정보를 저장하고 있는 커널 오브젝트에 접근하기 위해서는

커널 오브젝트들을 구별하는 커널 오브젝트 핸들(Object Handle)을 얻어야 한다.



커널 오브젝트와 핸들 :

커널 오브젝트는 Windows 운영체제에 종속적이다.

사용자가 리소스 생성을 요청하면 운영체제에서 사용자가 요청한 대로 리소스를 생성하게 되고

이를 관리하기 위해 커널 오브젝트를 생성한다.

즉, 커널 오브젝트는 Windows 운영체제에 의해 생성 및 소멸이 결정된다.


리소스가 생성되어 커널 오브젝트가 생성되면 커널 오브젝트에 핸들이 부여되고

부모 리소스도 구조체 변수를 통해 자식의 커널 오브젝트 핸들을 획득할 수 있다.

즉, 부모와 자식이 자식의 커널 오브젝트를 공유한다.


예)

부모 프로세스가 자식 프로세스의 커널 오브젝트 핸들 획득.

typedef struct _PROCESS_INFORMATION
{
      HANDLE hProcess;            // 커널 오브젝트 구분 위한 핸들
      HANDLE hThread;
      DWORD dwProcessId;        // 프로세스 구분 위한 ID
      DWORD dwThreadId;         
} PROCESS_INFORMAION;

위 구조체는 CreateProcess 호출할때 인자로 전달되는 구조체이다.(&pi)
호출이 완료되면 이 구조체에 자식 프로세스의 커널 오브젝트 핸들값이 hProcess 에 저장된다.

자신의 커널 오브젝트 핸들 획득.

GetCurrentProcess()

위함수를 사용하면 자신의 커널 오브젝트 핸들값을 리턴한다.



커널 오브젝트와 Usage Count :

운영체제는 해당 커널 오브젝트를 참조하는 대상이 하나도 없을때 커널 오브젝트를 소멸시킨다.

참조하는 대상은 Usage Count(참조 횟수)로 관리한다.

즉, Usage Count = 0 일 때 커널 오브젝트를 소멸한다.

리소스의 생성과 동시에 해당 커널 오브젝트의 Usage Count = 1 이된다.
생성이 완료되면 부모가 자식 리소스 커널 오브젝트의 핸들을 획득하기에 Usage Count = 2 가 된다.

만약 자식 리소스를 소멸하면 Usage Count 가 하나 줄어든다.

여기서 문제가 발생한다. 리소스가 소멸됬음에도 그 리소스를 관리하는 커널 오브젝트는 소멸되지 않는다.
(Usage Count 가 1이므로)

Usage Count = 0 을 만들기 위해선

부모의 자식의 커널 오브젝트 참조를 해제해야 한다.

CloseHandle() 함수를 사용하면 자식의 커널 오브젝트 핸들을 반환하여 참조를 해제한다.

즉, Usage Count 가 하나 줄어든다.

따라서 커널 오브젝트를 소멸하기 위해서는

부모가 소유한 자식의 커널 오브젝트 핸들을 반환해야 한다.


예)

부모 프로세스가 자식의 커널 오브젝트 핸들을 반환하지 않아 커널 오브젝트가 소멸되지 않았다고 가정할때

계산기 프로세스를 생성하면 그에 따른 커널 오브젝트가 생성된다.

계산기 프로세스를 종료시켜도 커널 오브젝트는 소멸되지 않는다(Usage Count =  1이므로 )
 
실행-> 종료, 실행 -> 종료 를 반복한다고 할때

커널 오브젝트는 실행의 수만큼 존재한다.

따라서 이 문제를 해결하기 위해 CloseHandle 을 통해 부모의 자식의 커널 오브젝트 참조를 해제함으로써

자식 프로세스가 종료될때 Usage Count = 0 이 되어 커널 오브젝트가 소멸된다)


(참고 :

바탕화면에서 아이콘을 통해 프로세스를 생성할 경우에도 Usage Count = 2 다.

바탕화면 자체도 프로세스이기 때문이다. 이 때는 바탕화면이 부모 프로세스가 된다.
(Cmd 에서 실행하면 Cmd 가 부모 프로세스)

즉, 프로세스는 생성과 동시에 Usage Count = 2 가 된다)