폴링·인터럽트·DMA로 이해하는 I/O 처리 방식
폴링, 인터럽트 기반 I/O, DMA의 동작 원리와 IOMMU, 버퍼링, 스케줄링을 중심으로 I/O 성능을 정리한다.
2026-08-14 · 최초 발행 2026-01-16
CPU가 장치와 데이터를 주고받는 경로
I/O 시스템은 CPU와 주변 장치 사이의 데이터 교환을 맡는다. 키보드, 디스크, 네트워크처럼 성격이 다른 장치도 장치 컨트롤러와 드라이버, 버스를 통해 운영체제에 연결된다. 처리 방식의 차이는 CPU가 완료 상태를 언제, 얼마나 개입해서 확인하느냐에서 시작된다.
| 구성 요소 | 역할 |
|---|---|
| I/O 장치 | 데이터 입출력 수행 (디스크, NIC 등) |
| 장치 컨트롤러 | 장치 제어 및 데이터 버퍼링 |
| I/O 포트 | CPU와 컨트롤러 간 통신 인터페이스 |
| 장치 드라이버 | 하드웨어 추상화 소프트웨어 |
| I/O 버스 | 데이터 전송 경로 (PCIe, SATA 등) |
완료 상태를 CPU가 직접 확인하는 폴링
폴링은 CPU가 장치 상태를 주기적으로 읽어 I/O 완료 여부를 판단하는 방식이다. 상태 레지스터의 Busy 비트가 해제될 때까지 CPU가 반복 확인한 뒤, 준비 상태가 되면 데이터 레지스터에 접근한다.
전형적인 흐름은 I/O 명령 발행, 상태 확인 루프, 데이터 전송, 완료 처리로 이어진다. 구현은 단순하고 인터럽트 오버헤드가 없으며, 빠른 장치에서는 짧은 지연 시간을 기대할 수 있다. 디버깅도 비교적 쉽다.
반면 대기 시간 동안 CPU를 점유하므로 바쁜 대기가 발생한다. 장치가 느리거나 여러 장치를 함께 처리해야 하면 CPU 시간 낭비와 전체 응답성 저하가 커진다.
폴링은 다음과 같은 조건에서 선택할 수 있다.
| 상황 | 이유 |
|---|---|
| 매우 빠른 장치 | 인터럽트 오버헤드가 더 클 수 있음 |
| 빈번한 I/O | 인터럽트 폭풍 방지 |
| 실시간 시스템 | 예측 가능한 지연 시간 |
| 전용 I/O 코어 | 다른 작업에 영향 없음 |
장치가 완료를 알리는 인터럽트 기반 I/O
인터럽트 기반 I/O에서는 장치가 작업을 끝낸 시점에 CPU로 인터럽트 신호를 보낸다. CPU는 완료를 기다리는 대신 다른 작업을 수행하고, 인터럽트가 발생하면 핸들러가 데이터를 읽고 처리 결과를 반영한다.
이 방식은 I/O 완료를 기다리지 않는 비동기 처리, 필요한 시점에만 CPU가 개입하는 이벤트 기반 처리, I/O 대기 중 다른 프로세스를 실행하는 멀티태스킹을 가능하게 한다. 결과적으로 CPU 자원을 더 효율적으로 활용할 수 있다.
| 측면 | 폴링 | 인터럽트 |
|---|---|---|
| CPU 오버헤드 | I/O 시간에 비례 | 인터럽트당 고정 |
| 응답 지연 | 폴링 주기에 의존 | 인터럽트 지연 시간 |
| 처리량 | 느린 장치에서 낮음 | 일정하게 유지 |
| 확장성 | 장치 수에 따라 저하 | 양호 |
| 예측 가능성 | 높음 | 인터럽트 시점 불확실 |
고속 장치에서는 인터럽트가 너무 자주 발생해 인터럽트 폭풍으로 이어질 수 있다. 이때 인터럽트 통합은 시간 임계값이나 패킷 수 임계값에 도달한 시점에 인터럽트를 발생시켜 데이터를 일괄 처리한다.
| 파라미터 | 설명 | 트레이드오프 |
|---|---|---|
| 시간 임계값 | 최대 대기 시간 | 지연 vs 효율 |
| 패킷 임계값 | 최대 누적 패킷 수 | 처리량 vs 지연 |
| 적응형 조정 | 부하에 따른 동적 조절 | 복잡성 증가 |
대량 전송에서 CPU를 우회하는 DMA
DMA(Direct Memory Access)는 장치가 CPU의 지속적인 개입 없이 메모리로 데이터를 전송하게 하는 기술이다. 프로그램 I/O와 인터럽트 I/O는 장치에서 CPU를 거쳐 메모리로 데이터가 이동하지만, DMA는 장치와 메모리 사이를 직접 연결한다. CPU는 전송의 시작과 완료를 처리한다.
| 방식 | 데이터 전송 경로 | 문제점 |
|---|---|---|
| 프로그램 I/O | 장치 → CPU → 메모리 | CPU가 모든 바이트 처리 |
| 인터럽트 I/O | 장치 → CPU → 메모리 | 빈번한 인터럽트 오버헤드 |
| DMA | 장치 → 메모리 (직접) | CPU는 전송 시작/완료만 처리 |
DMA 컨트롤러는 메모리 주소 레지스터(MAR), 데이터 카운터(DC), 제어 레지스터(CR), 데이터 레지스터(DR)를 바탕으로 전송을 관리한다.
전송을 시작할 때 CPU는 DMA에 주소, 크기, 방향을 초기화하고 장치에 I/O 명령을 발행한다. 장치가 전송을 요청하면 DMA는 HOLD로 버스 사용권을 요청하고, CPU는 HLDA로 이를 허가한다. DMA는 데이터를 메모리에 기록하면서 카운터를 감소시키고 주소를 증가시킨 뒤, 완료 인터럽트로 CPU에 결과를 알린다.
| 모드 | 설명 | 특징 |
|---|---|---|
| Burst Mode | 전체 블록 연속 전송 | 최고 처리량, 버스 독점 |
| Cycle Stealing | 한 워드씩 전송 | CPU와 번갈아 버스 사용 |
| Transparent Mode | CPU 미사용 시에만 전송 | CPU 영향 없음, 느림 |
분산 메모리와 장치 접근을 다루는 DMA 확장
Scatter-Gather DMA는 불연속적인 메모리 영역에 데이터를 전송할 때 사용한다. DMA 디스크립터 테이블을 따라 여러 메모리 영역에 접근하므로, 가상 메모리 환경에서 메모리 복사 없이 Zero-copy I/O를 구현할 수 있다.
IOMMU(I/O Memory Management Unit)는 DMA와 가상 메모리를 연결하는 하드웨어다. 장치의 가상 주소를 물리 주소로 변환하고, 장치의 무단 메모리 접근을 막는다. MSI 인터럽트 보안 강화에 필요한 인터럽트 리매핑과 장치별 독립 주소 공간을 통한 DMA 격리도 담당한다.
스케줄링과 버퍼링으로 조정하는 I/O 경로
디스크 I/O 스케줄링은 요청을 어떤 순서로 처리할지 결정한다. 공정성, 처리량, 지연 시간 요구가 다르므로 알고리즘도 워크로드에 맞춰 선택해야 한다.
| 알고리즘 | 특징 | 적합한 상황 |
|---|---|---|
| FIFO | 도착 순서대로 처리 | 공정성 중요 |
| SSTF | 가장 가까운 요청 우선 | 처리량 최적화 |
| SCAN | 엘리베이터 방식 | 균형잡힌 성능 |
| C-LOOK | 한 방향만 스캔 | 효율적 디스크 활용 |
| CFQ | 프로세스별 공정 큐 | 다중 사용자 환경 |
| Deadline | 요청별 마감 시간 보장 | 지연 시간 보장 |
버퍼링은 응용 프로그램의 사용자 버퍼, 커널 버퍼 캐시, 장치 버퍼를 거쳐 I/O 장치까지 이어지는 전송 경로를 조정한다.
| 버퍼링 유형 | 설명 | 효과 |
|---|---|---|
| 단일 버퍼링 | 하나의 시스템 버퍼 | 기본적인 I/O 최적화 |
| 이중 버퍼링 | 두 버퍼 교대 사용 | 연속 I/O 지원 |
| 순환 버퍼링 | 다수의 버퍼 순환 사용 | 고속 스트리밍 |
I/O 완료를 기다리는 방식도 운영 특성에 영향을 준다.
| 기법 | 설명 | API 예시 |
|---|---|---|
| Blocking I/O | 완료까지 대기 | read(), write() |
| Non-blocking I/O | 즉시 반환 | O_NONBLOCK |
| I/O 다중화 | 여러 FD 동시 감시 | select(), poll(), epoll() |
| 비동기 I/O | 완료 시 통지 | aio_read(), io_uring |