mir.pe (일반/어두운 화면)
최근 수정 시각 : 2024-07-28 20:33:00

인터럽트

1. 개요2. 상세3. 과정
3.1. 인터럽트 우선 순위
3.1.1. 정렬 방법
3.1.1.1. 소프트웨어적 방법3.1.1.2. 하드웨어적 방법
3.2. 인터럽트 요구 레벨
4. 종류5. 인터럽트 서술자 테이블 (Interrupt Descriptor Table)

1. 개요

Interrupt

인터럽트란 CPU가 특정 기능을 수행하는 도중에 급하게 다른 일을 처리하고자 할 때 사용할 수 있는 기능이다.

2. 상세

대부분의 컴퓨터는 한 개의 CPU[1]를 사용하므로 한 순간에는 하나의 일 밖에 처리할 수 없기 때문에 [2] 어떤 일을 처리하는 도중에 우선 순위가 급한 일을 처리할 필요[3]가 있을 때 대처할 수 있는 방안이 필요하다.

예를 들면, 키보드의 키를 하나 누르면, 눌려진 키 코드 값이 키보드 버퍼에 입력된 후 CPU에 인터럽트가 걸린다. 그럼 현재 처리하던 작업에 대한 정보를 수집하여 저장한 뒤에 인터럽트 서비스 루틴(Interrupt Service Routine)을 수행한다.(이 경우에는 키보드 버퍼에 있는 키 코드 값을 가져가는 일을 한다.) 이렇게 인터럽트 처리를 마친 후에는 다시 이전에 처리하던 작업으로 돌아간다.

3. 과정

이제 이런 인터럽트의 처리 과정을 간단하게 정리해서 설명하면 다음과 같다.
  1. 기존의 작업을 처리하던 도중, 인터럽트가 발생하면
  2. 현재 컴퓨터가 처리하는 일을 중지하고 현재의 컴퓨터의 상태(CPU 내부의 레지스터, 메인 메모리 내용 등을)를 저장한다.
  3. 해당하는 인터럽트를 처리해주기 위한 인터럽트 서비스 루틴을 처리한다.
  4. 인터럽트 처리 이후 저장되었던 이전 작업의 상태를 복구하고 이전 작업 수행을 재개한다.

3.1. 인터럽트 우선 순위

이렇게 인터럽트가 한 개씩만 실행되면 참 좋겠지만 여러 인터럽트가 동시에 발생하는 경우는 많이 존재한다. 이 때 한 개의 CPU인 상황이라면 동시에 여러 개의 인터럽트가 발생한다면 우선 순위를 정해서 순차적으로 처리해야 한다. 이를 인터럽트 우선 순위라 하고 이런 우선 순위는 아래와 같이 중요하고 심각한 인터럽트가 우선적으로 처리되어야 한다.
  1. 전원 공급의 이상
  2. CPU의 기계적인 오류
  3. 외부 신호에 의한 인터럽트
  4. 입출력 전송 요청 및 전송 완료, 전송 오류
  5. 프로그램 검사 인터럽트
  6. 수퍼바이저 호출(SVC 인터럽트)

3.1.1. 정렬 방법

이렇게 많은 인터럽트의 우선 순위를 정렬하기 위해서 소프트웨어적인 방법과 하드웨어적 방법이 있다.
3.1.1.1. 소프트웨어적 방법
소프트웨어적인 방법으로는 폴링 등이있다.
3.1.1.2. 하드웨어적 방법
하드웨어적인 방법은 벡터 인터럽트(Vectored Interrupt)라고도 불린다. 하드웨어적 방법은 인터럽트를 요청할 수 있는 장치에 버스를 직렬 또는 병렬로 연결해 인터럽트 요청 자치의 번호를 CPU에게 알리는 방식이다.

3.2. 인터럽트 요구 레벨

Windows에서 사용하는 인터럽트 수준으로 줄여서 IRQL(Interrupt Request Level)라고 한다. CPU의 인터럽트가 물리적인 인터럽트라면 윈도우의 IRQL는 논리적인 인터럽트이다.

IRQL는 CPU 아키텍처마다 값이 다른데, x86의 경우 0~31이며 AMD64(x64)와 AI-64의 경우 0~15이다.

IRQL의 구성은 다음과 같다. 주로 많이 사용하는 IRQL만 가져왔다.
윈도우 인터럽트 요구 레벨
이름 설명
x86 AMD64 IA-64
PASSIVE_LEVEL 0 0 0 대부분의 커널 및 유저 스레드가 동작하는 수준
APC_LEVEL 1 1 1 APC(Asynchronous Procedure Calls, 비동기 프로시저 호출) 및 페이지 폴트(Page Fault)
DISPATCH_LEVEL 2 2 2 스레드 스케줄링(Thread Scheduling) 및 DPC(Deferred Procedure Call, 지연된 프로시저 호출)
DIRQL 3-26 3-11 4-11 장치 인터럽트
POWER_LEVEL 30 15 14 전원 이상
HIGH_LEVEL 31 15 15 최고 수준

PASSIVE_LEVEL - 대부분의 프로세스가 동작하는 수준으로 IRQL에서 가장 낮다.
APC_LEVEL - 커널에서 비동기 프로시저 호출을 처리할 때 사용한다.
DISPATCH_LEVEL - 스케줄링 및 DPC를 위해 사용하는 수준으로 여기서부터 프로세서는 스레드를 전환하지 않는다. 즉 컨텍스트 스위칭 (문맥교환)이 일어나지 않는다. 여기서 주의해야할 점은 페이징된 메모리에 접근하거나 파일 입출력을 수행하면 안된다. 즉 페이지 폴트를 일으키면 안되는데 전환이 일어나지 않기에 페이지 폴트 핸들러가 실행할 수 없기 때문이다. 또한 대기 함수(KeWaitForSingleObject, KeDelayExecutionThread 등)를 사용할 수 없다.
DIRQL - 장치(키보드, 마우스 등)으로부터 발생하는 인터럽트를 처리하기 위해 사용하는 수준이다. 예를 들어 장치 드라이버의 인터럽트 서비스 루틴(ISR)이 DIRQL 수준에서 실행된다. 이 수준에서 매우 제한적인 커널 함수만 사용할 수 있다.

커널 함수마다 어느 IRQL에서 동작해야 하는지 다르다. 대부분 APC_LEVEL 이하지만 간혹 PASSIVE_LEVEL에서만 실행할 수 있거나 DISPATCH_LEVEL 또는 그 이상에서만 호출할 수 있는 커널 함수가 있다. 이러한 부분들은 마이크로소프트 문서에 나와있다.

이 IRQL를 변경할 수 있는 커널 함수는 KeRaiseIrql와 KeLowerIrql이다. 물론 드라이버에서만 사용할 수 있다. KeRaiseIrql는 IRQL를 높일 때 사용하고 KeLowerIrql는 IRQL를 낮출 때 사용한다. 여기서 KeRaiseIrql를 사용할 때 현재의 IRQL보다 낮게 설정하면 안된다는 것이다. 그럴 경우 블루스크린이 발생한다. 실제로 KeRaiseIrql 내부에서 변경하려는 IRQL 레벨이 현재의 IRQL 레벨보다 낮을 경우 블루스크린을 발생시킨다. 따라서 IRQL를 낮출려면 KeLowerIrql를 사용해야 한다. KeLowerIrql도 변경하려는 IRQL이 현재의 IRQL보다 높을 경우 KeRaiseIrql와 마찬가지로 블루스크린이 발생한다.

4. 종류

인터럽트는 다양한 종류가 있다. 일반적으로 사용되는 인터럽트는 두가지 갈래로 나뉠 수 있는데,

5. 인터럽트 서술자 테이블 (Interrupt Descriptor Table)

CPU에 들어오는 인터럽트 백터 테이블로 0x00부터 0xFF까지 총 256의 인터럽트 백터를 저장할 수 있다.

참고로 예외 처리나 기타를 위해 0x00부터 0x15까지는 예약되어 있다.


[1] 두개 이상의 CPU가 장착될 경우 멀티 프로세서이다. 사실 2010년대부터는 맞는 설명은 아닌데, 멀티코어 프로세서, 빅리틀 같은 것이 들어가 실제로는 CPU 여러 개가 들어가는 환경이나 다름없기 때문. [2] 대부분의 컴퓨터가 동시에 여러 가지 일을 동시에 처리하는 것 같지만 사실 매우 빠른 속도로 시간을 매우 잘게 쪼개고 일을 나누어서 처리한다. 이런 방식을 time-sharing(시-분할) 방식이라고 한다. [3] 비교적 낮은 수준에서 간단한 예를 들면 '4순위 입출력 전송 요청 및 전송 완료, 전송 오류(마우스 커서 이동 및 클릭, 키보드 입출력, 디스플레이 출력 등)'이 있다. 렉이 좀 많이 걸려 화면의 모든 페이지가 죄다 튕기는 한이 있어도 어지간해서는 마우스 동작 자체는 문제 없는 것도 이런 이유. 하지만 심각한 오류가 있을 때는 저런 것들을 죄다 씹어버리고 컴퓨터는 심각한 오류를 먼저 해결한다. 후술하겠지만 최우선 사항은 전원 공급 문제. [4] 꽃이름으로 꽃들의 뿌리가 땅속에서 직렬로 연결 된것을 뜻한다. [5] 이상하게 메모리 장소를 참조하는 경우 등. [6] 주로 기계어 레벨에서 제공되지 않는 인스트럭션을 운영 체제의 시스템 콜(System Call)의 형태로 제공되는 인터럽트.