6 장 . 커널 오브젝트 와 오브젝트 핸들 I . 커널 오브젝트 에 대한 이해 - 커널 : 컴퓨터 를 운영 하 는데 있 어서 중심 이 되 는 운영 체제 의 핵심 부분 -> 일반 적 으로 커널 과 운영 체제 를 같 은 의미 로 사용 - 커널 오브젝트 : 커널 에서 관리 하 는 중요 한 정보 들 을 담 아 둔 데이터 블록 1 . 커널 오브젝트 의 이해 - 프로세스 의 생 성과 소멸 , 상태 벼화 , 관리 는 모두 운영 체제 몫 - 여러 개 의 프로세스 르 관리 하 면 고정 적 으로 저장 하 고 갱신 할 정보 가 존재 ex ) 프로세스 상태 정보 ( Running , Blocked , Ready 상태 ) , 우선 순위 정보 => 운영 체제 내부 에 저장 되 어야 할 정보 , 변경 될 때 마다 갱신 되 어야 함 -> 프로세스 스 케 쥴 러 가 이 를 바탕 으로 프로세스 를 관리 - 프로세스 에 관련 된 정보 를 저장 , 참조 및 변경 할 수 있 는 구조 체 존재 ( 편의 상 ' 프로세스 관리 구 조체 ' 라 함 ) - 프로세스 가 생성 된 후 정보 를 초기 화 한 것 이 커널 오브젝트 - 프로세스 관리 구조 체 는 어떻게 구성 되 어 있 는지 알 수 없 음 ( 마이크 로 소프트 가 공개 하 지 않 음 ) => 프로세스 의 커널 오브젝트 는 프로그래머 가 직접 생성 하 거나 조작 하 는 것 을 막 음 2 . 그 이외 의 커널 오브젝트 - 프로세스 내 에 쓰레드 를 생성 할 때 , IPC 를 위해 사용 하 는 파이프 나 메일 슬롯 을 생성 할 때 도 커널 오브젝트 를 생성 해야 함 - 커널 오브젝트 종류 에 따라 다른 구조 체 를 생 성 ex ) 파일 커널 오브젝트 -> 파일 속성 정보 ( Read 모드 , Read / Write 모드 . .. ) 프로세스 커널 오브젝트 -> 프로세스 우선 순위 정보 ( 스 케 쥴 링 을 위해 ) => ∴ Windows 운영 체제 는 프로세스 , 쓰레드 와 파일 같 은 Resource 들 을 원활히 관리 하 기 위해 데이터 를 저장 하 는 메모리 블록 이 존재 => 커널 오브젝트 - 데이트 블록 : 커널 오브젝트 | 프로세스 나 파일 : Resource - Windows 커널 에 의해 관리 되 는 리소스 수 만큼 커널 오브젝트 도 생성 됨 II . 오브젝트 핸들 ( Handle ) 을 이용 한 커널 오브젝트 의 조작 - 프로그래머 는 직접 커널 오브젝트 를 조작 할 수 없 음 - 리소스 의 특성 을 변경 하 기 위해 선 ( 프로세스 우선 순위 변경 같 은 ) 해당 리소스 커널 오브젝트 를 조작 해야 함 -> 마이크 로 소프트 에서 제공 하 는 시스템 함수 를 이용 ( 안정 적 인 방식 ) 1 . 프로세스 우선 순위 ( Priority ) 변경 ex ) BOOL SetPriorityClass ( HANDLE hProcess ; / / 우선 순위 를 변경 할 프로세스 의 핸들 DWORD dwPriorityClass ; / / 새롭 게 적용 할 우선 순위 ) ;- 핸들 ( Handle ) : 커널 오브젝트 에 할당 되 는 숫자 ( 정수형 ) 2 . 커널 오브젝트 에 할당 되 는 숫자 = 핸들 ( Handle ) - Windows 는 커널 오브젝트 를 생성 할 때 마다 핸들 을 하나 씩 부여 3 . 핸들 정보 - 핸들 정보 를 얻 는 방법 은 커널 오브젝트 종류 에 따라서 다양 함 ( 프로세스 , 파일 , 쓰레드 . ..)- GetCurrentProces 함수 -> 현재 실행 되 고 있 는 프로세스 의 핸들 을 얻 을 떄 사용 => 항상 같 은 값 을 리턴 ( - 1 ) - '- 1 ' 은 자기 자신 을 의미 - 함수 가 호출 되 어 실행 되 는 중 에 ( 함수 는 여러 개 의 명령어 로 구성 ) CPU 할당 시간 을 다른 프로세스 에 넘겨 줄 수 있 음 => 우선 순위 를 넘기 는 기준 은 CPU 관점 에서 명령어 단위 가 기준 III . 커널 오브젝트 와 핸들 의 종속 관계 1 . 커널 오브젝트 의 종속 관계 - 커널 오브젝트 는 Windows 운영 체제 에 종속 적 ① 커널 오브젝트 에 종속 적 인 것 이 아니 라 , 운영 체제 에 종속 적 인 관계 로 커널 오브젝트 의 소멸 시점 은 운영 체제 에 의해 결정 됨 ② 커널 오브젝트 는 여러 프로세스 에 의해 접근 이 가능 ( 물론 함수 호출 을 통한 간접 호출 ) 2 . 핸들 의 종속 관계 - 핸들 ( 핸들 테이블 ) 은 운영 체제 에 종속 적 이 지 않 고 프로세스 에 종속 적 ex ) 프로세스 의 우선 순위 를 높이 기 위해서 는 핸들 을 이용 해 커널 오브젝트 에 접근 . - PROCESS _ INFORMATION 구 조체 typedef struct _ PROCESS _ INFORMATION { HANDLE hProcess ; / / 프로세스 핸들 HANDLE hThread ; / / 쓰레드 핸들 DWORD dwProcessID ; / / 프로세스 의 ID DWORD dwThreadID ; / / 쓰레드 의 ID } PROCESS _ INFORMATION ; 3 . 프로세스 핸들 과 ID - 운영 체제 는 프로세스 생 성시 프로세스 들 을 구분 짓 기 위해 ID ( 식별자 ) 를 할당 - 프로세스 핸들 : 프로세스 의 커널 오브젝트 를 가리키 기 ( 구분 짓 기 ) 위함 - 프로세스 ID : 커널 오브젝트 가 아니 라 프로세스 자체 를 구분 짓 기 위함 - CreateProcess 함수 를 통해 프로세스 를 생성 하 면 쓰레드 라는 시스템 리소스 도 생성 됨 IV . 커널 오브젝트 와 Usage Unit 1 . CloseHandle 함수 에 대한 정확 한 이해 CreateProcess 함수 호출 이 커널 오브젝트 의 생성 원인 이나 단지 프로세스 의 생 성 을 요청 할 뿐 프로세스 생 성 의 주체 는 운영 체제 이 다 . ( 함수 가 아님 ) - 프로세스 생 성시 , 그 프로세스 르 위한 커널 오브젝트 가 생성 됨 - but 프로세스 가 소멸 한다고 해서 커널 오브젝트 가 소멸 하 진 않 음 => 소멸 할 수 도 있 으나 하 지 않 을 수 도 있 음 - BOOL CloseHandle ( Handle hObject / / 핸들 을 닫 음 ( 반환 ) -> 핸들 의 소멸 , 리소스 해제 를 의미 하 지 않 음 ) ; 2 . 커널 오브젝트 와 Usage Count - 자식 프로세스 의 종료 코드 는 자식 프로세스 커널 오브젝트 에 저장 됨 - if 자식 프로세스 가 종료 될 때 커널 오브젝트 도 소멸 되 면 종료 코드 는 사라짐 => ∴ 프로세스 가 종료 되 어도 커널 오브젝트 는 동시 에 소멸 하 지 않 음 - 해당 커널 오브젝트 를 참조 하 는 대상 이 없 을 때 소멸 하 는 것 이 이상 적 => windows 가 커널 오브젝트 를 소멸 시키 는 방법 - 프로세스 의 생 성 과 동시 에 커널 오브젝트 의 Usage Count = 1 - 프로세스 에 접근 가능 한 핸들 수 가 늘어날 때 마다 Usage Count 증가 - 자식 프로세스 의 Usage Count = 2 ( 부모 프로세스 참조 + 자기 자신 참조 ) => 부모 프로세스 가 CreateProcess 함수 호출 과정 에서 PROCESS _ INFORMATION 구 조체 를 통해 자식 프로세스 의 핸들 을 얻 기 때문 - 핸들 값 은 커널 오브젝트 에 매핑 되 지 않 음 -> 각각 의 핸들 테이블 에서 핸들 값 을 사용 => ∴ 핸들 값 , 핸들 테이블 은 프로세스 에 종속 적 - 자식 프로세스 가 사라지 면 프로세스 에 종속 적 인 핸들 테이블 이 사라지 나 부모 프로세스 에서 자식 프로세스 커널 오브젝트 를 보 고 있 으므로 ( 핸들 테이블 에서 사용 중 ) 커널 오브젝트 는 사라지 지 않 고 단지 Usage Count 를 2 에서 1 로 감소 시킴 => UC ( Usage Count ) 가 존재 하 는 이유 - 운영 체제 영역 에서 커널 오브젝트 가 있 음 = 커널 오브젝트 의 소멸 은 운영 체제 게 UC 를 통해 정함 - UC 가 0 이 되 면 커널 오브젝트 는 소멸 ( but 파일 은 물리 적 으로 남 아 있 음 ) Q 1 . 프로세스 생 성시 자기 자신 의 커널 오브젝트 를 핸들 테이블 에서 참조 하 는가 ? - 프로세스 생 성시 자기 자신 의 커널 오브젝트 에 대한 핸들 정보 는 핸들 테이블 에 저장 하 지 않 음 but GetCurrentProcess 는 상수 ( - 1 ) 을 리턴 - 함수 들 은 - 1 이 리턴 되 면 현재 프로세스 를 지칭 한다고 인식 함 ( windows 의 약속 ) Q 2 . 자식 프로세스 가 종료 된 후 부모 프로세스 가 자식 프로세스 의 커널 오브젝트 를 참조 한다고 해서 커널 오브젝트 를 남겨둘 이유 가 있 는가 ? - 부모 프로세스 는 자식 프로세스 가 정상 종료 햇 는가 가 궁금 함 - 자식 프로세스 가 소멸 되 자 마자 자식 프로세스 의 커널 오브젝트 가 소멸 되 면 부모 프로세스 는 자식 프로세스 의 정상 종료 여부 를 알 지 못함 => ∴ UC 를 통해 운영 체제 가 커널 오브젝트 를 관리 ! - STARTUPINFO si = { 0 , }; / / 프로세스 생 성시 초기 정보 를 전달 하 는 목적 si . cb = sizeof ( si ) ;- PROCESS _ INFORMATION pi ; / / / 생성 된 프로세스 의 정보 를 얻 기 위한 구조 체 ( 핸들 값 얻 을 수 있 음 ) - 자식 프로세스 가 종료 되 더라도 부모 프로세스 의 참조 에 의해 자식 프로세스 의 커널 오브젝트 는 남음 -> but 종료 코드 를 얻 고 더 이상 커널 오브젝트 를 참조 할 필요 가 없 다면 UC 를 0 으로 만들 어 운영 체제 가 소멸 시키 도록 해야함 ( 자원 낭비 를 막 기 위해 ) => CloseHandle ( pi . hProcess ) ; / / 함수 를 이용 해 UC 를 하나 줄여 메모리 낭비 방지 공유 하 기 글 요소