본문으로 건너뛰기

인터럽트(Interrupt)

CPU가 수행 중인 작업을 방해하는 신호를 인터럽트(interrupt)라고 합니다.

인터럽트의 종류

인터럽트의 종류에는 동기 인터럽트와 크게 동기 인터럽트와 비동기 인터럽트가 있습니다.

동기 인터럽트(Synchronous Interrupt)

동기 인터럽트는 CPU에 의해 발생하는 인터럽트입니다. CPU가 명령어들을 수행하다가 예상치 못한 상황에 마주쳤을 때, 가령 CPU가 실행하는 프로그래밍상의 오류와 같은 예외적인 상황에 마주쳤을 때 발생하는 인터럽트가 동기 인터럽트입니다. 이런 점에서 동기 인터럽트는 예외(exception)이라고 부릅니다.

비동기 인터럽트(Asynchronous Interrupt)

비동기 인터럽트는 주로 입출력장치에 의해 발생하는 인터럽트이다. CPU가 프린터와 같은 입출력장치에 입출력 작업을 부탁하면 작업을 끝낸 입출력 장치가 CPU에 완료 알림을 보낸다.

가령 CPU가 프린터에 출력을 명령했다고 가정해보자. 입출력장치는 CPU보다 현저히 속도가 느리기 때문에 CPU는 입출력 작업의 결과를 바로 받아볼 수 없다. 이 때 만약 하드웨어 인터럽트를 사용하지 않는다면 CPU는 프린터가 언제 프린트를 끝낼지 모르기 때문에 주기적으로 프린터의 완료 여부를 확인해야 한다. 이로 인해 CPU는 다른 생산적인 일을 할 수 없으니 CPU 사이클 낭비이다. 하지만 하드웨어 인터럽트를 이용하면 CPU는 주기적으로 프린트 완료 여부를 확인 할 필요가 없다. CPU는 프린터로부터 프린트 완료 인터럽트를 받을 때까지 다른 작업을 처리할 수 있다.

하드웨어 인터럽트 처리 순서

  1. 입출력 장치는 CPU에 인터럽트 요청 신호를 보낸다.
  2. CPU는 실행 사이클이 끝나고 명령어를 인출하기 전 항상 인터럽트 여부를 확인한다.
  3. CPU는 인터럽트 요청을 확인하고 인터럽트 플래그를 통해 연재 인터럽트를 받아들일 수 있는지 여부를 확인한다.
  4. 인터럽트를 받아들일 수 있다면 CPU는 지금까지의 작업을 백업한다.
  5. CPU는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴을 실행한다.
  6. 인터럽트 서비스 루틴 실행이 끝나면 백업해둔 작업을 복구하여 실행을 재개한다.

CPU가 인터럽트 요청을 수행하기 위해서는 플래그 레지스터의 인터럽트 플래그(interrupt flag)가 활성화 되어 있어야 한다. 인터럽트 플래그는 말 그대로 하드웨어 인터럽트를 받아들일지, 무시할지를 결정하는 플래그이다.

CPU가 중요한 작업을 처리해야 하거나 어떤 방해도 받지 않아야 할 때 인터럽트 플래그는 불가능으로 설정된다. 만약 인터럽트 플래그가 '불가능'으로 설정되어 있다면 CPU는 인터럽트 요청이 오더라도 해당 요청을 무시한다. 반대로 인터럽트 플래그가 '가능'으로 설정되어 있다면 CPU는 인터럽트 요청 신호를 받아들이고 인터럽트를 처리한다.


CPU가 인터럽트 요청을 받아들이기로 했다면 CPU는 인터럽트 서비스 루틴이라는 프로그램을 실행한다. 인터럽트 서비스 루틴(ISR: Interrupt Service Routine)은 인터럽트를 처리하기 위한 프로그램이다. 인터럽트 핸들러(interrupt handler)라고도 부른다. 인터럽트 서비스 루틴은 '키보드가 어떤 인터럽트 요청을 보냈을 때는 이렇게 작동한다.', '마우스가 어떤 인터럽트 요청을 보냈을 때는 이렇게 작동한다.', '프로그램에 어떤 문제가 생겼을 때는 어떻게 작동한다.'와 같이 어떤 인터럽트가 발생했을 때 해당 인터럽트를 어떻게 처리하고 작동해야 할지에 대한 정보로 이루어진 프로그램이다.

요컨대 'CPU가 인터럽트를 처리한다'라는 말은 '인터럽트 서비스 루틴을 실행하고, 본래 수행하던 작업으로 다시 돌아온다'라는 말과 같다.

인터럽트를 처리하는 방법은 입출력장치마다 다르므로 각기 다른 인터럽트 서비스 루틴을 가지고 있다. 즉, 메모리에는 여러 개의 인터럽트 서비스 루틴이 저장되어 있다. 이들 하나하나가 '인터럽트가 발생하면 어떻게 행동해야 할지를 알려주는 프로그램'이라고 보면 된다.

CPU는 각기 다른 인터럽트 서비스 루틴을 구분할 수 있어야한다. CPU는 수많은 인터럽트 서비스 루틴을 구분하기 위해 인터럽트 벡터를 이용합니다. 인터럽트 벡터(interrupt vector)는 인터럽트 서비스 루틴을 식별하기 위한 정보이다. 인터럽트 벡터를 알면 인터럽트 서비스 루틴의 시작 주소를 알 수 있기 때문에 CPU는 인터럽트 벡터를 통해 특정 인터럽트 서비스 루틴을 처음부터 실행할 수 있다.

CPU는 하드웨어 인터럽트 요청을 보낸 대상으로부터 데이터 버스를 통해 인터럽트 벡터를 전달받는다.

가령, CPU가 작업을 수행하는 도중 키보드 인터럽트가 발생하면 CPU는 인터럽트 벡터를 참조하여 키보드 인터럽트 서비스 루틴의 시작 주소를 알아내고, 이 시작 주소부터 실행해 나가며 키보드 인터럽트 서비스 루틴을 실행한다.

인터럽트 서비스 루틴은 여느 프로그램과 마찬가지로 명령어와 데이터로 이루어져있다. 그렇기에 인터럽트 서비스 루틴도 프로그램 카운터를 비롯한 레지스터를 사용하여 실행한다.

Reference

  • 혼자 공부하는 컴퓨터구조 & 운영체제