본문 바로가기
WebBook/윈도우 구조

시스템 시작, 커널 생성

by 올엠 2022. 2. 13.
반응형

MBR과 부트 섹터를 지나 부트 로더인 Ntldr(비스타 이후 Winload.exe로 변경되었다)를 통해 BCD(Windows Boot Manager)의 실행까지 알아보았다.
이후 BCD는 지정된 시간 동안 입력이 없으면, 기본적으로 지정된 운영제체를 실행하여 부팅을 위한 윈도우 커널 초기화 작업을 진행하게 된다. 이때 부트 파티션에서 커널 초기화에 필요한 적절한 커널(Ntoskrnl.exe외 3가지) 파일과 HAL(Hardware Abstraction Layer) 이미지 등을 로드하고, 레지스트리 %SystemRoot%\System32\Config\System을 HIVE(연결) 하여 디바이스 드라이버를 로드하는 작업을 진행하게 된다(레지스트리에 대해서는 추후 커널과 유저의 소통에서 다룬다).
커널 초기화를 진행하는 Ntos****.exe은 CPU 개수 및 앞서 얘기한 Boot.ini에서 메모리의 PAE 기능 활성화 유무에 따라 아래 4개의 프로세스중 하나가 실행된다.

 

프로세스와 메모리 기능별 사용하는 커널 프로세스 정보는 다음과 같다.

Ntoskrnl.exe: 1 CPU
Ntkrnlmp.exe: n CPU
Ntkrnlpa.exe: 1 CPU, PAE 활성화
Ntkrpamp.exe: n CPU, PAE 활성화

 

커널 생성을 위한 작업을 크게 0, 1 두 단계로 나눌수 있으며, 단계 0은 단계 1을 하기 위한 준비 단계라 할 수 있다.

단계 0에서는 인터럽트(Interrupts)를 비활성화 한 이후에 Ntldr(혹은 Winload.exe)로부터 건네 받은 정보를 통해, KiSystemStartup 커널 함수를 호출하며 시작하게 되는데, 대략적인 MBR부터 Ntoskrnl.exe까지 흐름을 그림으로 나타낸다면 다음과 같다.

MBR 부터 Ntoskrnl.exe 진행 흐름

위 그림을 요약하면, 각 CPU의 인터럽터 컨트롤러 초기화를 먼저 진행한다.
그리고 메모리 관리자를 초기화하고, File system cache와 Non-paged Pool, Paged Pool를 만든다.
그 후 개체 관리자(Object Manger)는 첫번째 프로세스를 할당하기 위해 Security token을 초기화 하고, 프로세스 관리자(Process Manager)는 스스로 Idle Process 와 System Process를 생성하게 된다.
이렇게 단계 0를 마치고, 단계 1에서는 인터럽트를 다시 활성화 한 후, Bootvid.dll(윈도우 로그와 진행바 출력)를 로드하여, 윈도우 부팅 상태 스크린을 출력하게 한다. 그리고 기존에 Ntldr(혹은 Winload.exe)에서 하이브한 System, Hardware 레지스트리를 복사하여 로드한 후에 필요한 드라이버들과 커널의 Executive 영역에 위치한 관리자들을 초기화 한다.
이 진행 순서를 표로 정리하면 아래와 같다.

 

진행 순서(함수명) 설명
단계 0
Interrupts 비활성화 프로세서 초기화를 위해 인터럽트를 비활성화
KiSystemStartup 커널 초기화 시작
-HalInitializeProcessor 프로세서 초기화 시작
-KiInitializeKernel 부트 CPU에서 시스텀 전역 커널 초기화를 진행하여(KiInitSystem), 모든 CPU가 공유하는 데이터 구조체를 초기화한다.
--KiInitSystem KeServiceDescriptorTable 초기화
--ExpInitializeExecutive 부트 CPU만이 ExpInitializeExecutive를 호출해 커널 초기화를 진행한다. 이는 단계0의 다른 모든 초기화 작업을 담당한다. (메모리 관리자, 개체 관리자 등)
그 외 CPU HalInitSystem만 호출
---HalInitSystem HAL 제어권 획득
CPU InterruptSystem interrupt controller 구성하고 CPU시간을 계산하기 위해 Internal clock timer interrupt 구성
----MmInitSystem 메모리 관리자 초기화
----ObInitSystem 개체 관리자 초기화
----SeInitSystem 보안 참조 모니터 초기화, Security token 관리
----PsInitSystem 프로세서 관리자 초기화, PsInitPhase0과 함께 Idle Process, System Process가 생성한다.
----PpInitSystem 플러그앤 플레이 관리자 초기화
Idle Loop 스레드를 실행할 수 있는 준비가 완료됨
-- KeRaiseIrql 단계1Phase1Initialization 스레드를 수행할 수 있도록 IRQLDISPATCH_LEVEL로 설정한다.
단계 1
Phase1Initialization Phase1InitializationDiscard를 진행하고, MmZeroPageThread를 통해 스레드의 메모리 해제에 이용되는 Zero-page 스레드를 초기화 한다(2 11장 참조).
-Phase1InitializationDiscard  
--HalInitSystem Interrupts 활성화
--InbvEnableBootDrive Bootvid.dll(Boot video driver)
윈도우 로그와 함께 진행바가 표시된다.
--PoInitSystem Power Manager 초기화
--KeSetSystemTime HalQueryRealTimeClock을 이용하여, 시스템 시간 초기화
--KeStartAllProcessors Non boot CPU들에 대해 초기화
--ObInitSystem 개체 매니저를 초기화 한다(네임스페이스 Root (\), \ObjectTypes, etc 초기화).
--ExInitSystem Executive object types(Semaphore, Mutex, Event, Timer ) 생성
--KeInitSystem 멀티프로세서시 이를 이용하여 커널을 초기화 한다. (Scheduler, SSDT(System service dispatch table) 초기화)
--KdInitSystem 커널 디버거 초기화
--SeInitSystem 보안 참조 모니터 초기화
-MmInitSystem 메모리 관리자 초기화
--NLS Mapping 국가 언어 지원(NLS) 테이블을 시스템 공간인 Ntdll.dll에 매핑한다.
--CcInitializeCacheManager 캐시 관리자 초기화
--CmInitSystem1  
Ntoskrnl.exe 실행 초기 로드한 Hardware 정보 복사하여 레지스트리 System에 하이브한다.
--FsRtlInitSystem 글로벌 파일 시스템 드라이버 데이터 구조를 초기화한다.
--PpInitSystem 플러그앤 플레이 관리자 초기화
--LpcInitSystem LPC 초기화(LPC포트와 타입, 개체)
--IoInitSystem I/O관리자 초기화
드라이버(Driver)와 디바이스(Device) 개체 생성
디이나믹 디바이스(Dynamic device) 초기화 및 할당, WMI 지원과 드라이버를 초기화한다.
--PoInitSystem 전원 관리 초기화
--PsInitSystem 프로세스 관리자 초기화, Smss.exe Ntdll.dll 찾는다.
--SeRmInitPhase1 LPC 서버 스레드를 생성하고, SeRmCommandPort LPC포트을 만들어, Lsass.exe와 통신한다.
--RtlCreateUserProcess Smss.exe, 세션 관리자 생성하고 유저 모드 생성을 진행하게 된다.

현재 시스템에 사용되는 커널을 Windbg!lmi nt 혹은 lm vm nt 명령으로 확인할 수 있다.

사용 중인 커널 확인

System과 Idle

시스템 프로세스(System process)는 커널에서만 실행되는 시스템 스레드(System thread)들을 호스팅하는 프로세스로서, 앞서 Ntoskrnl.exe의 커널 생성 단계에서 생성하게 된다. 이는 디바이스 드라이버와 함께 시스템 공간에 로드되어 커널 모드에서 동작하는 스레드를 관리한다. 추가로 시스템 스레드는 커널 모드에서만 호출할 수 있는 PsCreateSystemThread 함수에 의해 생성됨을 알아두자.

로드된 디바이스 드라이버, 커널 모드 호출 함수

유휴 프로세스(Idle process)도 커널 생성 단계에서 생성되며, CPU당 하나의 유휴 스레드를 할당 받아, 유휴 CPU 사용률(남은 CPU 사용률)을 계산하는 역할을 수행한다.

일부 프로그램에서 다른 이름으로 표기되지만(Process explorer System Idle Process라 하고, Tlist에서는 System Process라 한다), 이는 표시만 다를 뿐 PID가 동일한, 같은 프로세스이다.

같은 프로세스이지만, 표시 이름은 다르다. 4개의 프로세서를 위해 개별 유휴 스레드가 실행된다.

유휴 프로세스의 서로 다른 이름 표시, CPU별로 유휴 스레드를 가진다

이들 프로세스는 CPU 현황과 관리를 돕는 프로세스로서, Windbg에서 !cpuinfo, !cpuid 명령으로 프로세서 정보를 확인할 수 있다.

kd> !cpuinfo
CP  F/M/S Manufacturer  MHz PRCB Signature    MSR 8B Signature Features
 0  6,30,5 GenuineIntel 2691 0000000000000000  0000000000000000 00013fff
                      Cached Update Signature 0000000000000000
                     Initial Update Signature 0000000000000000
kd> !cpuid
CP  F/M/S  Manufacturer     MHz
 0  6,30,5  GenuineIntel    2691

 

반응형