장치가 준비되면 CPU에 신호를 보내 알리는 방식.
폴링과의 비교
폴링 CPU 가 "다 됐니?" 를 반복해 묻는다
장점 구현이 단순하고 지연이 예측 가능하다
단점 기다리는 동안 CPU 를 태운다
인터럽트 장치가 준비되면 CPU 를 부른다
장점 기다리는 동안 다른 일을 한다
단점 문맥 저장·복원 비용, 발생 시점이 비결정적
언제 폴링이 낫나
- 응답이 매우 빠르다 (인터럽트 처리 비용 > 대기 시간)
- 이벤트가 매우 잦다 (인터럽트 폭주가 더 비싸다)
- 지연의 예측 가능성이 중요하다 (실시간 시스템)
고속 네트워크 카드는 NAPI 처럼 '인터럽트로 시작해 폴링으로 전환' 하는 혼합 방식을 쓴다 — 패킷이 몰릴 때 인터럽트 폭주를 막는다
상하반부 분리
인터럽트 핸들러는 짧아야 한다 — 도는 동안 다른 인터럽트가 막힌다
-
상반부(top half) — 최소한만 — 하드웨어 확인, 데이터 복사, 나중 작업 예약 하반부(bottom half) 무거운 처리 — 나중에 인터럽트가 켜진 상태로 실행
- (softirq · tasklet · workqueue)
DMA와 함께 쓴다
DMA 가 없으면 CPU 가 바이트를 하나씩 옮겨야 한다 DMA 컨트롤러가 메모리↔장치 전송을 대신하고, 다 끝나면 인터럽트로 알린다
- 대량 전송에서 CPU 는 시작과 완료만 관여한다
인터럽트 벡터와 처리 흐름
- ① 장치가 인터럽트 라인에 신호
- ② CPU 가 현재 명령을 끝내고 상태를 저장
- ③ 인터럽트 번호로 벡터 테이블을 조회
- ④ 해당 핸들러(ISR)로 점프 — 커널 모드
- ⑤ 처리 후 원래 지점으로 복귀
시스템 콜은 소프트웨어가 일부러 일으키는 인터럽트다 페이지 폴트 · 0으로 나누기는 예외(exception) 로, 같은 메커니즘을 타지만 원인이 현재 명령 자체에 있다
인터럽트 폭주(interrupt storm)
초당 수십만 패킷이 들어오면 인터럽트만 처리하다 유저 코드가 못 돈다 = receive livelock
대응
인터럽트 병합(coalescing) N개 모이거나 T시간 지나면 한 번만 알림
NAPI 첫 인터럽트 후 폴링으로 전환
RSS/다중 큐 큐를 여러 코어에 분산
인터럽트 비활성화의 위험
- 임계 구역을 지키려 인터럽트를 끄는 기법이 있다 (단일 코어 커널)
- 그 구간 동안 타이머·네트워크 인터럽트가 전부 밀린다
- 오래 끄면 시계가 느려지고 패킷이 유실된다
- 최대한 짧게, 멀티코어에서는 스핀락과 병행해야 한다
- (인터럽트를 꺼도 다른 코어는 계속 돈다)
면접 함정
- ❌ "인터럽트가 항상 낫다" → 이벤트가 폭주하면 폴링이 낫다.
- ❌ 핸들러에서 오래 걸리는 일 수행 → 다른 인터럽트를 막아 시스템이 굳는다.