Polling 방식에 대해 설명해 주세요.

CPU가 주기적으로 장치의 상태를 직접 확인하여 이벤트 발생 여부를 감지하는 I/O 처리 방식입니다.

핵심 개념

항목내용
방식CPU가 반복적으로 장치의 상태 레지스터를 읽어서 확인
주체CPU가 능동적으로 확인 (장치는 수동)
동기/비동기동기적 — CPU가 확인할 때까지 이벤트를 알 수 없음
별칭Busy Waiting, Programmed I/O

폴링의 동작 방식

CPU: 데이터 준비됐어? → 장치: 아니요
CPU: 데이터 준비됐어? → 장치: 아니요
CPU: 데이터 준비됐어? → 장치: 아니요   ← CPU가 계속 확인 (Busy Waiting)
CPU: 데이터 준비됐어? → 장치: 네!      ← 감지
CPU: 데이터 읽기 처리
┌─────────────────────────────────────────────┐
│               폴링 루프                       │
│                                             │
│   while (true) {                            │
│       status = read_device_status();        │
│       if (status == READY) {                │
│           data = read_device_data();        │
│           process(data);                    │
│           break;                            │
│       }                                     │
│       // 준비 안 됐으면 다시 반복             │
│   }                                         │
│                                             │
└─────────────────────────────────────────────┘

폴링 vs 인터럽트

항목폴링 (Polling)인터럽트 (Interrupt)
주체CPU가 장치 상태를 확인장치가 CPU에 알림
CPU 사용이벤트 없어도 CPU 점유이벤트 발생 시에만 CPU 사용
응답 속도폴링 주기에 의존즉시 감지 가능
구현 복잡도단순IDT, ISR 등 구조 필요
컨텍스트 스위칭없음모드 전환 + 레지스터 저장 오버헤드
적합한 상황이벤트가 매우 빈번한 경우이벤트가 불규칙한 경우
[폴링]
CPU 시간: ████████████████████████████████  (항상 점유)
장치:     ─────────────────────●──────────  (가끔 이벤트)
                               ↑
                         이벤트 발생했지만
                     다음 폴링까지 대기해야 감지

[인터럽트]
CPU 시간: ●━━●  ●━━━━●  ●━●               (필요할 때만)
장치:     ─────●────────●──────────────
               ↑        ↑
           즉시 감지  즉시 감지

폴링의 장단점

장점단점
구현이 단순CPU 시간 낭비 (Busy Waiting)
모드 전환 오버헤드 없음이벤트 없을 때도 CPU 점유
인터럽트 레이턴시 없음응답 시간이 폴링 주기에 의존
이벤트 순서가 예측 가능다중 장치 관리 시 비효율적
이벤트가 빈번하면 효율적이벤트가 드물면 매우 비효율적

폴링이 유리한 경우

1. 이벤트가 매우 빈번할 때

[초당 수십만 패킷을 처리하는 고성능 네트워크]

인터럽트 방식:
  패킷마다 인터럽트 → 모드 전환 + 상태 저장/복원 → 오버헤드 폭발
  → "인터럽트 폭풍 (Interrupt Storm)"

폴링 방식:
  지속적으로 NIC 상태 확인 → 패킷이 거의 항상 있음
  → 모드 전환 없이 빠르게 처리
  → 오히려 인터럽트보다 효율적

2. 응답 시간이 극도로 짧아야 할 때

인터럽트: 발생 → 상태 저장 → IDT 조회 → ISR 실행 (~수 μs 지연)
폴링:    확인 → 바로 처리 (~수십 ns 지연)

실시간 시스템(자동차 ECU, 항공기 제어)에서는
확정적인 응답 시간이 중요 → 폴링이 유리할 수 있음

3. 장치가 거의 항상 준비 상태일 때

CPU에 가까운 고속 장치 (예: CPU 내장 센서, 고속 SSD)
  → 확인할 때마다 거의 항상 데이터가 있음
  → 폴링의 "헛수고"가 거의 없음
  → 인터럽트 오버헤드를 아낄 수 있음

실제 사용 사례

사례방식이유
Linux NAPI (네트워크)인터럽트 + 폴링 하이브리드패킷 폭주 시 인터럽트 → 폴링 전환
NVMe SSD폴링 모드 지원초저지연 I/O에서 인터럽트 오버헤드 제거
DPDK (고성능 네트워크)폴링 전용초당 수백만 패킷 처리 시 인터럽트 감당 불가
임베디드/실시간 시스템폴링확정적 응답 시간 보장
일반 키보드/마우스인터럽트이벤트가 드문데 폴링하면 CPU 낭비
일반 디스크 I/O인터럽트I/O 완료까지 수 ms → 폴링 시 CPU 낭비

Linux NAPI — 하이브리드 방식

[일반 상태 — 인터럽트 방식]
패킷 도착 → NIC 인터럽트 → ISR 실행 → 패킷 처리

[패킷 폭주 감지 — 폴링으로 전환]
패킷 폭주 감지 → 인터럽트 비활성화 → 폴링 모드 진입
    │
    ▼
while (패킷이 있는 동안) {
    패킷 = NIC에서 읽기();   // 폴링
    처리(패킷);
}
    │
    ▼
패킷이 줄어듦 → 다시 인터럽트 모드로 복귀

이점:
  - 평소에는 인터럽트로 CPU 절약
  - 폭주 시에는 폴링으로 인터럽트 오버헤드 제거

Java에서의 폴링 예시

// 1. 폴링 방식 — CPU를 계속 점유
while (true) {
    if (queue.peek() != null) {   // 큐에 데이터 있는지 계속 확인
        Object data = queue.poll();
        process(data);
    }
    // 데이터 없어도 루프 반복 → CPU 낭비
}

// 2. 인터럽트(블로킹) 방식 — CPU를 양보
while (true) {
    Object data = queue.take();  // 데이터 올 때까지 스레드 Sleep
    process(data);               // 데이터 도착 시 깨어남
    // 대기 중에는 CPU를 다른 스레드에 양보
}

// 3. 하이브리드 — 폴링 + Sleep
while (true) {
    Object data = queue.poll();
    if (data != null) {
        process(data);
    } else {
        Thread.sleep(10);  // 10ms 쉬고 다시 확인 → CPU 낭비 줄임
    }
}
CPU 사용률 비교:

[순수 폴링]     CPU: ████████████████████████ (100%)
[하이브리드]     CPU: █░░█░░█░░█░░█░░░░░░░░░ (~30%)
[인터럽트/블로킹] CPU: █░░░░░░░█░░░░░░░░░░░░░ (~10%)

핵심 정리

폴링: CPU가 "데이터 있어?" 하고 계속 물어보는 방식

  장점: 단순하고, 이벤트가 빈번하면 효율적
  단점: 이벤트가 드물면 CPU 낭비

실무에서는 순수 폴링보다
인터럽트와 폴링을 결합한 하이브리드 방식을 주로 사용
  → 평소: 인터럽트 (CPU 절약)
  → 이벤트 폭주: 폴링 (오버헤드 절약)

CSLOG에서 보기