동시에 두 개 이상의 인터럽트가 발생하면, 어떻게 처리해야 하나요?

인터럽트 컨트롤러(PIC/APIC)가 우선순위를 비교하여 높은 우선순위 인터럽트를 먼저 처리하고, 낮은 우선순위 인터럽트는 보류(Pending)했다가 나중에 처리합니다.

처리 원칙

원칙설명
우선순위 기반 처리높은 우선순위 인터럽트를 먼저 처리
중첩 인터럽트 (Nested)높은 우선순위가 낮은 우선순위의 ISR을 선점 가능
보류 (Pending)현재 처리 불가능한 인터럽트는 보류 후 나중에 처리
순차 처리같은 우선순위면 발생 순서대로 처리

인터럽트 우선순위

높음  ┌──────────────────────────────┐
      │ NMI (논마스커블 — 전원 이상)    │ ← 절대 무시 불가
      ├──────────────────────────────┤
      │ 하드웨어 오류 (Machine Check)  │
      ├──────────────────────────────┤
      │ 타이머 인터럽트 (IRQ0)         │ ← 스케줄링에 필수
      ├──────────────────────────────┤
      │ 디스크 I/O (IRQ14)            │
      ├──────────────────────────────┤
      │ 네트워크 (IRQ11)              │
      ├──────────────────────────────┤
      │ 키보드 (IRQ1)                 │
      ├──────────────────────────────┤
      │ 마우스 (IRQ12)                │
      ├──────────────────────────────┤
낮음  │ 소프트웨어 인터럽트 (트랩)       │
      └──────────────────────────────┘

시나리오별 처리 방식

시나리오 1: 높은 우선순위가 낮은 우선순위 ISR을 선점

키보드 ISR 실행 중 (낮은 우선순위)
    │
    ▼
타이머 인터럽트 발생 (높은 우선순위)
    │
    ▼
키보드 ISR 중단 → 타이머 ISR 먼저 실행
    │
    ▼
타이머 ISR 완료
    │
    ▼
키보드 ISR 재개 → 이어서 처리
시간 ──→

키보드 ISR:  ████████░░░░░░████████
                     │         ↑
                  타이머 발생  복귀
                     │
타이머 ISR:          ██████████
                     (선점 실행)

시나리오 2: 낮은 우선순위가 높은 우선순위 ISR 중에 발생

타이머 ISR 실행 중 (높은 우선순위)
    │
    ▼
키보드 인터럽트 발생 (낮은 우선순위)
    │
    ▼
키보드 인터럽트 보류 (Pending)
    │
    ▼
타이머 ISR 완료 → EOI 전송
    │
    ▼
보류된 키보드 인터럽트 처리 시작
시간 ──→

타이머 ISR:  ████████████████
                  │          │
              키보드 발생    타이머 완료
              (보류됨)         │
                              ▼
키보드 ISR:                  ██████████
                             (보류 해제 후 실행)

시나리오 3: 같은 우선순위의 인터럽트가 동시 발생

키보드(IRQ1)와 마우스(IRQ12)가 동시에 발생
    │
    ▼
인터럽트 컨트롤러가 우선순위 비교
    │
    ├── PIC: IRQ 번호가 낮을수록 우선 → 키보드(IRQ1) 먼저
    │
    └── APIC: 프로그래밍된 우선순위에 따라 결정
    │
    ▼
키보드 ISR 실행 → 완료 → EOI
    │
    ▼
마우스 ISR 실행 → 완료 → EOI

시나리오 4: NMI가 발생한 경우

어떤 ISR이 실행 중이든 (cli로 인터럽트 비활성화 상태여도)
    │
    ▼
NMI (전원 이상) 발생
    │
    ▼
즉시 현재 ISR 중단 → NMI 핸들러 실행
(NMI는 IF 플래그와 무관하게 항상 처리됨)

인터럽트 컨트롤러의 동시 처리 메커니즘

PIC (8259A) — 레거시

PIC 내부 레지스터:

IRR (Interrupt Request Register)
  → 현재 요청된 인터럽트들을 비트로 기록
  ┌─────────────────────────────────┐
  │ IRQ7│IRQ6│IRQ5│IRQ4│IRQ3│IRQ2│IRQ1│IRQ0 │
  │  0  │  0 │  0 │  0 │  0 │  0 │  1 │  1  │
  └─────────────────────────────────┘
  → IRQ0(타이머)과 IRQ1(키보드) 동시 요청

ISR (In-Service Register)
  → 현재 처리 중인 인터럽트
  ┌─────────────────────────────────┐
  │  0  │  0 │  0 │  0 │  0 │  0 │  0 │  0  │
  └─────────────────────────────────┘
  → 아직 처리 중인 것 없음

IMR (Interrupt Mask Register)
  → 마스킹된(비활성화된) 인터럽트
  ┌─────────────────────────────────┐
  │  0  │  0 │  0 │  0 │  0 │  0 │  0 │  0  │
  └─────────────────────────────────┘
  → 마스킹 없음

처리 과정:
① IRR에서 가장 높은 우선순위(IRQ0) 선택
② ISR의 IRQ0 비트 세팅 (처리 중 표시)
③ CPU에 벡터 번호 전달
④ CPU가 ISR 실행
⑤ EOI 수신 → ISR의 IRQ0 비트 클리어
⑥ IRR에 남은 IRQ1 처리

APIC — 현대 시스템

I/O APIC 라우팅 테이블:
┌──────┬────────────┬──────────────┬──────────────┐
│ IRQ  │ 벡터 번호   │ 우선순위      │ 대상 코어     │
├──────┼────────────┼──────────────┼──────────────┤
│  0   │ 32         │ 최고         │ 코어 0        │
│  1   │ 33         │ 높음         │ 코어 1        │
│ 11   │ 43         │ 중간         │ 코어 2        │
│ 14   │ 46         │ 중간         │ 코어 3        │
└──────┴────────────┴──────────────┴──────────────┘

→ APIC는 서로 다른 코어에 동시 분배 가능!
→ 진정한 "동시 처리"가 가능
[PIC — 단일 코어]
인터럽트 A ──→ CPU ──→ 순차 처리 (A 먼저, B 나중)
인터럽트 B ──→

[APIC — 멀티 코어]
인터럽트 A ──→ 코어 0 ──→ 동시에 ISR_A 실행
인터럽트 B ──→ 코어 1 ──→ 동시에 ISR_B 실행

중첩 인터럽트 처리 (Nested Interrupt)

① 프로그램 실행 중 → 키보드 인터럽트(IRQ1) 발생
② 키보드 ISR 실행 시작
    │
    ▼  타이머 인터럽트(IRQ0) 발생 — 더 높은 우선순위
    │
③ 키보드 ISR 상태 저장 → 타이머 ISR 실행
    │
    ▼  NMI 발생 — 최고 우선순위
    │
④ 타이머 ISR 상태 저장 → NMI 핸들러 실행
    │
    ▼
⑤ NMI 완료 → 타이머 ISR 복원 → 계속 실행
    │
    ▼
⑥ 타이머 ISR 완료 → 키보드 ISR 복원 → 계속 실행
    │
    ▼
⑦ 키보드 ISR 완료 → 원래 프로그램 복원 → 계속 실행
스택 구조 (중첩 시):

┌──────────────────┐ ← 높은 주소
│ 프로그램 상태      │  ① 프로그램 중단
├──────────────────┤
│ 키보드 ISR 상태   │  ② 키보드 ISR 중단
├──────────────────┤
│ 타이머 ISR 상태   │  ③ 타이머 ISR 중단
└──────────────────┘ ← 현재 RSP (NMI 핸들러 실행 중)

복귀 순서: NMI → 타이머 → 키보드 → 프로그램 (LIFO)

인터럽트 비활성화 구간

ISR 실행 중 같은 레벨 이하의 인터럽트를 일시적으로 차단하여 경쟁 조건(Race Condition)을 방지합니다.

[Interrupt Gate를 통한 자동 비활성화]

인터럽트 발생 → IDT에서 Interrupt Gate 조회
    │
    ▼
CPU가 자동으로 IF = 0 (같은 레벨 이하 인터럽트 차단)
    │
    ▼
ISR 실행 (Top Half — 짧게!)
    │
    ▼
EOI 전송 → iret → IF 자동 복원 (다시 인터럽트 허용)
    │
    ▼
Bottom Half 실행 (인터럽트 허용 상태에서)
구간인터럽트 상태이유
Top Half비활성화 (같은 레벨 이하)공유 자원 보호, 짧게 유지 필수
Bottom Half활성화응답성 유지, 오래 걸리는 작업 처리

동시 인터럽트 처리 전략 요약

전략설명사용 환경
우선순위 기반 선점높은 우선순위가 낮은 우선순위 ISR 선점대부분의 OS
보류 후 순차 처리처리 불가 시 Pending, 나중에 처리단일 코어
멀티코어 분배서로 다른 코어에 동시 분배APIC 기반 멀티코어
인터럽트 비활성화임계 구간에서 일시적으로 차단ISR Top Half
NMI 즉시 처리어떤 상황에서도 즉시 처리치명적 오류
동시 인터럽트 발생 시 결정 흐름:

인터럽트 A, B 동시 발생
    │
    ├── 멀티코어? ──→ Yes → APIC가 서로 다른 코어에 분배 → 동시 처리
    │                 No ↓
    │
    ├── 우선순위 비교
    │    ├── A > B → A 먼저, B 보류
    │    ├── A < B → B 먼저, A 보류
    │    └── A = B → IRQ 번호 낮은 것 먼저 (PIC) 또는 설정에 따라 (APIC)
    │
    └── 처리 중 더 높은 우선순위 발생?
         ├── Yes → 현재 ISR 선점, 새 인터럽트 먼저 처리
         └── No  → 현재 ISR 완료 후 보류된 인터럽트 처리

CSLOG에서 보기