커널 패닉(Kernel Panic) 완전 정복

Kernel Panic

[커널 크래시란?]

1. 커널이란?

커널(Kernel)은 항상 메모리에 상주하는 OS의 핵심 부분으로, 하드웨어와 응용 프로그램 사이에서 인터페이스를 제공하며 컴퓨터 자원들을 관리하는 역할을 한다. 즉, 커널은 인터페이스로서 프로그램 수행에 필요한 여러 가지 서비스를 제공하고 여러 하드웨어 자원(CPU, Memory, Disk 등)을 관리하는 역할을 한다. 메모리에 상주하는 특징을 빼면 평범한 C 프로그램이다.

그림 1. 커널 구조 예시

그림 1. [커널 구조 예시]

커널의 가장 큰 목표는 컴퓨터의 하드웨어 자원(물리적 자원)과 추상화 자원을 관리하는 것이다. 추상화란, 물리적으로 하나뿐인 하드웨어를 여러 사용자들이 번갈아 사용할 수 있도록 마치 하드웨어가 여러 개인 것처럼 보이게 하는 기술이다. 즉 커널에 의해 유저들은 하나의 하드웨어를 독점적으로 사용하는 듯한 느낌을 받는다. 물리적 자원들과 이를 추상화한 자원들을 칭하는 용어는 대표적으로 아래와 같은 것들이 있다.

CPU(물리적 자원): Task or Process(추상화 자원): CPU는 실행 단위를 제공하며, 커널은 물리적 자원인 CPU를 추상적 자원인 Process 또는 Task로 관리한다
Memory: Page or Segment: 메모리는 커널에 의해 Page 또는 Segment 단위로 관리된다.
Disk - File: 물리적 자원인 디스크를 추상적 자원인 File로 제공한다
Network: Socket: 물리적 자원인 네트워크 자원은 Socket을 통해 프로그램 데이터 송수신이 가능하도록 추상화된다.

앞서 말한 커널 구성요소가 존재하는 공간을 커널 공간(Kernel Space)이라고 할 수 있다. 커널 공간 위에는 사용자로 여겨지는 유저 공간(User Space)가 있으며 여기에 Task, Process들이 존재한다. 그리고 이 유저 공간과 커널 공간 사이에는 보이지 않는 시스템 콜 인터페이스 (System Call Interface)가 존재한다. 유저 공간의 Task 또는 Process들이 커널이 관리하는 자원에 접근해야 할 때 → System Call Interface를 통해 → 커널 공간의 자원관리자에게 요청이 전달되는 방식이다. 이 과정이 이루어지면 커널은 사용자 요청에 맞는 하드웨어에게 명령을 전달하고 작업을 수행하게 된다.

그림 2. 커널과 유저 공간 구조도

그림 2. [커널과 유저 공간 구조도]


2. 커널 패닉 정의(커널 패닉이란?)

Windows 운영체제를 사용하는 사용자라면 한 번쯤은 ‘블루 스크린’을 들어본 적이 있을 것이다. 블루 스크린 오브 데스(Blue Screen of Death, BSOD)는 마이크로소프트 윈도우 운영체제에 나타나는 악명 높은 오류 메시지로 하드웨어 오류, 소프트웨어 문제, 드라이버 충돌 등 다양한 문제로 인해 발생한다.

그림 3. 블루 스크린 예시

그림 3. [블루 스크린 예시]

커널 크래시(Kernel Crash) 또는 커널 패닉(Kernel Panic)은 Linux 운영체제에서 발생하는 블루 스크린과 같은 오류이다. 블루 스크린과 달리 파란 화면이 아닌 검은 배경에 흰색 문구가 보인다.

그림 4. 커널 패닉 화면 예시

그림 4. [커널 패닉 화면 예시]


3.패닉 발생 원인

커널 패닉은 운영체제에서 발생할 수 있는 가장 심각한 오류 중 하나로, 갑작스러운 시스템 중단 또는 재부팅을 초래하는 경우가 많다.
커널 패닉은 다음과 같은 원인으로 인해 발생할 수 있다.

  • 운영체제의 부적절한 메모리 접근
  • 부정확하거나 제대로 장착되지 않은 RAM
  • 마이크로프로세스의 결함
  • 파일 시스템 또는 데이터 손상
  • 하드 디스크 손상
  • 프로그램 간의 충돌
  • 멀웨어(악성코드) 또는 버그가 있는 소프트웨어



4.Oops vs. Panic

웁스라고 불리는 것도 있다. 간단히 살펴보자!
웁스(oops)와 커널 패닉은 리눅스 커널에서 예외상황이 발생하였을 때 출력되는 메시지이다. 하지만 이 둘은 차이점이 있다.

구분 Oops Kernel Panic
정의 커널이 정상적인 동작 행위를 벗어나는 예외적인 상황이 발생했을 때 출력되는 메시지 커널에 회복 불가능한 치명적인 오류가 발생했을 경우, 시스템이 동작을 멈추며 출력하는 메시지
의미 문제가 생기긴 했지만, 커널이 시스템을 부분적으로 동작할 수 있는 상황 문제의 심각성이 커, 커널이 시스템을 더 이상 동작할 수 없는 상황
시스템 반응 문제가 발생한 스레드만 종료 시스템 전체가 정지 또는 자동 재부팅
발생하는 상황 잘못된 system call, 널 포인터 참조 등 oops 발생 이후 일관성이 깨짐, 메모리 오류 등
필요한 조치 로그를 분석하여 문제 해결 패닉 발생 이후 바로 재부팅되므로, kdump와 같은 툴로 덤프 수집이 필요




[커널 패닉 덤프 매커니즘]

1.커널 패닉 발생 흐름 – 패닉 유도 함수

C와 C++에는 assert() 함수가 존재한다.
assert() 함수는 디버깅 모드에서 오류가 생기면 치명적인 곳에 심어놓는 에러 검출용 코드이다.
오류가 발생하면 프로그램이 개발자에게 버그 발생 위치, 호출 스택 (call stack) 등 여러 정보를 알려주기 때문에,
개발자가 수많은 로그를 일일이 로그를 찾아보지 않아도 된다는 장점이 있다.

리눅스 커널에서는 assert() 함수 대신, BUG() 또는 panic() 이라는 함수가 커널 패닉을 의도적으로 유발하는 용도로 사용된다.
간단한 코드와 함께 이해해보자.

1
2
3
4
5
// arch/x86/mm/fault.c
if (unlikely(regs->cs == 0)) {
printk(KERN_EMERG "Double fault\n");
BUG();
}

먼저 BUG() 함수이다.
만약(if) 현재 실행 중인 코드 세그먼트(cs)가 0이라면, KERN_EMERG로 가장 높은 심각도라고 기록한다.
그리고 BUG() 함수를 호출하여 커널을 종료한다.
unlikely()는 if 분기문에서 컴파일러에게 해당 분기문의 결과가 거짓인 경우가 더 많을 것이라는 정보를 주는 함수이다.
해당 코드에서는 ‘발생 확률이 매우 적은 예외적 상황’이라는 정보를 준다고 생각하면 된다.
더블 폴트(Double fault) 는 프로세서가 이전 예외에 대한 예외 처리기를 호출하는 동안 두 번째 예외를 감지한 경우 발생한다.

1
2
// init/do_mounts.c → 부팅 시 루트 파일 시스템을 마운트 하는 과정
panic("VFS: Unable to mount root fs on %s\n", b);

다음은 panic() 함수이다.
리눅스는 부팅 과정에서 반드시 루트 파일 시스템(/)을 마운트해야 한다.
하지만 부팅 시 루트 파일 시스템을 찾을 수 없는 상황이 발생하면 정상적인 부팅 진행이 불가능해진다.
이런 경우 시스템은 panic() 함수를 호출하여 시스템을 중단시킨다.

VFS(Virtual File System) : 리눅스 커널의 파일 시스템 추상화 계층으로, 다양한 파일 시스템들을 동일한 인터페이스로 접근할 수 있게 해준다. 커널 부팅에 필요한 파일들에 접근하고 마운트하는데 중요한 역할을 한다.
root fs : 루트 파일 시스템
b : 커널 부팅 과정 중, 파라미터로부터 받아온 루트 디바이스 경로

두 함수를 살펴봤다면 이런 의문이 생길 수 있다.
“왜 개발자들은 함수를 이용해 의도적으로 커널 패닉을 유발할까?”
루트 파일 시스템이 마운트되지 않는 상황을 가정해보자.
루트 파일 시스템 마운트가 진행되지 않으면 시스템 부팅 과정에서 계속 오류가 발생할 것이다.
이때 커널 패닉을 유도하는 함수를 사용하지 않으면, 사용자는 루트 파일 시스템이 마운트되지 않은 상태인 것도 모르고 계속 시스템 에러를 잡는 수고를 할 것이다.
그렇기에 개발자들은 커널 크래시를 유발해 현재 문제 상황을 해결하라고 알려준다.

그림 5. 커널 패닉 메시지

그림 5. [커널 패닉 메시지]


2. Kernel Crash Dump & kexec

커널 크래시 덤프란, 커널의 실행이 중단될 때, 디스크에 복사되는 RAM의 내용 중 일부를 의미한다. 이는 커널이 패닉 상태에 진입했을 때 시스템의 메모리 상태를 파일로 기록함으로써 이후 디버깅을 가능하게 한다. 쉽게 말해 “커널 패닉 전의 상태를 저장한 스냅샷”이라고도 볼 수 있다.
커널 크래시 덤프는, 리눅스 운영체제에서 oops/kernel panic 과 같은 치명적인 오류를 분석할 수 있도록 해주는 중요한 매커니즘이다.

kexec는 현재 작동 중인 커널에 새로운 커널이 부팅되게 하는 리눅스 커널의 기능이다. 기존의 부트로더 단계를 생략하고, 새로운 커널을 메인 메모리에 로드하여 즉시 실행하기 때문에 전체 시스템 재부팅 과정을 거치는데 비해 재시작 시간이 훨씬 짧고 다운타임을 최소화할 수 있다.
kexec를 실행하기 위해서는 second kernel이 로드될 메모리가 설정되어 있어야 한다.


3.kdump

kdump는 kexec를 바탕으로 한 커널 크래시 덤프 매커니즘으로, 커널 크래시가 발생했을 때 크래시 덤프를 캡쳐하는데 사용하는 툴이다. 커널 크래시가 발생했을 때 시스템 메모리 상태를 vmcore 파일 형태로 저장하는 작업을 수행한다. 간단히 말하자면, 어떠한 에러가 발생했을 때 그 원인을 찾을 수 있는 실마리를 제공하는 것이 vmcore이라는 코어 파일이고, 이런 코어 파일을 생성하는 것이 kdump이다.
크래시가 발생하면 kexec가 실행되고, 예약된 메모리에서 kdump 커널을 로드한 후 RAM의 데이터가 로컬 디스크의 vmcore에 복사된 뒤 재부팅된다.


4.kdump와 kexec의 구동 원리

위에서 살펴본 것처럼 kexec는 현재 동작 중인 커널에서 새로운 커널(second kernel)을 부팅할 수 있도록 해주는 메커니즘이다.
second kernel은 캡처 커널(capture kernel)이라고도 불린다.
kexec는 시스템 부팅 시 second kernel을 현재 동작 중인 커널에 정의하여 메모리의 특정 영역에 예약한다.
이 과정이 아래 그림의 kexec -l 에서 수행된다.
이 과정에서 second kernel이 들어갈 메모리 공간이 확보된다고 생각하면 된다.
이후 커널 패닉이 발생하면 kexec -e 명령어를 통해 예약된 메모리의 second kernel이 부팅된다.
즉, kexec -l 명령어로 메모리에 커널을 미리 로드해두면 언제든지 kexec -e 명령어로 해당 커널을 실행할 수 있는 것이다.
kdump를 설정해두면, 사용자가 별도로 second kernel 이미지를 준비하지 않더라도 시스템이 자동으로 /boot 디렉토리에 커널 이미지를 생성해두기 때문에, 보다 쉽게 크래시 덤프 환경을 구축할 수 있다.

그림 6. kexec와 kdump의 구조도 예시

그림 6. [kexec와 kdump의 구조도 예시]


5.kdump의 작동 원리

위에서 살펴봤듯, kdump는 시스템이 처음 부팅할 때 시스템의 예약된 곳에 second kernel을 메모리에 로드하고 실행할 수 있게 해주는 메커니즘이다.
일반적인 재부팅 과정인 “BIOS → Boot Loader → Kernel” 로딩 순서가 아닌, kexec를 통해 이 과정을 생략하고 커널을 직접 메모리에 올려 실행함으로써 부팅 시간을 줄인다.
kexec -l로 second kernel을 메모리의 특정 영역에 로드하고 이후 커널 패닉이 발생하면 kernel -e 명령어를 통해 로드된 second kernel이 실행된다.
해당 과정을 자동화한 시스템이 바로 kdump이고, 이때 사용되는 명령어가 kexec -p이다.
kexec -e가 수동으로 second kernel을 실행하는 역할이었다면, kexec -p는 명령어를 통해 자동으로 second kernel을 로드하고, 커널 패닉 시 시스템에서 자동으로 실행되도록 구성된다는 차이점이 있다.

그림 7. kdump 동작 구조도 예시

그림 7. [kdump 동작 구조도 예시]

참고 문헌

  • http://www.iorchard.net/2016/11/01/using_crashdump_for_troubleshooting_kernel_crash.html
  • https://aboutevery.tistory.com/220
  • https://blog.naver.com/gold-mouse/223152352861
  • https://access.redhat.com/solutions/6038
  • https://blog.naver.com/crushhh/221557909652
  • https://fdcservers.net/ko/blog/things-to-know-about-kernel-panic-error
  • https://haward.tistory.com/5