인터럽트 처리 구조와 운영 시 고려할 점

인터럽트의 처리 흐름과 IRQ, ISR, 예외, MSI/MSI-X, 인터럽트 어피니티를 실무 관점에서 정리합니다.

2026-08-14 · 최초 발행 2026-01-06

CPU 실행 흐름에 개입하는 비동기 이벤트

인터럽트는 하드웨어 장치나 소프트웨어가 즉시 처리를 요청할 때 CPU의 일반 실행 흐름을 잠시 멈추게 하는 비동기 메커니즘이다. 폴링처럼 CPU가 계속 상태를 확인하지 않고 이벤트가 생긴 시점에만 개입하므로, CPU 사이클을 다른 작업에 사용할 수 있다.

처리는 현재 명령이 끝난 뒤 시작한다. CPU는 레지스터와 실행 상태를 보존하고, 인터럽트 벡터를 통해 인터럽트 서비스 루틴(ISR)을 찾는다. ISR이 끝나면 저장했던 컨텍스트를 복원해 중단 지점부터 실행을 이어 간다.

프로그램 실행인터럽트 신호현재 명령 완료컨텍스트 저장인터럽트 벡터 참조ISR 실행컨텍스트 복원원래 프로그램 재개

인터럽트는 발생 주체와 마스킹 가능 여부에 따라 구분할 수 있다.

  • 하드웨어 인터럽트는 외부 장치에서 발생한다.
  • 소프트웨어 인터럽트는 명령어로 발동하며 trap, syscall이 여기에 속한다.
  • 내부 인터럽트인 예외는 division by zero처럼 CPU 내부의 오류에서 발생한다.
  • 마스커블 인터럽트는 비활성화할 수 있다.
  • 논마스커블 인터럽트(NMI)는 항상 처리되는 고우선순위 인터럽트다.

이벤트를 CPU로 전달하는 경로

인터럽트 컨트롤러는 여러 인터럽트 소스를 받아 우선순위를 정하고 마스킹 상태를 검사한 뒤 CPU에 신호를 전달한다. 레거시 환경에서는 PIC와 8259A가 쓰이며, APIC 구성에서는 로컬 APIC와 I/O APIC이 이 역할을 맡는다. MSI/MSI-X도 이 경로와 연결된다.

인터럽트 소스PIC/APIC우선순위 결정마스킹 검사CPU에 신호PIC8259A (레거시)APIC로컬 APIC + I/O APICMSI/MSI-X

인터럽트 벡터 테이블은 각 인터럽트를 적절한 ISR로 연결하는 기준점이다. 벡터 번호에는 인터럽트별 고유 번호가 할당되고, 테이블에는 핸들러의 메모리 주소가 저장된다. x86에서는 IDT(Interrupt Descriptor Table), ARM에서는 IVT(Interrupt Vector Table)라는 이름으로 쓰이며, 벡터 번호가 우선순위 결정에도 사용된다.

우선순위 인터럽트 유형 예시
최상 NMI 하드웨어 오류, 전원 이상
매우 높음 하드웨어 예외 Machine Check
높음 외부 인터럽트 타이머, 네트워크
중간 소프트웨어 인터럽트 시스템 콜
낮음 트랩 디버그 브레이크포인트

장치가 보내는 하드웨어 인터럽트

타이머는 일정 주기로, 키보드는 입력 시점에, 마우스는 이동과 클릭 이벤트에 맞춰 인터럽트를 발생시킨다. 네트워크 카드는 패킷 수신이나 송신 완료를 알리고, 디스크는 읽기와 쓰기 작업의 완료를 알리는 방식으로 CPU의 처리를 요청한다.

IRQ(Interrupt Request)는 이런 하드웨어 요청을 구분하는 수단이다.

IRQ 라인IRQ 0: 타이머IRQ 1: 키보드IRQ 3/4: 직렬 포트IRQ 14/15: IDE 디스크PCIe: MSI

레거시 PCI에서는 여러 장치가 하나의 IRQ를 공유할 수 있다. 이 공유는 IRQ 충돌에 따른 성능 저하의 원인이 될 수 있다. MSI/MSI-X는 장치별 고유 벡터를 할당하며, PCI 인터럽트 라우팅은 BIOS/ACPI 설정과 관련된다. 리눅스에서는 /proc/interrupts에서 현재 상태를 확인할 수 있다.

시스템 콜과 CPU 예외의 처리

시스템 콜은 사용자 모드에서 커널 모드로 전환해 보호된 커널 기능을 호출하는 경로다. x86 레거시 리눅스 시스템 콜에는 INT 0x80이 사용되며, SYSCALL/SYSENTER는 빠른 시스템 콜을 위한 방식이다. 시스템 콜 번호와 인자는 레지스터로 전달되고, 커널은 실행 결과를 반환 값으로 돌려준다.

CPU 예외는 폴트(Fault), 트랩(Trap), 어보트(Abort)로 나뉜다. 폴트는 페이지 폴트처럼 복구할 수 있고, 트랩은 디버그 트랩처럼 의도적으로 발생한다. 어보트는 하드웨어 오류처럼 복구할 수 없는 경우다.

CPU 예외폴트(Fault)트랩(Trap)어보트(Abort)복구 가능의도적 발생복구 불가능페이지 폴트디버그 트랩하드웨어 오류

대표적인 예외에는 Division by Zero, 가상 메모리 접근 오류인 페이지 폴트, 권한 위반에 따른 General Protection Fault, 잘못된 명령어의 Invalid Opcode, 디버거 중단점인 Debug Breakpoint가 있다.

ISR에는 남기고, 나머지는 미룬다

인터럽트가 발생한 뒤 인지 지연, 컨텍스트 스위칭, ISR 실행, 복귀 오버헤드가 이어진다. 레이턴시를 다룰 때는 ISR을 빠르게 유지하고, 우선순위를 조정하며, 인터럽트 병합을 검토한다.

인터럽트 발생인지 지연컨텍스트 스위칭ISR 실행복귀 오버헤드최소화 기법빠른 ISR우선순위 조정인터럽트 병합

인터럽트 마스킹은 임계 구역을 보호할 때 사용한다. x86의 CLI/STI는 인터럽트를 비활성화하거나 활성화하며, 스핀락은 인터럽트 비활성화와 락을 함께 사용한다. 개별 IRQ도 마스킹할 수 있지만 NMI는 마스킹할 수 없다.

Top Half는 긴급한 최소 작업만 맡고, 나머지는 Bottom Half로 넘긴다. 커널은 Softirq, 간단한 지연 작업을 위한 Tasklet, 프로세스 컨텍스트에서 실행되는 Work Queue를 통해 이 분리를 구현한다. ISR에서는 빠른 실행, 블로킹 금지, 재진입 안전성, 최소 작업 원칙을 지켜야 하며 sleep, mutex는 사용할 수 없다.

폴링과 인터럽트를 함께 쓰는 경우

폴링은 상태를 지속적으로 확인하므로 CPU 사용이 커질 수 있지만, 응답 시간이 폴링 주기에 따라 예측 가능하고 구현이 단순하다. 인터럽트는 이벤트가 있을 때만 CPU를 사용해 저빈도 이벤트에 적합하지만, 처리 경로는 더 복잡하고 지연 시간이 변동할 수 있다.

특성 폴링 인터럽트
CPU 사용 지속적 체크로 낭비 이벤트 시에만 사용
응답 시간 폴링 주기에 의존 즉각 응답
구현 복잡도 단순 복잡
오버헤드 높음 (빈번한 체크) 낮음 (이벤트 시만)
적합 시나리오 고빈도 이벤트 저빈도 이벤트
지연 시간 예측 가능 변동 가능

NAPI(Network API)는 부하 상태에 따라 두 방식을 결합한다. 저부하에서는 패킷 도착 시 인터럽트로 처리하고, 고부하에서는 인터럽트를 비활성화한 뒤 배치 처리하는 폴링으로 전환한다.

NAPI (Network API)저부하: 인터럽트고부하: 폴링패킷 도착 인터럽트연속 처리로 전환인터럽트 비활성화배치 처리

멀티코어와 가상화 환경의 인터럽트

MSI/MSI-X는 메모리 쓰기로 인터럽트를 전달하는 Message Signaled Interrupts 방식이다. PCIe 데이터 패킷을 사용하므로 IRQ 라인이 필요 없고, 장치당 수백 개 벡터를 둘 수 있다. 로컬 APIC 활용은 캐시 친화성을 높이며, NUMA 환경에서는 특정 CPU에 인터럽트를 할당할 수 있다.

인터럽트 어피니티는 특정 CPU 코어에 인터럽트를 바인딩하는 설정이다. NUMA 노드의 메모리 지역성과 동일 CPU에서 처리되는 캐시 히트율을 활용할 수 있으며, 여러 코어에 인터럽트를 분산해 부하를 조절할 수도 있다. 리눅스의 irqbalance는 자동 밸런싱을 담당한다.

가상화 환경에서는 Posted Interrupt와 Virtual APIC이 사용된다. Posted Interrupt는 하이퍼바이저를 우회하고, Virtual APIC은 VM에 직접 전달된다. SR-IOV에서는 VF별 독립 인터럽트를 둔다.

가상화 인터럽트Posted InterruptVirtual APIC하이퍼바이저 우회VM 직접 전달SR-IOVVF별 독립 인터럽트

리눅스 커널에서 핸들러를 등록하는 방법

리눅스 커널은 request_irq로 인터럽트 핸들러를 등록하고 free_irq로 해제한다. 핸들러는 긴급 처리를 끝낸 뒤 Bottom Half 작업을 스케줄할 수 있다.

// 인터럽트 핸들러 등록
int request_irq(unsigned int irq, irq_handler_t handler,
                unsigned long flags, const char *name, void *dev);

// ISR 구현
irqreturn_t my_interrupt_handler(int irq, void *dev_id) {
    // 긴급 처리
    ack_interrupt();

    // Bottom Half 스케줄
    schedule_work(&my_work);

    return IRQ_HANDLED;
}

// 해제
void free_irq(unsigned int irq, void *dev_id);

운영 중 인터럽트 문제를 확인할 때는 /proc/interrupts의 IRQ 통계, /sys/kernel/irq/의 어피니티 설정, ftrace의 인터럽트 추적을 함께 살핀다.

인터럽트 디버깅/proc/interrupts/sys/kernel/irq/ftraceIRQ 통계어피니티 설정인터럽트 추적

인터럽트는 외부 장치의 응답과 보호된 커널 기능 접근을 가능하게 하는 시스템의 기본 경로다. 멀티코어 환경에서는 MSI-X와 인터럽트 어피니티가 높은 처리량과 낮은 레이턴시를 함께 다루며, 고성능 네트워킹과 스토리지 시스템에서 특히 중요한 역할을 한다.

인터럽트운영체제IRQISRAPIC