인터럽트
- 인터럽트(interrupt)
- 인터럽트(interrupt, 방해하다:중단시키다)
- CPU가 수행 중인 작업은 방해를 받아 잠시 중단될 수 있는데, 이렇게 CPU의 작업을 방해하는 신호를 인터럽트라고 한다.
- 더 급한일이 있어 일시적으로 작동을 중단하는 것.
- CPU가 꼭 주목해야 할 때, CPU가 얼른 처리해야 할 다른 작업이 생겼을 때 발생
인터럽트의 종류를 구분하는 통일된 기준은 없다.
게시글의 내용은 인텔의 공식 문서를 참조한 기준이다.
동기 인터럽트(synchronous interrupts)
- CPU에 의해 발생하는 인터럽트
- 예외(Exception)
- CPU가 명령어들을 수행하다가 예상치 못한 상황에 마주쳤을 때 발생하는 인터럽트.
- 가령 CPU가 실행하는 프로그래밍 상의 오류와 같은 예외적인 상황.
예외의 종류
- 예외
- CPU는 하던 일을 중단하고 해당 예외를 처리한다.
- 예외를 처리하고 나면 CPU는 다시 본래 하던 작업으로 돌아와 실행을 재개한다.
- 폴트: CPU가 본래 하던 작업으로 되돌아왔을 때 예외가 발생한 명령어부터 실행
- 트랩: CPU가 본래 하던 작업으로 되돌아왔을 때 예외가 발생한 명령어의 다음 명령어부터 실행
- 폴트(falut)
- 예외 처리 직후, 예외가 발생한 명령어부터 실행을 재개
- ex) 명령어 실행을 위해 꼭 필요한 데이터가 메모리가 아니라 보조기억장치에 있을 때, 프로그램 실행을 위해 명령어가 메모리에 저장되어 있어야 하므로, cpu는 폴트를 발생시키고 보조기억장치로부터 필요한 데이터를 가져와 저장한다.
- 폴트를 실행했으므로, CPU는 보조기억장치의 필요한 데이터를 메모리에 가져오고, 예외가 발생한 명령어부터 실행한다.
- 트랩(trap)
- 예외 처리 직후, 예외가 발생한 명령어의 다음 명령어부터 실행을 재개한다.
- ex) 디버깅시 프로그램을 중단시키고, 디버깅이 끝나면 프로그램은 다음 명령어부터 실행을 이어나간다.
- 중단(abort)
- CPU가 실행 중인 프로그램을 강제로 중단시킬 수 밖에 없는 심각한 오류를 발견했을 때 발생하는 예외
- 소프트웨어 인터럽트(software interrupt)

비동기 인터럽트 (asynchronous interrupts)
- 입출력장치에 의해 발생하는 인터럽트
- CPU가 프린터와 같은 입출력장치에 입출력 작업을 부탁하면 작업을 끝낸 입출력장치가 CPU에 완료 알림(인터럽트)을 보낸다.
- 키보드, 마우스와 같은 입출력장치가 어떠한 입력을 받아들였을 때 이를 처리하기 위해 CPU에 입력 알림(인터럽트)을 보낸다.
- 알림과 같은 인터럽트
- 입출력 작업 도중에도 효율적으로 명령어를 처리하기 위해 사용된다.
- 입출력장치는 cpu에 비해 느리므로,
- 인터럽트가 없다면 CPU는 프린트 완료 여부를 확인하기 위해 주기적으로 확인해야 한다.
- 인터럽트가 있다면 입출력 작업동안 CPU는 다른 일을 할 수 있다.
일반적으로 비동기 인터럽트를 인터럽트라 칭하기도 하지만, 이 책에서는 용어의 혼동을 방지하기 위해 하드웨어 인터럽트라는 용어를 사용한다.
하드웨어 인터럽트의 처리순서
(하드웨어 인터럽트라고 쓰긴 했지만) 인터럽트의 종류를 막론하고 인터럽트 처리 순서는 대동소이하다.
- 입출력장치는 CPU에 인터럽트 요청 신호를 보낸다.
- CPU는 실행 사이클이 끝나고 명령어를 인출하기 전 항상 인터럽트 여부를 확인한다.
- CPU는 인터럽트 요청을 확인하고 인터럽트 플래그를 통해 현재 인터럽트를 받아들일 수 있는지 여부를 확인한다.
- 인터럽트를 받아들일 수 있다면 CPU는 지금까지의 작업을 백업한다.
- CPU는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행한다.
- 인터럽트 서비스 루틴 실행이 끝나면 4에서 백업해 둔 작업을 복구하여 실행을 재개한다.
먼저, 낯선 용어들을 요약하자면 아래와 같다.
- 인터럽트 요청 신호: cpu의 작업을 방해하는 인터럽트에 대한 요청
- 인터럽트 플래그: 인터럽트 요청 신호를 받아들일지 무시할지를 결정하는 비트
- 인터럽트 벡터: 인터럽트 서비스 루틴의 시작 주소를 포함하는 인터럽트 서비스 루틴의 식별정보
- 인터럽트 서비스 루틴:인터럽트를 처리하는 프로그램
인터럽트 요청 신호

인터럽트는 CPU의 정상적인 실행 흐름을 중단하는 것이기에, 다른 누군가가 인터럽트 전에 "지금 끼어들어도 되나요?"하고 CPU에 물어야 하는데, 이를 인터럽트 요청신호라 한다.
인터럽트 플래그(interrupt flag)
- CPU가 인터럽트 요청을 수용하기 위해서는 플래그 레지스터의 인터럽트 플래그가 활성화되어 있어야 한다.
- 인터럽트 플래그가 '불가능': CPU가 중요한 작업을 처리해야 하거나 어떤 방해도 받지 않아야 하는 경우
- 인터럽트 플래그가 '가능': CPU는 인터럽트 요청 신호를 받아들이고 인터럽트를 실행한다.

- 모든 인터럽트를 인터럽트 플래그로 막을 수 있는것은 아니다.
- 이를 막을 수 없는 인터럽트(NMI: Non maskable interrupt)라고 부른다.
- 가장 우선순위가 높은, 가장 먼저 처리해야 하는 인터럽트가 있는데, 정전이나 하드웨어 고장으로 인한 인터럽트가 이에 해당한다.

인터럽트 서비스 루틴(ISR: interrupt Service Routine)
- CPU가 인터럽트 요청을 받아들이기로 했을 때 실행하는 프로그램.
- '키보드가 인터럽트 요청을 보냈을 때는 어떻게 작동한다', '마우스가 인터럽트 요청을 보냈을 때는 어떻게 작동한다'와 같이 어떤 인터럽트가 발생했을 때 해당 인터럽트를 어떻게 처리하고 작동해야 할지에 대한 정보로 이루어진 프로그램
- 인터럽트 서비스 루틴도 프로그램이기에 메모리에 저장된다.
- 정상적으로 작업 수행
- 인터럽트 발생
- 인터럽트 서비스 루틴으로 점프
- 인터럽트 서비스 루틴 실행
- 기존 작업으로 점프
- 기존 작업 수행 재개
인터럽트 벡터(interrupt vector)

인터럽트를 처리하는 방법은 입출력장치마다 다르므로 각기 다른 인터럽트 서비스 루틴을 가지고 있다. 즉, 메모리에는 위 그림처럼 여러 개의 인터럽트 서비스 루틴이 저장되어 있으며, 이들 하나하나가 '인터럽트가 발생하면 어떻게 행동해야 할지를 알려주는 프로그램'이다.
CPU는 이러한 인터럽트 서비스 루틴의 구분을 위해 인터럽트 벡터(interrupt vector)를 사용한다.
즉,
'CPU가 인터럽트를 처리한다'
== '인터럽트 서비스 루틴을 실행하고, 본래 수행하던 작업으로 다시 되돌아온다.'
(+ 그리고 CPU가 인터럽트의 시작 주소는 인터럽트 벡터를 통해 알 수 있다)
이때, 인터럽트 발생 전까지 레지스터에 저장되어 있던 값들은,
인터럽트 서비스 루틴이 끝나면 되돌아와 다시 실행되어야 하므로,
프로그램 카운터 값 등 현재 프로그램을 재개하기 위한 모든 내용을 스택에 저장해둔다.
그러고 나서 인터럽트 서비스 루틴을 실행하고,
인터럽트 처리 후 스택에 저장해 둔 값을 다시 불러와 작업을 재개한다.


추가
인터럽트 사이클까지 추가한 명령어 사이클은 아래와 같다.

Reference