커널 오브젝트와 오브젝트 핸들
커널
큰 범위에서 OS라고 한다.
OS(운영체제)에는 기본적으로 들어가 있는 프로그램이 많다.
그래서 그런 프로그램들을 쉽게 사용하기 위해 제공되는 소프트웨어도 많다
예를 들면 그림판, 날짜관리, 미디어 플레이어, 익스플로러 등등
모든 운영체제가 가지고 있는 핵심 부분이 있는데 이 부분을 커널이라 한다.
실제 운영체제를 배우면은 이 커널에 대해 배운다.
그래서 원래는 커널과 운영체제는 동일한 의미였다
근데 시간이 흐르고 운영체제가 해주는 일이 늘어나게 되었고 그래서 그 의미가 분리가 되었다.
즉 운영체제의 개념이 커져버렸다. 시간이 흘러도 운영체제의 핵심 부분은 크게 바뀌지 않았는데 이 부분을 커널이라 한다.
커널 오브젝트
커널에 의해 관리되는 리소스 정보를 담고 있는 데이터 블록
- 커널에 의해 관리되는 리소스란?
- 운영체제에 의해서 생성 및 소멸되는 것들을 말한다.
- 예를들어 개발자가 배열을 선언했고 선언한 배열에 저장하고 삭제하는 등 여러 가지 일을 한다. 이러한 것들도 리소스다.
- 이러한 일들은 커널(운영체제)에 의해서 관리되는게 아니라 프로그래머가 구현한 프로그램에 의해 관리가 되는 거다.
- 반면 윈도우즈에 의해서 생성되고 소멸되는 리소스들도 있다.
- 그러한 리소스들을 관리하기 위한 데이터 블록을 가리켜 커널 오브젝트라고 한다.
전체적인 예시를 살펴보자
- 파일이 있다고 하자 이 파일은 프로그래머에 의해 관리되는 리소스기도 하고 운영체제에 의해 관리되는 리소스기도 하다.
- 파일을 생성하기 위해서 함수를 호출한다고 하자(fopen) 함수를 호출할 때 여러 가지 권한을 부여한다. read 모드인지 write 모드인지 이 파일에 접근하기 위한 권한 설정 등
- 물리적인 공간에 파일이 존재하는 중이라고 하자
- 프로그램 상에서 파일에 접근하기 위해서 다양한 시도를 한다
- 근데 중간에 운영체제(커널)가 이거를 가로막고 있다.
- 커널이 중간에 가로막아서 무슨 일을 하냐면 만약에 파일이 read 모드로 열려 있는데 사용자가 write 모드로 함수를 호출하면 해당 요청은 허용이 안되게 한다.
- 파일 자체적으로는 그것을 허용하고 안하고의 능력이 없기 때문에 OS를 통해 그것을 허용하거나 안 할 수 있다.
- 즉 다시 말하면 파일 생성에 대한 요청을 운영체제에게 한 것이다.
- 프로그램은 파일을 만드는 방법만 알지 실제 물리적으로 어떻게 파일을 할당해야 하는지 파일 구조에 대해서는 운영체제가 알고 있다.
- 즉 프로그램은 파일과 관련된 함수를 호출한다는 건 운영체제에게 파일 생성을 요구한다는 거다
- 운영체제는 그 파일을 프로그램의 요구에 맞게 생성한다.
- 설정된 파일과 다른 요구가 오면은 그런 요구를 막는다.
- 실제로 파일을 생성해서 그것을 관리해주는 역할은 운영체제가 한다.
- 파일에 대한 접근 정보에 대해서 운영체제는 가지고 있어야 한다.
정리
운영체제에 의해서 관리되는 리소스들은 운영체제가 관리하기 위해서 데이터 블록을 내부적으로 저장하는데 이걸 가리켜 커널 오브젝트라고 한다. 다시말해 윈도우즈에 관리되는 리소스 중에 커널 오브젝트 생성을 동반하지 않는 리소스는 없다. 프로그램의 요청에 대해 적절히 허용해주기 위해서는 OS 나름대로 파일 이라는 리소스를 제어할 수 있는 정보가 필요한데 이러한 정보를 다음 데이터 블록을 가리켜 커널 오브젝트라고한다.
각각의 커널 오브젝트에 존재하는 데이터들은 다 다르다.
파일 같은 경우
- 어디까지 읽었는지에 대한 위치정보
- 접근을 어디까지 허용할 거냐는 접근 정보 등을 관리한다.
프로세스 경우
- 프로세스 상태 정보
- 이런 상태 정보를 커널 오브젝트에 저장을 해야 스케줄러에 의해서 프로세스를 실행 가능한 상태로 둘 건지 결정할 수 있다.
- 프로세스마다 우선순위가 있다.
- 실행에 있어 우선순위에 대한 정보
위에처럼 리소스마다 관리되어야 하는 데이터가 다르기 때문에 리소스들의 커널 오브젝트는 서로 동일하지 않고 다르게 디자인되어 있다.
프로세스 기반 커널 오브젝트
- createProcess 함수 호출
- 함수 호출할 때 여러 가지 정보를 함께 전달한다.
- OS에 프로세스 생성 요청이 전송됨
- OS는 프로그램이 보낸 여러가지 정보에 맞춰서 프로세스를 생성한다.
- 프로세스를 생성하는 동시에 OS는 프로세스를 관리하기 위해 필요한 커널 오브젝트도 동시에 생성한다.
- 이 커널 오브젝트는 생성한 프로세스에 대한 정보로 채워진다.
- struct_PObject
- 윈도우를 디자인한 개발자들이 커널 오브젝트를 관리하기 위한 구조체를 내부적으로 선언했다.
- 이 구조체는 프로세스 커널 오브젝트를 관리하기 위한 모델이 되는 구조체다.
- 그래서 이것을 바탕으로 생성되는 것이 커널 오브젝트이다.
- 이러한 구조체는 관리되는 리소스의 개수만큼 있어야 한다.
커널 오브젝트와 핸들의 관계
- 프로세스를 만들면 프로세스 커널 오브젝트도 생성이 되는데 여기에 우선순위 정보가 담겨 있다.
- 이 정보를 바꾼다고 하면 커널 오브젝트에 접근해서 우선순위를 바꿔줘야 한다.
- 하지만 커널 오브젝트는 중요한 요소여서 운영체제에 관리된다. 프로그래머가 직접 접근할 수 있는 영역이 아니다.
- 프로세스 커널 오브젝트에 집적 접근해서 우선순위를 바꿀 수는 없다.
- 대신 직접적인 접근은 불가능 하지만 간접적 접근은 가능하다.
- 간접 접근이라는 거는?
- 우선순위를 바꾸는 기능과 관련된 시스템 함수를 제공한다.
- 그렇다면 이 함수의 인자로는 우선순위를 바꾸고 싶은 프로세스의 커널 오브젝트를 넘겨줘야 한다.
- 하지만 커널 오브젝트에는 접근할 수가 없어 저 정보를 줄 수 없어 함수가 무용지물로 보인다.
- 이때 필요한 게 핸들 정보이다.
- 핸들은 int형 자료형이다 근데 HandleType이라고 이름이 있는데 실제 정수로 매핑이 되는 단순한 거다.
- 커널 오브젝트에는 고유값이 존재한다. 이 번호를 가리켜 핸들이라고 한다.
- 이 핸들 정보를 반환받을 수가 있다.
- 그럼 다시 돌아와서 함수를 호출할 때 인자로 위 핸들 정보를 전달할 수 있다.
정리
커널 오브젝트에 대한 직접적인 접근은 허용이 안되지만 핸들이라는 걸 통해서 어떤 커널 오브젝트의 정보를 바꿔달라는 요청 할 수가 있다. 커널 오브젝트는 구조체 변수고 핸들은 숫자다. 핸들을 얻는 방법은 리소스마다 달라 리소스 별로 핸들 얻는 방법을 체크해야 한다. 어떻게 프로세스의 핸들 정보를 얻을 수 있는가 지금 시간에는 이것에만 신경을 쓰자
예제 6-1
#include "stdio.h"
#include "tchar.h"
#include "windows.h"
int _tmain(int argc, TCHAR*argv[])
{
STARTUPINFO si = {0, };
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
TCHAR command[] = _T("C:\\\\c_cpp_study\\\\system_programming\\\\cmake-build-debug\\\\chapter06_6-1_Operation2.exe");
CreateProcess(
NULL , command , NULL , NULL ,
TRUE, 0 ,NULL , NULL , &si , &pi
);
while (1)
{
for (DWORD i =0; i<10000; i++) {
for (DWORD i = 0; i< 10000; i++); // Busy Waiting !
}
_fputts(_T("Operation1.exe \\n") , stdout);
}
return 0;
}
for (DWORD i =0; i<10000; i++) {
for (DWORD i = 0; i< 10000; i++); // Busy Waiting !
}
Busy Waiting이라는 거는 기다리기는 기다리는데 바쁘게 기다린다는 거다.
CPU는 상당히 고속이다. 그러다 보니 출력 결과가 너무 빠르다 그래서 관찰하기가 힘들다
그래서 출력되는 속도를 좀 늦추고 싶다. 그래서 보통 많이 생각하는 게 sleep이라는 함수를 많이 생각한다.
이 sleep 함수를 호출하면 실행의 속도가 늦춰진다. sleep 함수를 호출하면 자신의 실행시간을 10ms 동안 포기한다.
즉 sleep 함수를 호출하면 blocked 상태가 된다.
CPU가 계속 사용되다가 우선순위가 높은 프로세스가 등장하면 running상태에서 ready 상태로 바뀐다.
현재 우선순위의 높고 낮음에 따라서 실행의 양을 확인하자는 건데 이거를 sleep으로 둬버리면 주거니 받거니 실행을 해서 현재 원하는 결과를 얻을 수 없다. Busy Waiting 상태로 돌리면 우선순위가 높은 프로세스에게 양보하는 현상을 확인할 수 있다. 그래서 Busy Waiting 상태로 뒀다.
예제 6-2
#include "stdio.h"
#include "tchar.h"
#include "windows.h"
int _tmain(int argc, TCHAR* argv[])
{
SetPriorityClass(GetCurrentProcess() , HIGH_PRIORITY_CLASS);
while (1)
{
for (DWORD i =0; i<10000; i++) {
for (DWORD i=0; i<10000; i++) {
}
}
fputs(_T("Operation2.exe \\n"),stdout);
}
return 0;
}
- GetCurrentProcess()
- 나 자신의 핸들 값을 얻을 때 사용한다.
- 현재 나의 커널 오브젝트 값을 바꾸고 싶으면 나의 핸들 값이 필요하다 그때 사용하는 메서드가 GetCurrentProcess()이다
- 이 함수를 호출한 프로세스의 핸들 정보가 반환된다.
- HIGH_PRIORITY_CLASS
- 일반적인 프로세스보다는 높은 우선순위를 둔다.
- SetPriorityClass()
- 우선순위를 변경하는 함수다.
- SetPriorityClass(GetCurrentProcess() , HIGH_PRIORITY_CLASS);
- SetPriorityClass 함수를 호출해서 첫 번째 인자에 해당하는 프로세스의 우선순위를 HIGH_PRIORITY_CLASS로 변경하겠다는 소리다.
커널 오브젝트와 핸들의 종속 관계
프로세스 A가 프로세스 B를 생성했고 프로세스 B는 파일을 생성했다고 했을 때 운영체제 내부적으로는 어떠한 일들이 일어나는지 알아보자
아래 이미지는 프로세스 영역 운영체제 영역으로 나눠진 게 아니다. 모두 운영체제의 영역임을 주의하자 운영체제 내에서도 세부적으로 나눠진다.
커널 오브젝트와 핸들의 관계
- 프로세스 A가 생성이 되면 프로세스 A에 대한 커널 오브젝트가 생성이 된다. 이때 커널 오브젝트만 생성되는 게 아니라 프로세스 A만의 핸들 테이블이 생성된다.
- 커널 오브젝트가 생성이 되면 핸들값이 지정이 되고 이 핸들값을 통해 접근한다.
- 그러면 핸들 테이블의 핸들에는 핸들 값이 들어가고 대상에는 해당 핸들 값에 매핑이 되는 커널 오브젝트를 가리킨다.
- UC(Usage Count)는 커널 오브젝트에 접근 가능한 핸들 개수이다.
5. 프로세스 B의 커널 오브젝트 핸들 값이 3이라고 하자 그러면 프로세스 B의 핸들 테이블의 핸들 값에는 3이 있고 대상은 프로세스 B의 커널 오브젝트이다. 그러면 이때 UC 값은 1인 거 같지만 2가 된다.
6. 프로세스 A에 의해 프로세스 B가 생성이 될 때 프로세스 B의 핸들값이 A에게 반환이 된다. 즉 프로세스 A는 프로세스 B의 커널 오브젝트에 접근할 수 있는 핸들 값을 얻게 된다. 그때 핸들값을 3으로 하면 안 된다. 왜냐면 프로세스 A의 핸들 테이블에는 3이 존재해서 중복이 돼버린다. 그래서 그 값을 내부적으로 7이라고 가정해 보자 그러면 핸들값 7은 프로세스 B의 커널 오브젝트를 가리킨다.
7. 프로세스 B는 3이라는 핸들값으로 프로세스 B의 커널 오브젝트에 접근하고 프로세스 A는 7이라는 값으로 프로세스 B의 커널 오브젝트에 접근한다. 즉 커널 오브젝트는 하나의 숫자 값으로 매핑이 되는 게 아니다.
8. 실제 핸들 값은 각 프로세스 영역에서만 의미를 지닌다. 프로세스 A가 핸들 값을 참조해서 대상을 찾기 위해 필요한 게 핸들 값이지 실제 프로세스 A의 커널 오브젝트에 3이라는 값이 매핑이 돼서 모든 프로세스가 프로세스 A의 커널 오브젝트에 접근하려면 3이라는 값을 통해 접근하는 게 아니다. 즉 핸들 값은 프로세스에 종속적이다. 핸들 값이 프로세스에 종속적이다라는 의미는 핸들 테이블도 프로세스에 종속적이다.
9. 프로세스 A에도 핸들값 3이 있고 프로세스 B에도 핸들값 3이 있지만 각각의 프로세스에 종속적이어서 각 프로세스의 핸들값이 의미하는 바가 다르다. 프로세스 A의 3은 프로세스 A의 커널 오브젝트를 가리키고 프로세스 B의 3은 프로세스 B의 커널 오브젝트를 가리킨다.
10. 프로세스 A에도 부모 프로세스가 존재한다. 따라서 프로세스 A 커널 오브젝트의 UC 값은 2이다.
11. 이제 프로세스 B가 파일을 생성했다고 하자 그러면 파일 커널 오브젝트가 생성이 되고 프로세스 B의 핸들 테이블에는 핸들값 4가 생성이 되고 대상은 파일 커널 오브젝트이다.
12. 파일 같은 리소스는 생성한 프로세스만 접근이 가능해서 위 상황에서 파일 커널 오브젝트의 UC 값은 1이다.
프로세스 B가 소멸 됐다고 가정해 보자(프로세스 B의 핸들 테이블도 사라짐)
이때 프로세스 B의 커널 오브젝트는 소멸되지 않는다 왜냐면 프로세스 A가 프로세스 B의 커널 오브젝트를 참조할 수 있기 때문이다. 그래서 프로세스 B의 커널 오브젝트는 남아있게 되고 UC값만 줄여주면 된다. 프로세스 A가 프로세스 B의 커널 오브젝트를 참조하지 않는다면 UC 값은 0이 되고 프로세서 B의 커널 오브젝트는 없어진다. 프로세스가 커널 오브젝트를 참조하지 않는다면 커널 오브젝트의 UC값은 1씩 줄어들고 0이 되는 순간 커널 오브젝트는 사라진다. 파일의 커널 오브젝트가 사라졌다고 해서 파일 자체가 사라지는 게 아님을 주의하자.
프로세스가 소멸이 됐는데 다른 프로세스가 커널 오브젝트를 참조한다고 해서 소멸된 프로세스의 커널 오브젝트를 남겨둬야 할 필요가 있는가?
- 프로세스 B가 종료되면 1을 리턴하고 비정상적이면 -1을 리턴한다. 이 값은 프로세스 B의 커널 오브젝트로 들어간다.
- 즉 프로세스 B의 커널 오브젝트에는 프로세스 B가 적절히 실행을 하고 끝을 냈는지에 대한 종료 코드값도 들어간다.
- 프로세스 B가 종료되자마자 커널 오브젝트가 사라지면 부모 프로세스인 A는 자식 프로세스인 B가 적절히 종료를 하고 나갔는지 알 수 없다. 그래서 커널 오브젝트를 참조하고 있는 프로세스가 하나라도 있으면 운영체제는 해당 커널 오브젝트를 내버려둔다.
프로세스 A가 생성이 됐을 때 커널 오브젝트를 가리키는 핸들값이 핸들 테이블에 등록이 되는가?
- GetCurrntProcess() 함수는 어떤 프로세스가 호출하든지 고유한 값으로 리턴이 된다.
- 핸들 테이블에 등록되어있는 핸들값이 리턴이 되는 게 아니라 자기 자신을 의미하는 값으로서 윈도우즈 계열에서 약속되어 있는 상수값이 리턴이 된다.
#include "stdio.h"
#include "tchar.h"
#include "windows.h"
int t_main(int argc , TCHAR* argv[])
{
STARTUPINFO si = {0,};
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
TCHAR command[] = _T("C:\\\\c_cpp_study\\\\system_programming\\\\cmake-build-debug\\\\chapter06_6-1_Operation2.exe");
CreateProcess(
NULL , command , NULL , NULL , TRUE ,
0 , NULL , NULL , &si, &pi
);
DWORD timing = 0;
while (1)
{
for (DWORD i=0; i<10000; i++)
for(DWORD i=0; i<10000; i++);
_fputts(_T("Parent \\n"), stdout);
timing += 1;
if (timing == 2)
SetPriorityClass(pi.hProcess,NORMAL_PRIORITY_CLASS);
}
return 0;
}
#include "stdio.h"
#include "tchar.h"
#include "windows.h"
int _tmain(int argc, TCHAR* argv[])
{
SetPriorityClass(GetCurrentProcess() , HIGH_PRIORITY_CLASS);
while (1)
{
for (DWORD i =0; i<10000; i++) {
for (DWORD i=0; i<10000; i++) {
}
}
fputs(_T("Operation2.exe \\n"),stdout);
}
return 0;
}
- STARTUPINFO
- 어떻게 생성을 해라라는 정보를 주기 위한 구조체
- PROCESS_INFORMATION
- 프로세스의 정보를 얻기 위한 구조체
- pi.hProcess
- 생성한 프로세스의 핸들 정보를 얻는다.
- 프로세스를 처음 생성할 때는 HIGH_PRIORITY_CLASS를 통해 우선순위를 높게 주지만 시간이 지나면 우선순위를 NORMAL_PRIORITY_CLASS를 통해 일반적인 우선순위로 변경을 한다.
- 다른 프로세스의 커널 오브젝트에 접근하고 있는 모델이다.
- 생성한 프로세스의 핸들 정보는 PROCESS_INFORMATION을 통해 얻을 수 있다.
PROCESS_INFORMATION 구조체
typedef struct _PROCESS_INFORMATION
{ HANDLE hProcess; // 프로세스의 핸들
HANDLE hThread; // 쓰레드 핸들
DWORD dwProcessId; // 프로세스의 ID
DWORD dwThreadId; // 쓰레드 ID
}
프로세스 핸들은 프로세스의 커널 오브젝트를 가리키기(구분 짓기) 위한 것이고, 프로세스 ID는 커널 오브젝트가 아니라 프로세스 자체를 구분짓기 위한 것이다.
/KernelObjProb1.cpp
#include "stdio.h"
#include "tchar.h"
#include "windows.h"
int _tmain(int argc, TCHAR *argv[]) {
STARTUPINFO si = {0,};
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
TCHAR command[] = _T("C:\\\\c_cpp_study\\\\system_programming\\\\cmake-build-debug\\\\chapter06_6-3_KernelObjProb2.exe");
CreateProcess(
NULL, command, NULL, NULL, TRUE,
0, NULL, NULL, &si, &pi
);
CloseHandle(pi.hProcess);
return 0;
}
/KernelObjProb2.cpp
#include "stdio.h"
#include "tchar.h"
#include "windows.h"
int _tmain(int argc, TCHAR * argv[])
{
DWORD n =0;
while (n < 100)
{
for (DWORD i =0; i<10000; i++)
for (DWORD i = 0; i< 10000; i++); // Busy Waiting !
_fputts(_T("KernelObjProb2.exe \\n"),stdout);
n++;
}
return 0;
}
/OperationStateParent.cpp
/*
프로그램 실행 결과에 따른 반환값 확인
* */
#include "stdio.h"
#include "tchar.h"
#include "windows.h"
int _tmain(int argc, TCHAR * argv[])
{
STARTUPINFO si = {0,};
PROCESS_INFORMATION pi;
DWORD state;
si.cb = sizeof(si);
si.dwFlags = STARTF_USEPOSITION | STARTF_USESIZE;
si.dwX = 100;
si.dwY = 200;
si.dwXSize = 300;
si.dwYSize = 200;
si.1pTitle = _T("return & exit");
TCHAR command[] = _T("OperationStateChild.exe");
CreateProcess (NULL , command,
NULL,NULL, TRUE ,
CREATE_NEW_CONSOLE,
NULL , NULL,
&si, &pi
);
for (DWORD i=0; i< 10000; i++)
for (DWORD i=0; i<10000; i++);
}
CloseHandle
정리
CloseHandle 함수는 커널 오브젝트의 UC 값을 하나 줄이고 핸들 테이블에서 해당 핸들정보를 삭제하는 기능이다.
주의할 점은 CloseHandle 함수가 해당 대상을 종료시키는 함수가 아니다.
CloseHandle 함수에 대한 정확한 이해
A라는 이름의 프로세스가 생성되면, A 프로세스를 위한 커널 오브젝트가 생성된다.
이때 커널 오브젝트는 완전히 프로세스를 대표하게 된다.
그 역도 성립할까? 성립하지 않는다.
프로세스가 소멸된다고 해서 커널오브젝트가 소멸될 수도 있고 아닐 수도 있다. 운영체제가 결정할 일이다.
CloseHandle 함수와 프로세스 소멸
#include "stdio.h"
#include "tchar.h"
#include "windows.h"int _tmain(int argc, TCHAR *argv[]) {
STARTUPINFO si = {0,};
PROCESS_INFORMATION pi;
si.cb = sizeof(si);
TCHAR command[] = _T("KernelObjProb2.exe");
CreateProcess(
NULL, command, NULL, NULL, TRUE,
0, NULL, NULL, &si, &pi
);
CloseHandle(pi.hProcess);
return 0;
}
CloseHandle 함수와 프로세스 종료 코드
운영체제는 프로세스가 종료되면 커널 오브젝트를 소멸시킨다.
커널 오브젝트와 Usage Count
자식 프로세스의 종료 코드는 자식 프로세스의 커널 오브젝트에 저장된다.
자식 프로세스가 종료될 때 커널 오브젝트도 동시에 소멸된다면 부모 프로세스는 종료 코드를 얻을 수 없게 된다.
때문에 프로세스가 종료되었다고 해서 커널 오브젝트까지 동시에 소멸시키지는 않는다.
그렇다면 언제 커널 오브젝트를 소멸시키는 것이 좋을까?
해당 커널 오브젝트를 참조하는 대상이 하나도 없을 때 소멸시키는 것이 가장 이상적이다.
Windows는 이러한 정책을 기반으로 커널 오브젝트 소멸 시기를 결정짓기 위해 Usage Count(참조 횟수)라는 것을 관리한다. 이 Usage Count가 0이 되는 순간 해당 커널 오브젝트는 소멸된다.
프로세스는 생성과 동시에 커널 오브젝트의 Usage Count가 1이 된다.
만약 생성과 동시에 Usage Count 가 0으로 초기화된다면, 커널 오브젝트 소멸 원칙에 의해 생성과 동시에 소멸되고 만다.
이를 막기 위해서 자식 프로세스는 생성과 동시에 Usage Count가 1이 된다.
Usage Count와 CloseHandle
자식 프로세스가 종료되면 커널 오브젝트에 접근하는 대상이 하나 줄어든다.
CloseHandle 함수는 핸들을 반환하면서 커널 오브젝트의 Usage Count를 하나 감소시키는 기능을 지닌다.
정리
모든 운영체제가 가지고 있는 핵심 부분이 있는데 이 부분을 커널이라 한다.
그래서 원래는 커널과 운영체제는 동일한 의미였다.
근데 시간이 흐르고 운영체제가 해주는 일이 늘어나게 되었고 그래서 그 의미가 분리가 되었다.
즉 운영체제의 개념이 커져버렸다. 시간이 흘러도 운영체제의 핵심 부분은 크게 바뀌지 않았는데 이 부분을 커널이라 한다.
커널 오브젝트란 커널에 의해 관리되는 리소스 정보를 담고 있는 데이터 블록이다.
- 커널에 의해 관리되는 리소스란?
- 운영체제에 의해서 생성 및 소멸되는 것들을 말한다.
- 윈도우즈에 의해서 생성되고 소멸되는 리소스들이 있다.
- 그러한 리소스들을 관리하기 위한 데이터 블록을 가리켜 커널 오브젝트라고 한다.
프로그램의 요청에 대해 적절히 허용해 주기 위해서는 OS 나름대로 파일이라는 리소스를 제어할 수 있는 정보가 필요한데 이러한 정보를 다음 데이터 블록을 가리켜 커널 오브젝트라고 한다. 운영체제에 의해서 관리되는 리소스들은 운영체제가 관리하기 위해서 데이터 블록을 내부적으로 저장하는데 이걸 가리켜 커널 오브젝트라고 한다. 다시 말해 윈도우즈에 관리되는 리소스 중에 커널 오브젝트 생성을 동반하지 않는 리소스는 없다. 리소스마다 관리되어야 하는 데이터가 다르기 때문에 리소스들의 커널 오브젝트는 서로 동일하지 않고 다르게 디자인되어 있다.
프로세스를 생성하는 동시에 OS는 프로세스를 관리하기 위해 필요한 커널 오브젝트도 동시에 생성한다.
커널 오브젝트에 대한 직접적인 접근은 허용이 안되지만 핸들이라는 걸 통해서 어떤 커널 오브젝트의 정보를 바꿔달라는 요청을 할 수 있다. 커널 오브젝트는 구조체 변수고 핸들은 숫자다.
커널 오브젝트는 하나의 숫자 값으로 매핑이 되는 게 아니다. 즉 핸들 값은 프로세스에 종속적이다.
CloseHandle 함수는 커널 오브젝트의 UC 값을 하나 줄이고 핸들 테이블에서 해당 핸들정보를 삭제하는 기능이다.
주의할 점은 CloseHandle 함수가 해당 대상을 종료시키는 함수가 아니다.
'운영체제 > 뇌를 자극하는 윈도우즈 시스템 프로그래밍' 카테고리의 다른 글
뇌를 자극하는 윈도우즈 시스템 프로그래밍 8장 (0) | 2024.09.05 |
---|---|
뇌를 자극하는 윈도우즈 시스템 프로그래밍 7장 (0) | 2024.09.05 |
뇌를 자극하는 윈도우즈 시스템 프로그래밍 5장 (0) | 2024.05.04 |
뇌를 자극하는 윈도우즈 시스템 프로그래밍 4장 (0) | 2024.05.04 |
뇌를 자극하는 윈도우즈 시스템 프로그래밍 3장 (0) | 2024.05.03 |