CPU가 프로그램을 실행하는 도중, 예기치 않은 예외 상황이 발생하거나 긴급히 처리를 요하는 요청이 들어올 때 현재 작업을 잠시 멈추고(Suspend) 현재 상태(PC, 레지스터)를 저장한 뒤, 해당 요청을 우선 처리하고 복귀하는 메커니즘
인터럽트 발생 시 cpu는 interrupt vector table에서 해당 상황에 대응하는 적절한 함수를 골라 실행한다. 이를 interrupt handler 또는 ISR, Interrupt Service Routine 이라고도 한다.
https://zipcpu.com/zipcpu/2019/04/02/icontrol.html
예를 들어 타이머 인터럽트가 발생했다고 하자.
IVT(Interrupt Vector Table)와 ISR은 모두 RAM에 저장되어 있다.
RAM은 volatile이라서 부팅하면 사라질텐데? 라는 의문이 드는데, 사실 맞다. 전원을 끄면 RAM에 있던 ISR은 사라진다. 다만 매 부팅 시 SSD에 저장되어있는 드라이버 코드를 불러오면서 그 일부인 ISR 코드도 함께 올라온다. ISR코드는 운영체제/드라이버 파일에 포함되어 SSD에 보관되고 있다. 컴퓨터가 부팅되면 RAM에 올라오는 것이다. 운영체제는 RAM에 다시 올라온 핸들러의 주소를 IVT에 등록하는 과정을 거친다.
https://www.geeksforgeeks.org/operating-systems/interrupts/
장치의 작업 완료, 타이머 등 하드웨어가 사건을 만들면 하드웨어 컨트롤러가 발생시키는 인터럽트이다.
하드웨어에서 발생한 인터럽트는 IRQ (Interrupt Request)로 CPU에게 전달된다.
CPU는 인터럽트 요청을 받으면 원래 진행하고 있던 프로세스를 잠시 멈추고, 인터럽트 핸들링을 한 뒤 다시 원래 작업으로 돌아온다. 하지만 인터럽트 요청을 무조건 당장 처리해야하는 것은 아니다. 이를 Interrupt Masking이라고 한다. CPU가 중요한 작업을 처리하는 동안 다른 인터럽트 요청을 일시적으로 무시하거나 연기하도록 차단할 수 있는 기능이다. 이 마스킹이 가능한지 불가능한지에 따라 하드웨어 인터럽트가 분류될 수 있다.
초기 인텔 CPU(8086)에는 마스킹 가능한 일반 인터럽트를 받는 INTR 핀과, 마스킹 불가능한 긴급 인터럽트를 받는 NMI핀 이렇게 2개가 있었다. 이 핀에 복수의 장치를 연결하기 위해 PIC라는 칩을 두고, 장치들의 IRQ 선을 PIC에 연결된 구조가 일반적이었다. PIC는 최대 8개 장치를 연결할 수 있었고, PIC 두 개를 직렬(캐스케이드)연결한다고 하더라도 최대 15개 밖에 연결할 수 없었다. 또한 CPU 코어가 여러 개가 되자 특정 인터럽트를 몇 번 코어에 보내야할지를 정할 수 없었다는 한계가 존재했다.
현대 CPU는 APIC 구조를 사용하며, 장치는 전용 선(I/O APIC 경유) 또는 MSI(메모리 쓰기) 방식으로 인터럽트를 보낸다.
APIC(Advanced PIC)
MSI(Message Signaled Interrupts)
전용 선을 사용하지 않는다. 장치가 인터럽트를 발생시키면 미리 정해진 특정 메모리 주소에 특정 값을 쓰는 것으로 신호를 보낸다. 그럼 Local APIC가 이를 감지하고 CPU에게 전달하는 방식이다.
프로그램이 특정 명령어를 실행하여 발생되는 인터럽트이다.
예를 들어 프로그램에 특정 파일의 값을 읽어오는 명령어가 있다고 하자. 프로그램은 파일 시스템을 통해 파일에 접근하고, 값을 읽어오는 작업을 수행해야 하는데 이를 위해선 운영체제의 권한이 필요하다. 보통 프로그램은 read() 와 같은 라이브러리 함수를 호출하고, 그 함수 내부에서 운영체제가 제공하는 서비스를 접근하게 도와주는 시스템 콜을 호출한다. 그 시스템 콜이 CPU에 인터럽트를 발생시키는데 이것이 소프트웨어 인터럽트의 대표적인 예이다.
이외에도 CPU가 명령어 실행 중 0으로 나누기, 페이지 폴트와 같은 특정 상황을 감지하면 Exception을 발생시키는데, 이는 Software Interrupts와는 다른 개념이다.
x86에서 Exceptions의 종류를 다음과 같이 분류한다.
| 종류 | 핵심 의미 | 해결 방법 | 예시 |
|---|---|---|---|
| Fault | 실행 중인 명령어에서 문제가 발생했을 때 발생하며, 수정 후 재시작이 가능한 예외 | 오류를 처리한 뒤, 문제가 발생했던 그 명령어부터 다시 실행 | Page fault |
| Trap | 의도되었거나 혹은 조건에 의해 발생하며, 예외를 처리한 후 다음 명령어로 계속 진행하는 예외 | 오류나 특정 이벤트를 처리한 뒤, 문제가 발생한 명령어의 다음 명령어부터 실행 | 디버깅의 단일 단계 실행, system call(system call은 엄밀히는 소프트웨어 인터럽트지만 Trap처럼 동작) |
| Abort | 복구할 수 없는 심각한 하드웨어 오류나 치명적인 시스템 문제가 발생했을 때 나타나는 예외 | 프로그램을 정상적으로 복구하거나 재시작할 수 없으며, 보통 해당 프로세스나 시스템을 강제 종료 | 하드웨어 고장, 패리티 비트 오류, 유효하지 않은 시스템 테이블 값 |