CPU와 인터럽트 (Interrupt)
인터럽트는 무엇인가?
interrupt [ˌɪntəˈrʌpt]
- (말·행동을) 방해하다[중단시키다/가로막다]
- (무엇을 잠깐) 중단시키다
사전 상의 interrupt
(이하 인터럽트)는 위와 같은 어떤 행동이나 흐름을 중단시키는 의미로 등재 되어있다.
컴퓨터에서도 인터럽트는 어떤 흐름을 중지하는 역할을 한다.
CPU는 순차적으로 명령어를 처리한다. 하지만 예상치못하거나 긴급한상황에 의도적으로 특별한 처리를 해야한다. 예를 들어 스타크래프트나 리그오브레전드처럼 3인칭시점에서 마우스로 지면을 클릭하는 경우, 해당위치로 캐릭터가 이동한다. 이 경우 이동이 끝나지 않아도, 우리는 새로운 위치를 클릭하여 방향을 바꿀수도있다.
이 처럼 CPU가 명령을 실행하는중에도 긴급하거나, 실시간 처리가 필요한경우 IRQ를 통해, CPU에 인터럽트 신호를 보내 우선적으로 처리를 수행할 수 있다.
인터럽트 서비스 루틴
Interrupt Service Routine (이하 ISR)은 다른말로 Interrupt Handler(인터럽트 핸들러)라고도 한다.
ISR
은 인터럽트를 처리하기위한 어떤 일련의 프로세스이다. IRQ
를 통해 CPU
로 인터럽트 신호를 보내면(CPU의 인터럽트), CPU는 하던 일을 중단하고 ISR이 있는 주소로 실행을 옮긴다.
그리고 ISR
이 실행된후 다시 원래 연산을 재개한다. ISR은 인터럽트 번호 테이블로 구성되어있다. 이는 시스템마다 다를수 있고 콜백루틴 방식으로 처리된다.
인터럽트 원인에 따라 처리되는 ISR이 별도로 있으며,이는 커널(kernel)에 존재한다.
인터럽트가 발생되는 원인은 일반적으로 하드웨어 리셋
, 정해진 메모리 외부 참조
, 0으로 나누기
등 여러 예외가 존재한다.
인터럽트가 발생(raise)하면 ISR
의 주소를 Interrupt Vector(이하 인터럽트 벡터)라고 하는 배열을 인터럽트 요청과 함께 장치 고유번호로 인덱싱한다.
또한 CPU
는 인터럽트를 포착(catch)하면 현재 실행 중이던 작업을 중단하고 ISR
로 전송(dispatch)하면 루틴을 실행해야하기 때문에 실행중인 작업의 레지스터 값들을 스택에 저장하여 상태를 보존한다.
이러한 값들에는 프로그램 카운터(이하 PC), 스택 포인터 등 범용 레지스터 들이 포함된다.
벡터 번호 | 설명 |
---|---|
0 | 나눗셈 에러 |
1 | 디버그 예외 |
2 | Null 인터럽터 |
... | |
18 | 기기 검사 |
19~31 | (Intel에서 예약, 사용금지) |
32~255 | Maskale 인터럽트 |
ISR
이 실행되는 동안에는 프로세서의 레지스터 값을 변경할수 있기때문에, ISR
이 끝나기전에 인터럽트를 지우고(clear) 스택에 저장해 두었던 레지스터 값들을 다시 복원 하여 CPU가 인터럽트 발생 전 상태로 되돌아 갈수 있게 레지스터 값을 원복한다.
ISR
실행 후 인터럽트 요청에서 받았았던 복귀 주소를 PC
로 적재하여 인터럽트 발생시점부터 실행을 옮겨 중단되었던 연산을 다시 시작한다.
실제로는 인터럽트 벡터의 주소 개수보다 많은 장치가 있기 때문에, 인터럽트 체인
방식을 사용한다.
이는 벡터의 각 요소를 핸들럭 목록을 체인으로 묶어, 처리할수 있는 핸들러를 찾을 떄까지 하나씩 호출하는 방법이다.
위에서 표1
에서 0~31까지는 각 루틴에 대한 마스킹이 이미 되어있기때문에 Non Maskable Interrupt
라고 하며 예약된 루틴이고, 32부터는 Maskable 이므로 그외 인터럽트를 처리하기 위해 사용된다.
IPL
)IPL
은 인터럽트 별로 우선 순위를 정하여, 인터럽트 처리에도 우선순위를 둘 수 있다.IPL
은 순위에 따라 처리를 연기하거나, 순위가 더높은 인터럽트가 실행을 선점 할 수 도있다.
인터럽트의 매커니즘
인터럽트는 CPU연산 중 신호를 받아 ISR
을 실행한다고 하였다. 하지만 컴퓨터는 동기순차회로이기 때문에 순차적으로 연산이 이루어져야 한다.
때문에, CPU가 하나의 명령어 실행이 완료될 때마다 IRQ를 감지하여 인터럽트 번호를 읽어 이 번호를 인터럽트 벡터의 인덱스로 사용하고, ISR
로 점프하여 인덱스와 관련된 주소에서 실행을 시작한다.
인터럽트 처리후 복원까지 수행하면 return_from_interrupt
명령어로 CPU를 인터럽트 전 실행상태로 되돌린다.
CPU가 주기적으로 장치의 상태를 직접확인하고, 상태에따라 처리하는 방식이다.
이는 장치컨트롤러와 연관이이 있는데, CPU와 병렬로 실행되는 장치컨트롤러는 내부의 로컬버퍼와 장치간 데이터의 전송을 담당한다.
장치에서 입력이있다면, 로컬버퍼로 데이터를 이동시키고 상태 레지스터의 값을 변경한다. 여기서 CPU는 장치컨트롤러의 상태 레지스터를 주기적으로 확인하여, 상태가 변경되었는지 확인하며 로컬버퍼의 데이터를 읽어와 처리한다.
이러한 방식은 CPU가 주기적으로 장치의 상태를 확인하기 때문에, CPU의 부하가 높아지고, 실시간 처리에 적합하지 않다. 이때 전송하는 빈도를 폴링 레이트라고한다. 폴링레이트가 높을때 입력이 많은경우 CPU의 부하가 높아지는 이유가 이것 때문이다.
타이머
타이머는 설정한 시간이 지났을때 인터럽트를 발생시킬수 있는 장치이다. 예컨데 사용자 프로그램이 무한루프에 빠지거나, 시스템 서비스 호출에 실패하여, 제어가 운영체제로 복귀하지않는 경우에를 대비해 설정할 수 있다.
대표 적인 예가 DMA이다. DMA는 CPU의 개입없이 메모리와 I/O장치간 데이터를 전송하는 기술이다. DMAC이 입출력 장치간 데이터 전송을 관장하는경우 데이터 버스에 대한 제어권를 얻게 되는데, CPU가 제어권을 넘기는 시점에 타이머를 설정하여, 지정된 시간까지 DMA가 모두 이루어지지 않는 경우 인터럽트를 발생시킨다.