I/O Systems

Kamator0·2026년 6월 6일

I/O Systems

Basic I/O Concepts — I/O 시스템 기본 개념

I/O 시스템의 구성 요소

I/O 시스템은 세 가지 계층으로 구성된다.

계층영문역할
I/O 장치I/O Devices키보드, 디스크, 프린터 등 실제 하드웨어
디바이스 드라이버Device Drivers각 장치를 제어하는 소프트웨어 모듈
I/O 서브시스템I/O Subsystem커널 내부에서 장치 독립적 인터페이스를 제공하는 계층

I/O 서브시스템의 목적

I/O 서브시스템이 존재하는 핵심 이유는 추상화(Abstraction)이다.

  1. 장치별 세부사항 은닉: 커널의 상위 계층(파일 시스템, 가상 메모리 시스템 등)과 애플리케이션 개발자에게 장치의 하드웨어적 차이를 숨긴다.
  2. 통일된 접근 방법 제공: 종류가 다른 수많은 주변 장치를 open(), close(), read(), write(), ioctl() 같은 동일한 시스템 콜로 사용할 수 있게 한다.

계층 구조 (위에서 아래로 갈수록 장치에 특화됨):

+----------------------------------+  <-- Generic (장치 독립적)
|  File System, VM System, etc.    |
+----------------------------------+
|  I/O Subsystem                   |
+----------------------------------+
|  Device Drivers                  |
+----------------------------------+
|  Interrupt Handlers              |
+----------------------------------+
|  I/O Device Hardware             |  <-- Specific Details (장치 종속적)
+----------------------------------+

핵심 포인트: 위로 갈수록 "어떤 장치인지 몰라도 되는" 범용(Generic) 코드이고, 아래로 갈수록 "특정 장치에 맞춘" 전용(Specific) 코드이다. 이 계층 분리 덕분에 새 장치를 추가할 때 드라이버만 작성하면 되고, 커널이나 앱을 수정할 필요가 없다.

Linux의 file_operations 구조체 — 추상화의 실제 구현

Linux에서 I/O 서브시스템의 추상화가 어떻게 실현되는지를 보여주는 핵심 구조체가 file_operations이다.

동작 원리:

  1. 틀(껍데기) 정의: I/O 서브시스템이 file_operations라는 구조체를 정의한다. 이 구조체에는 .open, .read, .write, .ioctl 등의 함수 포인터 슬롯이 있지만, 내용(실제 함수 주소)은 비어 있다.

  2. 드라이버가 슬롯을 채움: 키보드 드라이버(atkbd.ko)가 부팅 시 로드되면, 자신의 함수 주소를 각 슬롯에 등록한다.

    • .open -> atkbd_open() (장치 초기화, IRQ 등록)
    • .read -> atkbd_read() (키 이벤트, 버퍼 반환)
    • .write -> atkbd_write() (LED 켜기, CapsLock 등)
    • .ioctl -> atkbd_ioctl() (키 반복 속도, 레이아웃 설정)
  3. 시스템 콜 경로: 사용자가 read(fd, buf, n)을 호출하면:

    • VFS(Virtual File System)가 fd -> inode -> fops 포인터를 조회
    • 해당 file_operations.read 슬롯에 적힌 주소로 점프
    • 결과적으로 atkbd_read()가 실행됨
App: read(fd, buf, n) 호출
        |
VFS: fd -> inode -> fops 포인터 조회 -> .read 호출
        |
I/O 서브시스템: file_operations 구조체
  +--------+--------+---------+--------+
  | .open  | .read  | .write  | .ioctl |  <-- 함수 포인터 슬롯
  +---+----+---+----+----+----+---+----+
      |        |         |        |
  atkbd_open atkbd_read atkbd_write atkbd_ioctl  <-- 드라이버 함수
        |
키보드 하드웨어 (i8042): IRQ 발생, 포트 0x60 데이터

왜 이런 구조인가?: 이 "함수 포인터 테이블" 패턴은 다형성(Polymorphism)을 C 언어에서 구현한 것이다. C++의 가상 함수 테이블(vtable)과 동일한 원리다. 커널은 "어떤 장치의 read인지" 몰라도, 그냥 .read 슬롯에 적힌 주소를 호출하면 된다.


Exception & Interrupt — 예외와 인터럽트

정의

예외(Exception)인터럽트(Interrupt)는 프로세서의 정상적인 명령어 실행 흐름을 방해(disturb)하여, 특수한 명령어(서비스 루틴)를 실행하도록 프로세서의 주의를 전환시키는 이벤트이다.

Exception (예외) — 내부 이벤트

예외는 프로세서 명령어의 실행에 의해 발생하는 내부 이벤트이다. 즉, CPU가 현재 실행 중인 명령어와 직접적인 인과 관계가 있다.

예외 종류설명
Page Fault Exception접근하려는 페이지가 물리 메모리에 없을 때
Arithmetic Exception0으로 나누기(Division by Zero) 등
TRAP의도적인 예외 (시스템 콜 진입점 등)

"내부 이벤트"라는 점이 핵심: page fault는 MOV 명령어가 특정 주소를 접근하다가 발생한 것이고, division by zero는 DIV 명령어가 실행되다가 발생한 것이다. 모두 CPU가 실행한 명령어가 원인이다.

Interrupt (인터럽트) — 외부 이벤트

인터럽트는 프로세서 명령어의 실행과 관련 없는 외부 이벤트이다. 외부 이벤트의 소스는 일반적으로 외부 하드웨어 장치이다.

인터럽트 예시설명
Reset Button임베디드 보드의 리셋 버튼
Device Signal장치에서 생성된 전기적 신호 (키보드 키 입력, 디스크 I/O 완료 등)

Exception vs Interrupt 핵심 차이

구분ExceptionInterrupt
발생 원인CPU가 실행 중인 명령어 (내부)외부 하드웨어 장치 (외부)
동기/비동기동기적 (Synchronous) — 명령어 실행과 동시에비동기적 (Asynchronous) — 언제든 발생 가능
예시Page fault, Division by zero, TRAP키보드 입력, 디스크 완료, 타이머
재현성같은 조건이면 반복 재현 가능외부 이벤트이므로 타이밍이 비결정적

Roles of Interrupts — 인터럽트의 역할

하드웨어 병행성 1: 완료 통지 (Notification)

외부 하드웨어 장치들은 CPU와 병렬로(in parallel) 장치 고유의 작업을 수행할 수 있다. 병행성의 핵심은 장치가 작업을 완료했는지 알아내는 것이다.

예시: 애플리케이션이 프로세서에서 실행 중인데, 디스크 드라이브가 데이터 읽기를 완료하면 외부 인터럽트를 발생시켜 완료를 알린다.

만약 인터럽트가 없다면? CPU가 계속 "끝났어? 끝났어?" 하고 확인해야 한다(Polling). 인터럽트 덕분에 CPU는 다른 일을 하다가 장치가 "끝났어!"라고 알려주면 그때 처리하면 된다.

하드웨어 병행성 2: 서비스 요청 (Service Request)

외부 하드웨어 장치가 CPU에게 서비스를 요청하는 통신 메커니즘으로도 인터럽트가 사용된다.

예시: 키보드를 누르면 키보드 컨트롤러가 인터럽트를 발생시켜 "사용자가 키를 눌렀으니 처리해달라"고 CPU에 요청한다.


PIC and External Interrupts

IRQ Line (Interrupt ReQuest Line)

인터럽트 요청을 발생시키는 각 장치는 IRQ 라인이라는 단일 출력선을 갖는다. 이 선을 통해 "나 인터럽트 요청할게!"라는 전기 신호를 보낸다.

PIC (Programmable Interrupt Controller)

모든 장치의 IRQ 라인은 PIC라는 하드웨어 칩의 입력 핀에 연결된다.

PIC의 역할:

  1. 다수 인터럽트 소스의 우선순위 결정: 여러 장치가 동시에 인터럽트를 요청하면, 가장 높은 우선순위의 인터럽트만 CPU에 전달한다.
  2. CPU의 부담 경감: 인터럽트의 정확한 소스를 판별하는 작업을 PIC가 대신 처리한다.

PIC의 동작 과정

PIC는 다음 단계를 순서대로 수행한다:

  1. IRQ 라인 감시: 신호가 올라왔는지(raised signal) 계속 모니터링
  2. 신호가 감지되면:
    • 올라온 신호를 벡터(vector)로 변환
    • 변환된 벡터를 PIC의 포트에 저장 -> CPU가 데이터 버스를 통해 읽을 수 있도록
    • 해당 인터럽트를 CPU에 발행(issue)
    • CPU가 PIC 포트에 쓰기를 하여 인터럽트를 확인(acknowledge)할 때까지 대기

벡터(Vector)란?: 인터럽트 번호이다. 예를 들어 키보드는 IRQ 1이고, 이 번호가 벡터 테이블의 인덱스가 되어 해당 ISR(인터럽트 서비스 루틴)의 주소를 찾는다.

Intel 8259 PIC

x86 아키텍처에서 사용된 고전적인 PIC이다. 하나의 8259는 8개의 IRQ 입력을 가지며, 두 개를 캐스케이드(cascade)로 연결하여 총 16개(IRQ 0~15)를 지원했다.

IRQ 0 : Timer        --+
IRQ 1 : Keyboard       |  Master
IRQ 2 : Slave 연결     |  8259
...                     |
IRQ 7                 --+--INT--CPU
                         ^
IRQ 8~15              --+  Slave 8259

현대에는 APIC (Advanced PIC)로 대체되었다. APIC는 멀티프로세서 환경에서 인터럽트를 특정 CPU 코어로 라우팅할 수 있다.


Classification of Interrupts — 인터럽트 분류

Maskable Interrupt (마스크 가능 인터럽트)

소프트웨어에 의해 차단(block)하거나 허용(enable)할 수 있는 인터럽트이다.

  • 예시: 외부 장치가 생성하는 일반적인 인터럽트 (키보드, 디스크 등)
  • CPU의 플래그 레지스터에 있는 IF(Interrupt Flag)를 0으로 설정하면 마스크 가능 인터럽트가 차단된다.

Non-maskable Interrupt, NMI (마스크 불가능 인터럽트)

소프트웨어로 차단할 수 없는 인터럽트이다. 프로세서가 즉시 확인하고 처리한다.

  • 예시: 하드웨어 리셋 예외, 메모리 패리티 오류 등
  • 시스템의 안전과 직결되는 치명적 이벤트에 사용된다.

왜 Non-maskable인가?: 메모리 패리티 오류 같은 건 무시하면 시스템 전체가 망가질 수 있기 때문에, 어떤 상황에서도 반드시 즉시 처리해야 한다.


Exception and Interrupt Priority — 예외 및 인터럽트 우선순위

우선순위 체계

모든 프로세서는 예외와 인터럽트를 정해진 우선순위에 따라 처리한다. 모든 예외와 인터럽트는 OS 스레드보다 높은 처리 우선순위를 갖는다.

  ^ 높은 우선순위 (Absolute System-Wide Priority)
  |
  |  +-------------------------------+
  |  |  Non-maskable Interrupt       |  <-- 최고 우선순위
  |  +-------------------------------+
  |  |  Exceptions                   |
  |  +-------------------------------+
  |  |  Maskable Interrupts          |
  |  +-------------------------------+ --- 하드웨어 제어 경계
  |  |  Thread (높은 우선순위)          |     <-- 커널 제어 경계
  |  |  Thread                       |
  |  |  ...                          |  Thread Priority
  |  |  Thread (낮은 우선순위)          |  (Programmable)
  |  +-------------------------------+
  v 낮은 우선순위

핵심 구분:

  • 하드웨어 제어: NMI > Exceptions > Maskable Interrupts — 이 순서는 하드웨어가 결정하며 OS가 바꿀 수 없다.
  • 커널 제어: 스레드 간 우선순위는 OS 스케줄러가 프로그래밍 가능하다(Programmable).
  • 모든 인터럽트/예외는 어떤 스레드보다도 우선순위가 높다. 따라서 인터럽트가 발생하면 실행 중이던 스레드는 즉시 중단된다.

Exception & Interrupt Handling — 처리 과정

벡터 테이블 (Vector Table)

시스템은 예외/인터럽트 벡터 테이블을 알고 있다. 이 테이블에는 각 벡터 번호에 대응하는 서비스 루틴의 시작 주소가 저장되어 있다.

  • ESR (Exception Service Routine) = Exception Handler: 예외를 처리하는 루틴. 시스템 설치 시 등록.
  • ISR (Interrupt Service Routine) = Interrupt Handler: 인터럽트를 처리하는 루틴. 드라이버 설치 시 등록.

처리 흐름

[인터럽트 경로]
장치 -> PIC Checks -> Interrupt enabled? 
                          | Yes
                    CPU Calculates Vector -> Vector Table에서 ISR 주소 찾기
                                                    |
                                            Memory에서 ISR 실행
                                                    |
                                            원래 실행 지점으로 복귀

[예외 경로]
CPU 내부 이벤트 -> CPU Calculates Vector -> Vector Table에서 ESR 주소 찾기
                                                    |
                                            Memory에서 ESR 실행
                                                    |
                                            원래 실행 지점으로 복귀

인터럽트와 예외의 차이: 인터럽트는 외부에서 전달해서 PIC를 거치고, 예외는 CPU 내부에서 발생하므로 CPU가 직접 벡터를 계산한다.

인터럽트의 상태 (States of Interrupts)

상태영문설명
비활성Disable (Masked)마스킹되어 차단된 인터럽트
대기 중Pending아직 확인(acknowledge)되지 않은 인터럽트. 프로세서가 현재 더 높은 우선순위 인터럽트를 처리 중일 때 발생
활성Active프로세서가 현재 확인하고 처리 중인 인터럽트

Intel Pentium 이벤트

벡터 번호설명
0Divide Error (0으로 나누기)
1Debug Exception
2Null Interrupt (NMI)
3Breakpoint
6Invalid Opcode
8Double Fault
13General Protection Fault
14Page Fault
16Floating-Point Error
18Machine Check
19-31Intel 예약 (사용 금지)
32-255Maskable Interrupts (외부 장치용)

포인트: 벡터 0~31은 Intel이 예외(Exception)용으로 예약했고, 32번부터 255번까지가 외부 장치의 마스크 가능 인터럽트에 할당된다.


Interrupt Priority — 인터럽트 우선순위 세부

필요성

하나의 인터럽트를 서비스하는 동안 다른 인터럽트가 발생할 수 있다. 따라서 서로 다른 종류의 인터럽트에 대한 우선순위 제어가 필수적이다.

우선순위 결정 규칙

  • 높은 우선순위 인터럽트는 낮은 우선순위 인터럽트의 서비스를 선점(preempt)할 수 있다.
  • 각 인터럽트 유형에는 IPL(Interrupt Priority Level)이 할당된다.
  • 예시: 타이머 인터럽트와 네트워크 인터럽트가 동시에 발생하면, IPL이 높은 쪽이 먼저 처리된다.

Interrupt Miss — 인터럽트 누락

정의

ISR이 인터럽트를 비활성화(disable)한 상태에서 너무 오래 실행하면, 그 동안 발생한 다른 인터럽트를 프로세서가 기록하지 못하는 상황이 Interrupt Miss이다.

문제점

  1. 커널 스케줄러 실행 불가: ISR이 모든 시스템 인터럽트를 비활성화하면, 타이머 인터럽트도 차단되므로 스케줄러가 돌아갈 수 없다.
  2. 실시간 스레드 영향: 엄격한 데드라인을 가진 실시간 스레드가 제시간에 실행되지 못할 수 있다.

Interrupt Timing — 인터럽트 타이밍

시간 정의

기호영문의미
T_ATime between interrupts인터럽트 간 시간 간격. 장치의 인터럽트 빈도에 의존
T_BInterrupt Latency인터럽트가 발생한 시점부터 ISR 실행이 시작되기까지의 지연 시간
T_CProcessing TimeISR의 실제 처리 시간
T_DInterrupt Response Time전체 응답 시간. T_D = T_B + T_C

인터럽트 지연(Latency)에 영향을 미치는 요소

  1. 인터럽트 핸들링 초기화 시간: 레지스터 저장, 벡터 조회 등
  2. 더 높은 우선순위 인터럽트가 활성 상태: 현재 처리 중인 고우선순위 인터럽트가 끝날 때까지 대기
  3. 인터럽트 비활성화 구간: 소프트웨어가 인터럽트를 disable 했다가 나중에 re-enable하는 시간

핵심 문제

높은 우선순위 인터럽트의 처리 시간(T_C)이 길면, 낮은 우선순위 인터럽트의 지연(T_B)이 늘어나고, 낮은 우선순위 인터럽트의 누락(miss) 가능성이 증가한다.

이것이 바로 다음 절(Bottom Halves)의 동기이다.


Bottom Halves (Deferring Work) — 하반부 처리

문제 인식

ISR이 오래 실행되면 인터럽트 누락이 발생한다. 그렇다면 ISR을 어떻게 짧게 만들 수 있을까?

해결: 인터럽트 처리를 두 부분으로 분리

구분Top Half (상반부)Bottom Half (하반부)
실행 컨텍스트ISR 컨텍스트 (인터럽트 핸들러)스레드 컨텍스트 (커널 데몬 스레드)
인터럽트 상태일부 또는 전체 인터럽트 비활성화모든 인터럽트 활성화
실행 시점인터럽트 발생 즉시나중에 (deferred)
특징빠르고 간단시간 소모적 작업 처리
하는 일최소한의 긴급 작업만 수행데이터 처리, 프로토콜 처리 등

목표

Bottom half의 핵심 목표는 인터럽트 핸들러의 실행 시간을 최소화하여 인터럽트 누락 가능성을 줄이는 것이다.

동작 흐름

키보드 타이핑
     |
Interrupt Controller -> Processor
     |
    ISR (Top Half)
  - 스캔코드 읽기
  - 이벤트 큐에 삽입
  - 즉시 반환
     |
    Queue: [Req 3][Req 2][Req 1]
     |                    |
Thread 0 (Daemon)    Thread 1 (Daemon)
  - 큐에서 요청 꺼내서 처리 (Bottom Half)

비유: 응급실 접수 데스크(Top Half)에서는 환자 이름만 빠르게 적고, 실제 치료(Bottom Half)는 의사가 나중에 한다. 접수 데스크가 한 환자를 오래 붙잡고 있으면 뒤에 온 응급 환자를 놓칠 수 있다.


Linux 키보드 인터럽트 처리 — 전체 흐름 상세

I/O 포트 주소 공간

CPU에는 두 종류의 주소 공간이 동시에 존재한다:

주소 공간영문범위접근 명령어용도
메모리 주소 공간Memory Address Space가상: 0x0000~0xFFFFFFFFMOV, LOAD, STORERAM, MMIO
I/O 포트 주소 공간I/O Port Address Space0x0000~0xFFFF (64KB 고정)IN, OUT (x86 전용)장치 레지스터

핵심 차이:

  • 메모리 주소는 MMU에 의해 가상화(Virtual -> Physical 변환)된다.
  • I/O 포트 주소는 가상화 없음 — 물리 주소에 직접 매핑된다.
  • x86에서는 IN/OUT 명령어로만 접근 가능하다.

포트 주소란?

포트 주소는 디바이스 컨트롤러의 내부 레지스터 번지이다. 가상 addr 필요 없음

inb(0x60) 실행 시:
1. CPU가 I/O 버스에 주소 0x60을 송출
2. 키보드 컨트롤러(i8042) 내 주소 디코더가 0x60을 받아 자신의 데이터 레지스터를 선택
3. 해당 레지스터에 저장된 스캔코드 값을 버스로 출력
4. CPU가 이 값을 읽어감

i8042 키보드 컨트롤러 내부:
+----------------------------------------------+
|               주소 디코더                      |
|   버스에서 받은 주소(0x60)로                    |
|   어느 레지스터인지 선택                        |
+--------------+--------------+----------------+
| 데이터 레지스터 | 상태 레지스터  | 명령 레지스터   |
| 포트 0x60     | 포트 0x64     | 포트 0x64      |
| 스캔코드 저장   | 버퍼 상태      | LED 제어 등    |
| *inb(0x60)   | inb(0x64)    | outb(0x64)    |
+--------------+--------------+----------------+

키보드 'A' 키 입력의 전체 흐름

[하드웨어]
키보드에서 'A' 키 누름
    |
i8042 컨트롤러: 스캔코드 생성 -> IRQ 1 발생
    |
[Top Half -- ISR]
CPU: 작업 중단, 레지스터 저장 -> ISR 호출
    |
ISR: 포트 0x60에서 스캔코드 읽기 (0x1E)
    |
ISR: 이벤트 큐에 KEY_A 삽입
    |
ISR: CPU 작업 복귀 (수 마이크로초)
    |
[Bottom Half]
키코드 변환: 0x1E -> KEY_A
    |
tty 버퍼 기록: line discipline 처리
    |
wake_up(): 대기 프로세스 깨움
    |
[App]
read()에서 대기 중이던 프로세스 -> 버퍼에서 'a' 읽음 -> read() 반환

Device Hardware — 장치 하드웨어

포트 (Port)

장치가 컴퓨터 시스템과 통신하는 연결 지점이다. 장치는 케이블이나 무선을 통해 전기 신호를 보내며, 포트는 이 신호가 오가는 물리적/논리적 접속점이다.

버스 (Bus)

여러 장치가 공통의 와이어(전선 묶음)를 사용하여 통신하면, 이 연결을 버스라고 한다.

버스 종류영문역할
메모리 버스Memory Bus프로세서와 메모리(또는 메모리 컨트롤러)를 연결
PCI 버스PCI (Peripheral Component Interconnect) Bus프로세서-메모리를 빠른 장치들(그래픽, SCSI 등)에 연결
확장 버스Expansion Bus느린 장치들(키보드, 시리얼 포트 등)을 연결

디바이스 컨트롤러 (Device Controller)

컴퓨터와 주변 장치 사이의 데이터 전송을 제어하는 칩이다.

  • 디스크, 키보드, 프린터 등 모든 장치에 컨트롤러가 필요하다.
  • 컨트롤러는 CPU 보드 위에 있거나, 장치 자체에 내장되어 있다.

디바이스 제어 레지스터 (Device Control Registers)

  • 통상 CPU 외부에 위치 (CPU 보드 또는 디바이스 컨트롤러 내부)
  • 장치를 초기화하고 서비스를 요청하는 데 사용
  • 상위 계층(드라이버)이 이 레지스터에 명령을 기록하여 데이터 전송을 요청 -> 이것을 Device Control이라 한다

Polling & Interrupts — 폴링과 인터럽트

Polling (폴링 / Busy-waiting)

  1. 컨트롤러가 작업 중이면 상태 레지스터의 busy bit를 설정(set)
  2. 준비가 완료되면 busy bit를 해제(clear)
  3. CPU가 상태 레지스터의 busy bit를 반복적으로 읽어서 장치가 서비스 준비가 됐는지 확인
  4. CPU는 커맨드 레지스터의 command-ready bit를 통해 장치에게 명령을 전달

Polling의 문제점

CPU가 상태 레지스터를 계속 확인하는 동안, 다른 유용한 처리가 진행되지 못한다. CPU 시간이 낭비된다.

해결책: Interrupt

하드웨어 컨트롤러가 장치의 서비스 준비가 완료되면 CPU에게 인터럽트를 발생시켜 알린다. CPU는 다른 일을 하다가 인터럽트가 오면 그때 처리하면 된다.

Polling vs Interrupt 비교

비교 항목PollingInterrupt
CPU 활용낮음 (busy-wait으로 낭비)높음 (다른 작업 가능)
응답 속도폴링 주기에 의존즉각적
구현 복잡도단순복잡 (벡터 테이블, ISR 등 필요)
적합한 상황매우 빈번한 I/O, 짧은 대기대부분의 I/O 장치

DMA I/O — 직접 메모리 접근

Programmed I/O (PIO) — 프로그래밍된 I/O

CPU가 직접 상태 비트를 폴링하여 I/O 요청 완료를 확인하고, 1바이트씩 데이터를 컨트롤러 레지스터에 공급하는 방식이다.

PIO의 문제점

대량 데이터 전송을 하는 장치에서, 프로세서가 반복적으로 데이터를 레지스터에 넣는 것은 CPU 자원의 낭비이다. CPU는 연산에 쓰여야 하는데, 단순 데이터 복사에 묶여 있게 된다.

DMA (Direct Memory Access) — 직접 메모리 접근

핵심 아이디어: 폴링과 데이터 전송 같은 작업을 DMA 컨트롤러라는 전용 프로세서에게 떠넘겨서 CPU의 부담을 줄인다.

DMA 동작 과정 (5단계)

[Step 1] Device driver가 "drive 2의 데이터를 메모리 주소 x의 버퍼로 전송하라"는 
         명령을 받음

[Step 2] Device driver가 drive controller에게 "c바이트를 주소 x의 버퍼로 전송하라"고 지시
         (소스 주소, 목적지 주소, 전송 길이를 DMA 컨트롤러에 설정)

[Step 3] Drive controller가 DMA 전송을 개시

[Step 4] DMA controller가 바이트를 메모리 주소 x의 버퍼로 전송
         - 메모리 주소를 증가시키고 (x -> x+1 -> x+2 -> ...)
         - 카운터 c를 감소시킴 (c -> c-1 -> ... -> 0)
         - 이 동안 CPU는 다른 작업을 자유롭게 수행

[Step 5] c = 0이 되면, DMA controller가 CPU에 인터럽트를 발생시켜 전송 완료를 알림
           +---------+              +--------------+
           |   CPU   |              | DMA Controller|
           +----+----+              +------+-------+
                |                         |
    ============+=========================+===========  (시스템 버스)
                |         Polling         |
                v                         v
          +----------+             +----------+
          |   Main   |             |   I/O    |
          |  Memory  |             |  Device  |
          +----------+             +----------+

          DMA Controller가 장치<->메모리 간 데이터를 직접 전송
          CPU는 전송 완료 인터럽트만 받으면 됨

PIO vs DMA 비교

비교 항목PIO (Programmed I/O)DMA I/O
데이터 전송 주체CPUDMA Controller
CPU 부담매우 높음 (1바이트마다 CPU 개입)낮음 (초기 설정 + 완료 인터럽트만)
적합한 상황소량 데이터 전송대량 데이터 전송 (디스크, 네트워크 등)
전송 중 CPU 상태전송에 묶여 있음다른 작업 수행 가능

핵심 개념 정리 (시험 대비)

개념 간 관계도

사용자 앱: read(fd, buf, n)
     | 시스템 콜
VFS -> file_operations -> .read 슬롯
     | 드라이버 함수 호출
Device Driver -> 장치 레지스터에 명령 기록
     |
장치가 작업 수행 (CPU와 병렬)
     |
+- Polling: CPU가 상태 레지스터 반복 확인 (비효율)
+- Interrupt: 장치가 완료 시 IRQ 발생 -> PIC -> CPU -> ISR
+- DMA: DMA Controller가 데이터 전송 -> 완료 시 인터럽트
     |
ISR (Top Half): 최소 작업만 수행, 요청을 큐에 넣음
     |
Bottom Half: 스레드 컨텍스트에서 나머지 처리
     |
프로세스 깨움 -> read() 반환

빈출 키워드 요약

키워드한 줄 정의
file_operationsI/O 서브시스템이 정의한 함수 포인터 테이블 — 드라이버가 구현을 채움
ExceptionCPU 명령어 실행에 의해 발생하는 동기적 내부 이벤트
Interrupt외부 장치에 의해 발생하는 비동기적 외부 이벤트
PIC다수의 IRQ를 우선순위에 따라 관리하는 하드웨어
Maskable Interrupt소프트웨어로 차단/허용 가능한 인터럽트
Non-maskable Interrupt차단 불가능, 즉시 처리 필수인 인터럽트
Vector Table벡터 번호 -> ISR/ESR 주소 매핑 테이블
Interrupt Latency (T_B)인터럽트 발생 -> ISR 시작까지의 지연 시간
Interrupt MissISR이 너무 오래 실행되어 다른 인터럽트를 놓치는 현상
Top HalfISR에서 최소한의 긴급 작업만 수행하는 부분
Bottom Half스레드 컨텍스트에서 나머지 작업을 처리하는 부분
PollingCPU가 상태 레지스터를 반복 확인하는 방식
DMACPU 대신 데이터 전송을 수행하는 전용 컨트롤러
I/O Port Address Space메모리 주소 공간과 별개인, 장치 레지스터용 주소 공간 (x86)
Device Controller컴퓨터와 주변 장치 간 데이터 전송을 제어하는 칩
IRQ Line장치가 인터럽트를 요청하는 단일 출력선
IPLInterrupt Priority Level, 인터럽트 유형별 우선순위

0개의 댓글