Kernel Mode vs. User Mode

오늘은 아주 원론적인 얘기이지만 운영체제를 이해하는 데 있어서 가장 기본이 되는 Kernel Mode와 User Mode에 대해서 알아볼까 합니다. 특히 Windows Internals 책에 이 부분에 대한 내용이 잘 정리되어 있어서 많은 부분을 참고해서 본 글을 쓰고자 합니다. 자세한 내용은 Windows Internals의 4th Edition의 p.16-21 부분을 참고하시기 바랍니다.

Intel CPU에서는 다음과 같이 'ring'이라는 용어를 이용해서 아래 그림에서 가장 내부에 있는 Ring 0로부터 가장 바깥 부분에 해당하는 Ring 3까지 크게 4가지의 특권 레벨(privilege level)로 구분하고 있습니다. 원의 중심부에 있을 수록 시스템의 주요 자원에 접근할 수 있는 권한이 많은 것이고, 바깥 부분에 있을 수록 제한적인 접근만 허용됩니다. 이렇게 4개의 레벨로 구분함으로써 각 계층에서 접근 가능한 시스템 자원의 권한을 구분함으로써 외부의 Ring에서 부적절한 코드에 의해서 시스템의 주요 자원이 손상되는 것을 막을 수 있으니 시스템의 안정성은 높아질 수 있고, 각 계층별로 할 수 있는 일과 할 수 없는 일을 구분함으로써 각 layer에 맞는 적절한 역할을 수행할 수 있도록 구조화 한 것입니다.

 

 

실제 Windows 운영체제에서는 이와 같은 4개의 특권 레벨 중에서 Ring 0와 Ring 3 2개만 사용하며, Ring 0를 'Kernel mode' , Ring 3를 'User Mode' 라고 정의하고 있습니다. 기존의 Windows 운영체제에서 지원했던 Alpha나 MIPS chip에서는 2개의 특권 레벨만 지원했기 때문에 WIndows도 2계층으로 설계를 하였다고 합니다.

Windows 운영체제에서 Kenel Mode와 User Mode의 가장 큰 차이점은 접근 가능한 가상메모리 영역에 있습니다. User Mode는 일반적으로 작성되는 User Mode Application에서 사용되는 User Address Space만 접근이 가능하며 Kernel Address Space는 접근할 수 없습니다. 반면에 Kenel Mode에서 실행되는 코드는 모든 Address Space에 접근이 가능합니다. User Address Space는 각 프로세스마다 독립적인 공간을 보장 받기 때문에 해당 프로세스의 영역에 해당하는 데이터만 접근이 가능한 반면에, Kernel Address Space는 Kernel Level에서 실행되는 디바이스 드라이버나 시스템 쓰레드 등이 공유해서 함께 사용되는 영역으로 프로세스의 구분이 없습니다.

Kernel Mode에서는 모든 Address 영역에 접근이 가능하므로 코드 작성이 잘못되거나 악의적인 목적으로 특정 부분을 공격할 경우 시스템의 안정성에 크게 영향을 받게 되므로, Kernel에서 실행되는 모듈을 설치할 때는 주의할 필요가 있습니다. 악성 Kernel Module이 시스템에 설치되어 문제를 일으키는 것을 막기 위해 커널 모듈이 시스템이 설치될 때 해당 모듈을 어느 회사에서 만든 것인지 인증하기 위해 Driver Code Signing이라는 기술을 사용하기도 합니다. 실제로 Windows 2003 서버 이후 64bit 운영체제에서는 이렇게 디지털 서명되지 않은 커널 모듈은 운영체제에 의해서 로드 되지 않습니다. 어느 회사에서 만든 것인지 신분이 확실한 모듈만 선별해서 로드함으로써 시스템 안정성을 높이고자 하는 것입니다.

그렇다면 User Mode에서 실행 중인 코드에서 파일에 접근하거나 화면에 그래픽 작업을 해야하는 등의 시스템 자원을 이용해야 하는 경우에는 어떻게 해야 될까요? 외부의 Ring에서는 하위에 있는 Ring을 거쳐서만 Ring 내부로 접근이 가능합니다. 즉, Windows 에서는 User Mode에서는 Kernel Mode를 거쳐야지만 시스템 자원에 접근할 수 있다는 의미가 됩니다. 이를 위해서는 User Mode에서 실행되던 thread가 Kernel Mode에 접근할 수 있도록 특권 레벨을 부여 받은 뒤에 시스템 자원을 사용하고, 그 뒤에 다시 User Mode로 돌아갈 때에는 반대의 과정으로 낮은 특권 레벨로 변경되는 과정이 필요합니다. User Mode에서 Kernel Mode로 변경하는 과정을 System Service Call이라고 부릅니다. 말 그대로 User Mode에서 시스템에서 제공하는 서비스를 호출해서 사용하는 것을 의미합니다.

이러한 System Service Call은 원래 User Mode에서 Kernel Mode로 진입하기 전에 인터럽트 0x2e를 발생시킴으로써 Kenel에서 handler가 이를 감지하고 필요한 Service Call을 해주는 형태로 설계되어 있습니다. 매번 interrupt handler가 이를 처리하는 과정에서 발생하는 overhead를 줄이기 위해서 Pentium II 이후 버전에서는 System Service Call 만을 위한 CPU instruction이 새로 추가되어 사용되고 있습니다. 이를 위해 Intel에서는 SYSENTER를, AMD에서는 SYSCALL 명령어가 별도로 제공되고 있습니다.

이러한 System Service Call 작업에서는 thread context switching이 발생하지 않습니다. 즉, User Mode에서 실행이던 해당 thread가 System Service Call을 함으로써 Kernel Mode에서 실행되는 것을 의미합니다. Thread와 관련된 커널 구조체 중에 KTHREAD 구조체에는 실제로 특정 thread가 User Mode에서 실행된 시간과 Kernel Mode에서 실행된 시간이 각각 따로 관리되어 저장되고 있습니다. 이는 실행되는 Thread의 성격에 따라서 어떤 것은 Kernel Mode에서 더 많이 실행되고, 어떤 것은 User Mode에서 더 많이 실행됩니다. 또는 운영체제에서 생성한 System Thread라는 특이한 thread 도 있는데, 이는 운영체제가 부팅 되는 과정에서 System Process 내에 생성되어 오직 Kernel Mode에서만 실행되는 여러 시스템 관련 thread를 일컫는 용어 입니다.

다음에 기회가 되면 System Service Call의 과정에 대해서 보다 자세히 정리해보도록 하겠습니다.