예외 디스패칭
- Windows Server 2008
아무 때나 발생 할 수 있는 인터럽트와는 대조적으로 예외는 실행 중인 프로그램의 직접적인 실행 결과(runtime error)로 발생하는 상황이다. 윈도우는 예외가 발생할 때 애플리케이션이 제어를 받을 수 있는 구조적 예외 처리(structured exception handling) 기능을 사용한다.
애플리케이션은 제어를 받으면 예외 상황을 수정하여 예외가 발생했던 위치로 되돌아 갈 수 있고 스택을 언와인드(unwind) 시키거나 예외를 처리 할 예외 핸들러를 찾을 수 있도록 제어를 시스템으로 되돌아가 가게 할 수 있다.
x86과 x64 프로세서의 경우 모든 예외는 특정 예외에 대한 트랩 핸들러를 가리키는 IDT 내의 엔트리에 직접적으로 대응하는 이미 정의된 인터럽트 번호를 가진다.
다음 표는 x86에 정의된 예외에 할당된 인터럽트 번호이다.
인터럽트 번호 | 예외 |
0 | Divide Error |
1 | Debug (Single Step) |
2 | Non-Maskable Interrupt (NMI) |
3 | Breakpoint |
4 | Overflow |
5 | Bounds Check |
6 | Invalid Opcode |
7 | NPX Not Available |
8 | Double Fault |
9 | NPX Segment Overrun |
10 | Invalid Task State Segment (TSS) |
11 | Segment Not Present |
12 | Stack Fault |
13 | General Protection |
14 | Page Fault |
15 | Intel Reserved |
16 | Floating Point |
17 | Alignment Check |
18 | Machine Check |
19 | SIMD Floating Point |
트랩 핸들러가 해결할 수 있을 만큼 단순한 예외를 제외한 그 밖의 모든 예외는 예외 디스패처로 불리는 커널 모듈에 의해 서비스 된다. 예외 디스패처의 역할은 예외를 처리 할 수 있는 예외 핸들러를 찾는 것이다.
커널은 이들 예외를 유저 프로그램에게는 투명하게 잡아 처리한다. 예를 들어 디버깅 중인 실행 프로그램이 브레이크포인트를 만나면 예외를 생성하고 커널은 디버거를 호출해 이 예외를 처리한다. 커널은 호출자에게 실패 상태 코드를 반환해 예외를 처리하는 경우도 있다.
일부 예외는 전혀 처리되지 않은 채로 유저모드로 보내진다. 예를 들어 특정 유형의 메모리 접근 위반이나 산술연산 오버플로우는 운영체제가 처리하지 않는 예외를 생성한다.
예외가 발생 할 때 커널은 현재 스택 프레임과 연관된 예외 핸들러를 찾는다. 예외 핸들러가 존재하지 않는다면 커널은 프레임 기반의 예외 핸들러를 찾을 때까지 바로 이전 스택 프레임과 연관된 예외 핸들러를 계속 찾는다. 최종적으로 예외 핸들러를 찾지 못한다면 커널은 자신의 디폴트 예외 핸들러를 호출 한다.
64비트 애플리케이션의 경우 구조적 예외 처리는 프레임 기반의 핸들러를 사용하지 않고 대신 컴파일 시점에 이미지에서 만들어지는 각 함수에 대한 핸들러 테이블을 사용한다. 커널은 각 함수와 연관된 핸들러를 찾는데 이때 32비트 코드의 경우에 설명한 바와 동일한 알고리짐을 일반적으로 따른다.
예외가 발생 할 때 소프트웨어에 의해 명시적으로 발생하거나 하드웨어에 묵시적으로 발생하든지 관계없이 커널에서는 일련의 이벤트가 발생하기 시작한다. CPU 하드웨어는 제어를 커널 트랩 핸들러로 넘긴다. 커널은 인터럽트가 발생할 때처럼 트랩 프레임을 생성한다. 시스템은 트랩 프레임을 이용해 예외가 해결된 이후에 자신이 실행을 중단했던 곳에서부터 실행을 재개할 수 있다. 트랩 핸들러 역시 예외의 원인과 기타 관련 정보를 포함하는 예외 레코드를 생성한다.
커널모드에서 예외가 발생 했다면 예외 디스패처는 예외를 처리할 프레임 기반의 예외 핸들러를 찾기 위한 루틴을 호출 한다.
유저모드에서 예외가 발생 했다면 예외 디스패처는 좀더 정교한 작업을 수행 한다. 윈도우 서브시스템은 윈도우 프로세스에서 윈도우 예외를 통지 받는 디버거 포트와 예외 포트를 갖고 있다. 디폴트 예외 처리에 이들 포트를 사용한다. 예외 핸들러를 찾지 못하거나 아무도 예외를 처리하지 않는다면 예외 디스패처는 커널로 전환 후 디버거를 호출해 사용자가 추가적인 디버깅을 하게 한다. 이것을 [두 번째 기회 통지(second-chance notification)]이라 한다.
디버거가 실행되지 않고 유저모드 예외 핸들러도 찾지 못했다면 커널은 스레드 프로세스와 연관된 예외 포트로 메시지를 보낸다. 이 예외 포트는 예외를 일으킨 스레드를 제어하는 환경 서브시스템에 의해 등록된 것이다. 예외 포트는 사진의 포트를 리슨(Listen)하고 있는 환경 서브시스템에 예외를 환경 전용 신호나 예외로 변환할 기회를 준다. 이 신호는 윈도우 오류보고 목적으로 사용한다.
[참고자료]
Windows Internals
'Windows , IIS' 카테고리의 다른 글
윈도우 오류 보고 (0) | 2015.07.16 |
---|---|
처리되지 않은 예외 (0) | 2015.07.16 |
비동기 프로시저 호출 인터럽트 (0) | 2015.07.16 |
소프트웨어 인터럽트 (0) | 2015.07.16 |
소프트웨어 인터럽트 요청 레벨(IRQL) (0) | 2015.07.16 |