본문 바로가기

High Level Technique/Window System

커널 오브젝트 (Kernel Object)

커널 오브젝트 (Kernel Object)




개념


프로세스의 상태정보(Ready, Running, Blocked)와 우선순위 정보를 예로 들어보자.

이러한 정보들을 운영체제 내에서 저장되는데 이러한 정보가 상태나 우선순위가 바뀜에 따라서 갱신되어야 합니다.

스케줄러가 위와 같은 정보를 가지고 관리를 할 수 있습니다. 따라서 윈도우 개발자들은 정보를 저장하기 위해서 프로세스 관리 구조체를 만들게 되었고 이를 커널 오브젝트라고 합니다.






이외의 커널 오브젝트


쓰레드, IPC 등을 생성할 때에도 커널 오브젝트가 생성됩니다. 하지만 모든 것이 동일한 구조체로 생성되는 것은 아닙니다. 종류에 따라 서로 다른 구조체가 생성됩니다.






프로세스 우선순위 변경


프로세스의 우선순위를 변경하는 것은 SetPriorityClass()를 통해서 변경할 수 있습니다.


SetPriorityClass

{

HANDLE hProcess;

DWORD dwPriorityClass;

}


HANDLE hProcess는 우선순위를 변경할 프로세스의 핸들을 말합니다.

DWORD dwPriorityClass는 새롭게 적용할 우선순위 정보를 전달합니다.


여기서 핸들이라는 것이 나왔는데 핸들은 해당 프로세스의 핸들을 말하며 이 값은 정수이며 커널 오브젝트를 생성할 때마다 부여됩니다.

즉, 프로세스가 생성이되면 커널 오브젝트 또한 생성되고 관리되어야 하기 때문에 핸들이라는 것을 지정하여 관리를 합니다. 


핸들 값은 GetCurrentProcess()를 통해서 얻을 수 있습니다.





커널 오브젝트는 윈도우에 종속적이다.


1. 커널 오브젝트는 프로세스가 아니라 운영체제에 종속족이기 때문에 소멸 또한 운영체제에 결정된다.

2. 프로세스에 종속적인 것이 아니기 때문에 여러 프로세스에 의해 접근이 가능하다.


(핸들은 운영체제에 종속적인 것이 아니라 프로세스에 종속적이다.)



커널 오브젝트가 프로세스가 아닌 윈도우에 종속적이기 때문에 둘 이상의 프로세스가 한개의 커널 오브젝트에 접근을 할 수 있습니다.


가령, A라는 프로세스가 B라는 프로세스를 생성하고 B라는 프로세스는 자신의 우선순위를 높입니다. 이후 다시 A프로세스에서 B프로세스의 우선순위를 낮춰 자신의 우선순위를 높이게 할 수 있을까요? 하나의 커널 오브젝트에 둘 이상의 프로세스가 접근이 가능하기 때문에 가능합니다.



예제


Operation1.exe


#include <stdio.h>

#include <Windows.h>

#include <tchar.h>


int main(void)

{

STARTUPINFO si = { 0, };

PROCESS_INFORMATION pi;

si.cb = sizeof(si);


TCHAR command[] = _T("Operation2.exe");


CreateProcess(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);



int timing = 0;

while (1)

{

for (int i = 0; i < 10000; i++)

{

for (int i = 0; i < 10000; i++)

{


}

}


printf("Operation1.exe \n");


timing += 1;

if (timing == 2)

{

SetPriorityClass(pi.hProcess, NORMAL_PRIORITY_CLASS);

}

}


return 0;

}


Operation2.exe는 동일.





CloseHandle()


CloseHandle()은 해당 Handle을 닫아버리는 함수다.


앞서 커널 오브젝트의 소멸 또한 운영체제가 결정한다고 했는데 A 프로세스에서 B 프로세스를 실행하고 CloseHandle()을 이용해서 B 프로세스의 Handle을 닫아버리면 어떻게 될까?

단순히 생각을 했을 때 B 프로세스의 Handle이 닫혔기 때문에 더 이상 실행이 안된다고 생각할 수 있다.



Operation1.exe


#include <stdio.h>

#include <Windows.h>

#include <tchar.h>


int main(void)

{

STARTUPINFO si = { 0, };

PROCESS_INFORMATION pi;

si.cb = sizeof(si);


TCHAR command[] = _T("Operation2.exe");


CreateProcess(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);


CloseHandle(pi.hProcess);


return 0;

}






위 결과를 보면 Operation2.exe는 계속해서 실행이 된다. (실행결과 오타)






Usage Count


자식프로세스는 자식 프로세스의 커널 오브젝트가 존재하는데 부모 프로세스 또한 같은 커널 오브젝트를 사용합니다.

자식 프로세스가 종료되어 커널 오브젝트가 소멸한다고 한다면 부모 프로세스 또한 소멸 되어야 합니다. 하지만 자식 프로세스의 커널 오브젝트가 소멸했다고 해서 부모 프로세스까지 죽어버린다는 것은 말이 안되죠.


이러한 것을 막기위해서 Usage Count를 이용하여 해당 커널 오브젝트에 얼마나 많은 프로세스가 붙어있는지 카운팅하여 관리합니다.



즉, 자식 프로세스가 해당 커널 오브젝트를 사용하므로 Usage Count가 1이 되고 부모 프로세스 또한 같은 커널 오브젝트를 사용하기 때문에 Usage Count가 2가 됩니다.


따라서 자식 프로세스를 CloseHandle()을 통해서 Handle을 반환시켜버리면 Usage Count는 1이 되지만 해당 커널 오브젝트는 존재하기 때문에 CloseHandle()의 역할은 Usage Count를 감소시킨다고 할 수 있습니다.


추가적으로 프로세스가 종료되는 시점에서도 Usage Count가 감소합니다.




'High Level Technique > Window System' 카테고리의 다른 글

커널 오브젝트 상태 (Kernel Object State)  (0) 2016.12.27
메일 슬롯 (Mail Slot)  (0) 2016.12.27
프로세스  (0) 2016.12.26
명령어, 레지스터의 구성  (0) 2016.09.20
Polymorphic  (0) 2016.09.13