동시에 두 개 이상의 인터럽트가 발생하면, 어떻게 처리해야 하나요?
인터럽트 컨트롤러(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 완료 후 보류된 인터럽트 처리