삽질의 현장/- 윈도우 시스템

#016_WIndow_System_커널 오브젝트 & 핸들 테이블

shovelman 2015. 9. 21. 16:59


안녕하세요 삽잡이 입니다.

이번 시간에는 핸들 테이블에 관해서 정리해보려고 합니다.


프로세스는 내부적으로 커널 오브젝트 핸들 테이블을 가지고 있습니다.

여기서 커널 오브젝트란,

커널에서 관리하는 중요한 정보들을 담아둔 데이터 블록을 말합니다.

즉, 프로세스들은 OS가 관리합니다. 그리고 관리를 위해 구조체 하나를 만들게 된 것입니다.

프로세스가 생성될 때마다 이 구조체가 하나씩 생성되고 프로세스의 정보들이 초기화 되는데,

이를 우리는 '커널 오브젝트'라고 부르는 것입니다.


아무튼...

프로세스는 내부적으로 이 커널 오브젝트 핸들 테이블을 가지고 있는 것입니다.

이 핸들 테이블이 필요한 이유는, 

모든 프로세스가 커널 오브젝트를 받을 때 커널 오브젝트를 관리하기 위해서 입니다.


또한, 

이 커널 오브젝트 핸들 테이블은 자식 프로세스가 부모 프로세스에게 상속 받을 수 있습니다.

이 말은, A라는 프로세스가 서브(자식) 프로세스를 띄우게 될 때

서브 프로세스에 A 프로세스 핸들 테이블을 상속할 수 있다는 것입니다.


이와 같이 상속을 받을 수 있는 핵심적 이유는,

테이블에 등록되어 있는 핸들에는 해당 커널 오브젝트에 대한 정보를 가지고 있는데,

자식에서도 동일한 커널 오브젝트의 정보를 갖게 되기 때문입니다.

커널 오브젝트들은 핸들 테이블을 갖고, 상속 받을 수 있다는 것이 핵심입니다.


우선, CreateEvent를 살펴보도록 하겠습니다.

해당 함수는 커널 오브젝트 이벤트 상속을 가능하도록 설정하는 것입니다.



해당 함수는 네번째 인자인 lpName 

즉, 이름이 있으면 프로세스간에 공유를 가능하도록 만들어주는 함수입니다.

ID라고 생각하시면 됩니다.

이렇게 되면 비신호 상태로 이벤트가 생성이 되고, 자식과 부모의 핸들이 똑같게 됩니다.


커널 오브젝트 이벤트란 무엇일까요... 이벤트는 정말로 많이 나오는 단어인데, 

이벤트는 동기화를 위한 커널 오브젝트를 말합니다.

동기화와 비동기화는 굉장히 중요한 단어입니다.

동기화는 sync, 비동기화는 async라고 하는데, 동기화를 위한 커널 객체중 하나가 바로 이벤트입니다.

즉, 이벤트는 동기화를 수행하기 위한 커널 오브젝트라고 하는 것입니다.

이벤트에 대해서는 나중에 다시 자세하게 설명을 하도록 하겠습니다.


핸들 테이블을 자식에게 상속하기 위해서는,

SECURITY_ATTRIBUTE 구조체가 필요합니다.

CreateProcess 함수를 통해 자식 프로세스를 생성할 때에 



해당 구조체의 세번째 인자인 상속 여부가 결정되 어있는 구조체의 주소를 넘겨줘야합니다.


아무튼...

아까 커널 오브젝트에 대해서 언급을 시작했으니 좀더 알아보도록 하겠습니다.

커널에는 커널 오브젝트와 커널 리소스가 있습니다.

따라서 우리는 커널오브젝트와 커널 리소스로 구분할 수 있어야합니다.


여기서 말하는 리소스란 '시스템의 자원'이라는 의미를 가지고 있습니다.

곧, 시스템이 어플리케이션 간에 공유하는, 시스템이 관리하는, 항상 남아돌지 않는다는 

개념을 가지고 있는 것이 리소스라는 것입니다.

그래서, 커널 오브젝트는 커널 리소스와 밀접한 연관성을 가지고 있습니다.


우리가 프로세스라고 부르는 것은 쓰레드, 이벤트 파일, 세마포어 등등이 있는데,

이는 사실 커널 리소스입니다.

즉, 모든 커널과 관련된 것들을 커널 리소스라고 부른다는 것입니다.

프로세스 자체를 리소스라고 부르고,

리소스의 정보를 유지하기 위한 하나의 메모리 단위를 가리켜 커널 오브젝트라고 부르는 것입니다.


이벤트를 포함한 다른 것들은 몰라도, 

프로세스와 쓰레드는 리소스와 커널 오브젝트를 분리하지 않고 같은 취급을 해서는 안됩니다.


왜냐하면, 프로세스가 생성되고 어느 순간 죽게 되면, 반환 종료 코드를 가져올 수 있어야하는데,

리소스와 커널 오브젝트를 같이 묶는다면 

소멸 되는순간 모든 것이 날라가니 종료코드를 받아올 수 없게 됩니다.

어딘가에서 받아와야하는데 그 어딘가가 바로 커널 오브젝트라는 것입니다.


예를 들어 메모장을 생각해보겠습니다.

메모장이 실행되면 메모장 프로세스가 생성되지요...

그렇다는것은 메모장의 커널 오브젝트가 있다는 것입니다.

그런데, 메모장이 종료되면 메모장 프로세스라는 리소스가 없어집니다.

하지만, 커널 오브젝트는 아직 없어지지 않습니다. 왜냐, 종료코드를 얻기 위해!

아무튼... 분리되어있다는 것을 잊지마세요....


다시 한번 말씀드리지만,

대부분의 커널 오브젝트와 리소스는 같다고 생각해도 되지만,

프로세스와 쓰레드는 절대로 같게 생각해서는 안됩니다.

이에 대해서는 잠시후 다시 알아보도록 하겠습니다.


여기서 잠시 핸들에 대해서 생각보도록 하겠습니다.

핸들은 리소스를 가지고 노는 것이 아닙니다. 핸들은 커널 오브젝트에 대한 핸들입니다.

핸들은 숫자인데, 이 숫자만을 가지고는 사용을 하지 못합니다.

즉, 프로세스가 전혀 다르면 같은 커널 오브젝트에 대한 핸들 번호가 같다고 보장할 수 없다는 것입니다.

커널이라는 것은 단지, 커널 오브젝트를 컨트롤 하기위한 OS가 할당해준 번호에 지나지 않다는 것입니다.


각 프로세스에는 핸들 테이블이 있고, 정보를 핸들 테이블에 할당하고 사용하게 됩니다.

핸들 테이블 내부에는 몇가지 주요 정보들이 있는데, 

커널 오브젝트가 할당된 주소가 있습니다.

예를 들어 '3000 번 주소에 할당된 핸들 번호' 이와 같이 저장이 된다는 것입니다.

우리는 각 프로세스에 다른 핸들일지 모르지만, 같은 오브젝트의 내용물이라는 것을 

이를 통해 알 수 있게 됬습니다.



모든 커널 오브젝트는 usage count라는 것을 가지고 있습니다.

사용 카운트라고 부르지요... 즉, 몇개가 나를 사용하고 있느냐를 이를 통해 알 수 있습니다.

usage count와 많이 중복되서 사용하는 내용이 refernce count라고 하는데... 아무튼...

이 count는 kernel object를 얼만큼 사용하느냐에 따라서 수가 바뀌겠지요..


모든 커널 오브젝트 핸들이 나를 얼마나 사용하고 있느냐를 usage count를 통해 알 수 있습니다.

usage count가 0이 되면 자동적으로 OS는 해당 커널 오브젝트를 날립니다.


커널 오브젝트는 공유될 수 있기 때문에 

프로세스에 의해서 누가 사용하고 있는지를 모릅니다. 

즉, usage count를 통해 누가 사용하고 있는지 모르는 커널 오브젝트가 

무작정 없어지는 것을 막는 것입니다.

특정 프로세스에서 신나게 쓰고 있는데, 죽여버리면 다른 프로세스가 못쓰는 상황이 발생하지 않겠습니까...

그 정보를 유지하기 위해서 usage count를 사용한다고요..

어찌됬건 usage count 상태로 유지가 됩니다.

여기서 우리는 중요한 사실을 알게됬습니다.

커널 오브젝트는 usage count를 가지고 있고, 프로세스가 사용할 때 증가하는 것을 알았습니다.



모든 커널 오브젝트는 상속 여부에 대한 결정 권한을 가지고 있습니다.

여기서 상속이라는 것은, 핸들 테이블을 자식 프로세스에게 물려줄 것인가에 대한 내용입니다.

한마디로, A프로세스에 자식 프로세스를 만든다고 해봅시다.

그런데, 핸들 테이블을 상속하지 않으면 자식 프로세스에 핸들 테이블은 비어져 있게됩니다.

커널 오브젝트들에 대한 정보를 안가지고 있게 되는 것입니다.

그런데, 상속을 할 때 부모의 핸들 테이블을 상속한다고 해봅시다.

그러면 상속이 그대로 되는 것이 아닙니다.

중요한 것은, 핸들 테이블에는 각각 상속 여부도 결정된다는 것입니다.


커널 오브젝트를 생성하거나 연결할 때 '상속 가능/불가능 한 핸들'이라는 것이 있습니다.

그러면, 생성, 연결할 때 프로세스에 테이블에도 그 여부가 저장되는 것입니다.

그 결과로 자식 프로세스에 핸들 테이블을 상속할 때 테이블 정보로 인해 상속 여부가 결정되겠지요...


자식 프로세스를 생성하는 동시에 내가 가지고 있는 핸들 테이블을 

상속할지 안할지에 대해서 결정되고 상속 한다고 하면,

테이블에 상속된다는 놈들만 상속 되게 되는 것입니다.

그럼 자식 프로세스에서 상속하면, 해당 커널 오브젝트의 usage count도 증가되겠군요...


정리하자면, 핸들 객체, 핸들 테이블이 상속해줄 때 

자식테이블에서 커널 오브젝트의 핸들을 사용할 수 있게 되는 것입니다.



핸들을 닫으면, 자기 자신의 핸들 테이블에서 사라지고, 

핸들 객체 즉, 커널 오브젝트의 usage count의 숫자가 감소하게 됩니다.

지금까지 커널 오브젝트의 개념에 대해서 알아봤습니다.


어렵군요...

하지만, 포기하지 않고 열심히 달려보겠습니다.

이상 삽잡이였습니다!