hahahia

커널 오브젝트와 오브젝트 핸들 02 본문

Windows Programming/Windows::System

커널 오브젝트와 오브젝트 핸들 02

hahahia 2012. 3. 14. 22:00

GetCurrentProcess 함수를 잠깐 봅시다

HANDLE GetCurrentProcess(VOID);

- 현재 실행되고 있는 프로세스의 핸들을 얻을 때 사용하는 함수입니다.
 
커널 오브젝트와 핸들의 종속 관계

- 커널 오브젝트는 Windows 운영체제에 종속적입니다

여기서 잠깐 비유(?)를 통해 종속 관계를 표현해보겠습니다
책 - 커널 오브젝트, 고객 - 프로세스, 도서 대여점 - 운영체제

- 커널 오브젝트는 프로세스에 종속적인 것이 아니라, 운영체제에 종속적인 관계커널 오브젝트의 소멸지점은 운영체제에 의해 결정된다.
-> 풀이를 해보자면 책은 고객이 마음대로 할 수 없는 것이고, 도서 대여점에서 관리를 합니다. 그리고 책을 폐기처분은 도서 대여점에서 합니다.
- 커널 오브젝트는 프로세스에 종속적인 것이 아니라 운영체제에 종속적인 관계여러 프로세스에 의해서 접근 가능(커널오브젝트 하나에서 자식프로세스, 부모 프로세스 둘다 접근 할 수 있다라는 점 알아두시기 바랍니다)
- > 책은 고객에 대해 종속적인 것이 아니라 도서 대여점에 종속적인 관계이므로 여러 고객에 책을 볼 수 있다.

흠 더 헷갈렸나요-_-;;;
어쨋든 요약을하자면 커널 오브젝트는 운영체제에 종속적이고, 커널 오브젝트는 여러 프로세스에 의해 접근이 가능하다 이겁니다....ㅋㅋ 

그리고 핸들은 운영체제에 종속적이지 않고 프로세스에 종속적입니다. 뒤에서 자세히 설명하도록 하겠습니다.

typedef struct _PROCESS_INFORMATION
{
      HANDLE hProcess;            // 프로세스의 핸들
      HANDLE hThread;   // 쓰레드 핸들
      DWORD dwProcessId;        // 프로세스의 ID
      DWORD dwThreadId;      // 쓰레드의 ID
} PROCESS_INFORMAION;

프로세스 핸들프로세스의 커널 오브젝트를 가리키는 것이고, 여기서 프로세스 ID는 커널 오브젝트가 아니라 프로세스 자체를 구분짓기 위한 것입니다.

전에 프로세스를 생성할 때 선언하던 구조체를 정의한 것입니다.
예를들어 프로세스의 우선순위를 바꾸고싶다 하면
SetPriorityClass(pi.hProcess, NORMAL_PRIORITY_CLASS); 이런식으로
표현하면 현재 pi로 정의된 프로세스의 우선순위를 낮추게 됩니다


커널 오브젝트와 Usage Count

- 프로세스가 소멸된다고 해서 커널 오브젝트가 소멸된다고 할 수 없습니다. 소멸을 시키는 것은 바로 운영체제입니다. 
이 운영체제는 해당 커널 오브젝트가 참조하는 대상이 하나도 없을 때 커널 오브젝트를 소멸 시키는데 그 참조하는 대상을 Usage Count라는 놈이 관리를하죠 
눈치가 빠르면 알겠지만 Usage Count가 0이 되는 순간 해당 커널 오브젝트는 소멸된다고 볼 수 있겠습니다.

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

만약 자식 리소스를 소멸하면 Usage Count 가 하나 줄어들게 되겠죠??
여기서 문제가 발생하게 됩니다. 리소스가 소멸됬음에도 그 리소스를 관리하는 커널 오브젝트는 소멸되지 않습니다. 왜냐하면 Usage Count 가 1이기 때문이죠. 이렇게되면 계속해서 커널 오브젝트가 잔류하게 되어서 속도상에 문제가 발생할 수 있겠습니다.
Usage Count = 0 을 만들기 위해선 부모의 자식의 커널 오브젝트 참조를 해제해야 Usage Count가 하나 줄어들고 0이 되겠습니다.
여기서 CloseHandle() 함수를 사용하면 자식의 커널 오브젝트 핸들을 반환하여 참조를 해제하게 됩니다.

즉, Usage Count 가 하나 줄게 되겠죠.
따라서 커널 오브젝트를 소멸하기 위해서는
부모가 소유한 자식의 커널 오브젝트 핸들을 반환해야 합니다


예)

부모 프로세스가 자식의 커널 오브젝트 핸들을 반환하지 않아 커널 오브젝트가 소멸되지 않았다고 가정할때
계산기 프로세스를 생성하면 그에 따른 커널 오브젝트가 생성이 되겠죠?
계산기 프로세스를 종료시켜도 커널 오브젝트는 소멸되지 습니다 왜냐하면 Usage Count =  1이기 때문입니다
실행-> 종료, 실행 -> 종료 를 반복한다고 할때
커널 오브젝트는 실행의 수만큼 존재할텐데
따라서 이 문제를 해결하기 위해 CloseHandle 을 통해 부모의 자식의 커널 오브젝트 참조를 해제를 합니다.
자식 프로세스가 종료될때 Usage Count = 0 이 되어 커널 오브젝트가 소멸되겠죠?

정리를 해보도록 하겠습니다. 부모 프로세스가 자식 프로세스를 생성함과 동시에 커널 오브젝트가 생성됩니다. 이 과정에서 Usage Count값이 1이 되는것 같지만, 부모 프로세스가 CreatProcess 함수 호출과정에서 자식 프로세스의 핸들을 얻기때문에 결과적으로는 Usage Count = 2 가 되는것입니다. 
그리고 프로세스(자식)를 종료할 때 Usage Count값은 2-1=1 이므로 커널 오브젝트가 지워지지 않는데 이 남은 연결고리를 끊어버리기 위해 부모프로세스에서 CloseHandle 함수를 호출해 UsageCount = 0 이 되고 커널 오브젝트는 없어지게 됩니다.
또 길어지네요.....정리를 하고싶었지만 ㅠ_ㅠ
 
참고 :

바탕화면에서 아이콘을 통해 프로세스를 생성할 경우에도 Usage Count = 2 겠죠
바탕화면 자체도 프로세스이기 때문입니다. 이 때는 바탕화면이 부모 프로세스가 되고 아이콘을 통해 생성된 프로세스는 자식프로세스입니다...
(Cmd 에서 실행하면 Cmd 가 부모 프로세스)
즉, 프로세스는 생성과 동시에 Usage Count = 2 가 됩니다.

출처 : 윈도우즈 시스템 프로그래밍 | 윤성우 저 | 한빛미디어
Comments