Exceptions
Exception은 프로세서(CPU)의 상태가 변경되는 이벤트에 대한 응답으로 OS 커널로 제어를 넘기는 것이다.
Examples of Events
- Divde by 0
- arithmetic overflow
- page fault
- I/O request completes
- typing Ctrl-C
이벤트는 현재 명령어를 실행하는 것과 직접적인 관계가 있을 수 있다.
그 예로 page fault, arthmetic overflow, divde by zero가 있다.
반면에, 이벤트가 발생한 것이 현재 명령어의 실행과 관련 없는 것이 있을 수 있다.
그 예로 timer interrupt, I/O request가 있다.
CPU가 이벤트를 감지하면, 특정 이벤트를 처리하기 위해 만들어진 OS의 서브루틴인 exception hadnler를 jump table인 exception table을 통해서 간접적으로 procedure call(the exception)을 발생시킨다.
명령어 실행 중에 이벤트가 발생하면 Exception이 발생한 것으로 CPU 제어권이 user code에서 Kernel code로 넘어간다.
제어권이 kernel로 이동할 때 user program이 실행하고 있던 명령어 주소는 kernel의 스택에 push 된다.
kernel에서 Exception handler가 예외를 처리한다.
그 다음 예외가 발생한 원인에 따라 handler가 3가지 방법으로 다음을 실행한다.
- Return to I_current : 예외가 발생했던 명령어를 return 한다.
- Return to I_next : 예외가 발생했던 명령어의 다음 명령어를 return 한다.
- Abort : interrupt 된 프로그램을 종료한다.
Exception Table
하드웨어와 소프트웨어 사이의 긴밀한 협력을 hadnling 해야 하기 때문에 Exception을 이해하기 어려울 수 있다.
어느 구성 요소가 어떤 일을 해야 할지 혼란스럽기 쉽다.
하드웨어와 소프트웨어가 하는 일을 자세히 분리해서 볼 필요가 있다.
시스템에서 발생 가능한 각각의 exception은 고유한 양의 정수인 exception number를 가지고 있다.
특정 exception number는 CPU디자이너에 의해 할당되어 있다.
example
- divide by zero
- page faults
- memory access violations
- break-points
- arithmetic overflow
그 외의 수들은 OS의 Kernel에 의해 할당된다.
example
- system calls
- signals from external I/O devices
Exception table은 Exception k에 대한 exception handler 코드가 있는 주소를 포함하는 entry k를 가진 jump table이다.
System boot time에 OS는 entry k가 exception k에 대한 핸들러의 주소를 가질 수 있도록 exception table을 초기화하고 할당한다.
Run time에 프로세서는 이벤트가 발생했다는 것을 감지하고 exception에 상응하는 number k를 결정한다.
다음으로 프로세서는 exception table의 entry k와 대응되는 handler에 indirect procedure를 호출함으로써 예외를 trigger 한다.
Exception number는 exception table에 대한 인덱스이다. 이 exception table의 시작 주소는 exception table base register라고 불리는 특별한 CPU 레지스터에 포함된다.
Classes of Exceptions
Exception은 크게 Asynchronous, Synchronous 두 가지 방식으로 나뉘고
세부적으로 네 가지 interrupt, traps, faults, aborts로 나뉜다.
Asynchronous exception은 CPU외부의 I/O 디바이스 이벤트에 대한 결과로 발생한다.
Synchronous exception은 실행 중인 명령어의 직접적인 결과(영향)로 발생한다.
Asynchronous Exceptions (Interrupts)
Asynchronous Exception은 CPU 외부의 이벤트에 의해 발생한다.
Interrupts
- 현재 명령어가 실행 중 interrupt pin이 high로 바뀐다.
- 현재 명령어의 실행이 끝나고 제어권이 user code에서 kernel code의 handler로 넘어간다.
- CPU가 system bus로부터 exception number를 읽고 interrupt handler를 호출한다.
- handler는 exception을 처리하고 다음 명령어로 제어권을 넘긴다.
중요한 것은 interrupt가 발생해도 프로그램은 계속 실행한다.
Examples
- Time interrupt
- 외부의 타이머 칩이 매우 작은 ms마다 interrupt를 동작시킨다.
- kernel이 user 프로그램의 CPU 제어권을 받기 위해 사용된다.
- I/O interrupt from external device
- 키보드로 Ctrl-C을 눌렀을 때
- 네트워크로부터 패킷이 도착.
- 디스크로부터 데이터가 도착.
Synchronous Exceptions
Synchronous Exception은 실행 중인 명령어의 결과로 인한 이벤트에 의해 발생한다.
Traps
- Traps은 실행 중인 명령어의 결과로 인해 일어나는 고의적인 exception이다.
- exception을 처리하고 제어권을 다음 명령어로 return 한다.
trap을 사용하는데 가장 중요한 것은 user 프로그램과 kernel사이의 인터페이스인 system call을 제공하는 것이다.
user 프로그램은 다음의 함수들을 사용하기 위해 kernel에게 도움을 요청해야 한다.
- read
- fork
- execve
- exit
- kernel 서비스에 대한 제한된 접근을 허용하기 위해 CPU는 user 프로그램이 서비스 n을 요구할 때
실행할 수 있는 특별한 syscall n 명령어를 제공한다. - syscall 명령어를 실행하면 n이라는 argument를 decoding한다.
- 다음으로 적절한 kernel routine을 호출하는 exception handler에 trap이 발생한다.
프로그래머의 관점에서 system call은 일반적인 함수와 같다. 그러나 system call의 구현은 매우 다르다.
일반적인 함수는 실행할 수 있는 명령어의 종류를 제한하는 user mode에서 실행된다.
그리고 일반적인 함수는 호출하는 함수와 같은 stack에 접근한다.
system call은 권한 있는 명령어를 실행하고 kernel의 stack에 접근 가능하도록 허용하는 kernel mode에서 실행된다.
Faults
Fault는 handler가 처리할 수 있는 오류 상태에서 발생한다.
- fault가 발생할 때 CPU는 제어권을 fault 핸들러로 넘긴다.
- handler가 오류를 처리할 수 있으면 handler는 오류가 발생한 명령어로 제어권을 넘기고 다시 실행한다.
- 처리할 수 없으면 handler가 fault를 발생시킨 프로그램을 종료시키는 abort를 return 한다.
fault의 전형적인 예는 page fault exception이다. page fault exception은 대응하는 page가 메모리에 존재하지 않기 때문에 디스크에서 검색해야 하는 가상 주소를 명령어가 참조할 때 발생한다.
가상 메모리의 연속 블록은 일반적으로 4KB이다. page fault handler는 디스크에서 적절한 page를 로드한 후 오류를 일으킨 명령어로 제어권을 return 한다. 명령어가 다시 실행되면 해당 page가 메모리에 상주하여 명령을 오류 없이 실행할 수 있다.
Abort
Abort는 회복 불가능한 치명적인 오류(일반적으로 DRAM 또는 SRAM 비트가 파손되었을 때 발생하는 패리티 오류 등)에서 발생한다. handler는 프로그램을 종료하는 abort routine으로 제어권을 return 한다.