강민철님의 "혼자 공부하는 컴퓨터 구조+운영체제"을 기반으로 학습한 게시물입니다.
📕 목차
1. 장치 컨트롤러와 장치 드라이버
2. 다양한 입출력 방법
1. 장치 컨트롤러와 장치 드라이버
📌 장치 컨트롤러 (Device Controller)
- 입출력장치는 다루기가 까다롭다.
- 입출력 장치의 종류가 너무 많다.
- Character Device : 키보드, 사운드 카드, 프린트 등
- Block Device : 저장 장치(Disk, RAM, CD·ROM 등)
- Network Device : packer과 같은 추상적인 개념
- 장치마다 속도, 데이터 전송 형식 등이 다양해서 규격화가 어렵다.
- 일반적으로 CPU, Memory와 입출력장치의 데이터 전송률의 차이가 다르다.
- 전송률(transfer rate) : 데이터를 얼마나 빨리 교환할 수 있는지를 나타내는 지표
- CPU는 1초에 수많은 데이터를 처리하지만, 대부분의 I/O Device는 그보다 훨씬 느리다.
- 입출력 장치의 종류가 너무 많다.
- I/O Device는 컴퓨터에 직접 연결되지 않고, Device Controller를 통해 연결된다.
- 입출력 제어기, 입출력 모듈 등으로도 불린다.
- 모든 I/O Device는 각자의 Device Controller를 통해 컴퓨터 내부와 정보를 주고 받는다.
- Device Controller는 하나 이상의 I/O Device와 연결되어 있다.
- Device Controller가 일종의 번역가 역할을 수행하여 정보의 규격화 문제를 해소할 수 있다.
- Devcie Controller의 역할
- CPU와 입출력 장치 간의 통신 중개
- 오류 검출
- 데이터 버퍼링
- 버퍼링(buffering) : 장치 사이에 임시 저장 공간인 버퍼(buffer)를 두어 전송률을 비슷하게 맞춘다.
- CPU와 I/O Device 사이의 전송률 차이를 완화한다.
- Device Controller 내부
- 데이터 레지스터(data register)
- buffer 역할을 수행하며, CPU와 주고받을 데이터가 담긴다.
- 주고받는 데이터가 많은 I/O Device는 RAM을 대신 사용하기도 한다.
- 상태 레지스터(status register)
- I/O Device 입출력 작업 준비 상태, 완료 상태, 오류 점검 정보가 담긴다.
- 제어 레지스터(control register)
- I/O Device가 수행할 내용에 대한 제어 정보와 명령을 저장한다.
- 데이터 레지스터(data register)
📌 장치 드라이버 (Device Driver)
- Device Controller의 동작을 감지하고 제어하는 장치 구동자 역할
- User Application에서 interface를 통해 device에 접근 가능하도록 하는 program
- device management를 위한 interface 구현이 필요한 함수의 집합 및 자료 구조
- 규격화된 표준 서비스 제공을 위해 kernel의 일부로 만들어진다.
- Hardware에 독립적인 Program을 만들 수 있게 돕는다.
- 운영체제가 기본적으로 제공하는 Device Driver도 있고, Device 제작자가 따로 배포하기도 한다.
2. 다양한 입출력 방법
Device Controller와 CPU가 정보를 주고받는 방법에는 크게 3가지가 있다.
- 프로그램 입출력
- 인터럽트 기반 입출력
- DMA 입출력
📌 프로그램 입출력(Programmed I/O)
- 기본적으로 프로그램 속 명령어로 I/O Device를 제어한다.
예를 들어, HDD에 데이터를 저장할 때 과정이다.
- CPU가 control register에 쓰기 명령을 보낸다.
- HDD Controller가 HDD 상태를 확인하여, 가능하다면 준비 완료 상태를 표시한다.
- CPU가 status register를 주기적으로 읽어 완료 상태를 확인하면, 백업할 메모리 정보를 data register에 쓴다.
- 만약 쓰기 작업이 덜 끝났다면, 1번 과정부터 반복한다.
그렇다면 CPU는 어떻게 Device Controller의 register 주소를 모두 알 수 있는 걸까?
1️⃣ 메모리 맵 입출력(Memory-mapped I/O)
- Memory와 I/O Device에 접근하기 위한 주소 공간을 하나의 주소 공간으로 간주한다.
- ex. 1,024개 주소를 표현 가능하다면 절반은 memory addr, 절반은 i/o controller addr을 표현한다.
- I/O가 차지하는 만큼 Memory 용량이 줄어든다.
- CPU 입장에서는 Memory나 I/O나 동일한 외부기기로 간주되므로, access하기 위한 명령어가 다를 필요가 없다.
- CPU 입장에선 주소 정보만 관심이 있고, 해당 주소가 Memory인지 I/O Device 주소인지 관심조차 없다.
- 특징
- Load나 Store 명령에 의해 수행된다.
- 대표적인 프로세서로 ARM, MIPS, PowerPC, M68K가 있다.
- 포트 입출력 구현 시, 복잡성이 사라져 CPU 내부적으로 로직이 덜 필요하다.
- 저렴하고, 빠르면서 쉬운 CPU를 만들 수 있다. (Embedded 시스템 구현 시 장점)
- 주소와 데이터 버스를 많이 사용하게 되어, main memory에 접근하는 것보다 매핑된 장치에 접근하는 것이 느리다.
- 사용시 컴파일러 최적화 방지를 위해 I/O 영역 변수를 volatile 타입으로 선언해야 한다.
- I/O 영역은 Non-cahceable로 설정해야 한다. (cache memory 접근 시, 변경 내용을 가져올 수 없을 수도 있다.)
2️⃣ 고립형 입출력(isolated I/O)
- Memory와 I/O Device 주소 공간을 분리하는 방법이다.
- I/O Device를 사용한다고 Memory 용량이 감소하지 않는다.
- CPU 입장에서는 Memory와 I/O Device를 구분하기 위해 RD, WR 신호 외에 I/O 접근을 위한 신호가 필요하다.
- Memory에 대한 접근은 Load / Store에 의해 수행되고, I/O는 Input / Output 명령에 의해 수행된다.
- 특징
- 주로 Intel 계열 프로세서에 사용된다.
- Addressing 능력이 제한된 CPU 사용 시 빛을 발한다.
📌 인터럽트 기반 입출력(Interrupt-Driven I/O)
- Device Controller에 의해 발생되는 HW Interrupt로 신호를 보낸다.
- Interrupt가 발생하면 그에 맞는 ISR을 호출한다.
✒️ 폴링(Polling)
CPU가 주기적으로 Device Controller의 status register를 확인하는 방식이다.
일을 맡겨놓은 채로 온전히 다른 일을 수행하지 못하기 때문에, Interrupt 방식보다 CPU 부담이 크다.
- 여러 Interrupt 신호가 동시다발적으로 들어오는 경우 우선순위에 따라 처리한다.
- Interrupt를 처리하는 도중에도 더 높은 우선순위 Interrupt가 발생하면 그 일을 처리한다.
- NMI(Non-Maskable Interrupt) : Interrupt bit를 비활성화해도 무시할 수 없는 Interrupt
🟡 프로그래머블 인터럽트 컨트롤러 (PIC; Programmable Interrupt Controller)
- 여러 Device Controller에 연결되어 HW Interrupt 우선순위를 판별한 뒤, CPU에게 처리해야 할 작업을 알려주는 장치
- PIC가 Device Controller로 부터 Interrupt를 받는다.
- 우선 순위를 판단하여 CPU에 처리해야 할 Interrupt를 보낸다.
- CPU가 PIC에 Interrupt 확인 신호를 보낸다.
- PIC가 데이터 버스를 통해 CPU에 Interrupt vetor를 보낸다.
- CPU가 해당 장치의 ISR을 실행한다.
- PIC의 각 핀은 CPU에 Interrupt 요청을 보낼 수 있는 약속된 HW가 연결된다.
- EX. 첫 번째 핀은 타이머 인터럽트를 받음, 세 번째 핀은 키보드 인터럽트를 받음, ...
- PIC를 계층화하여 더 많은 Hardware Interrupt를 관리할 수도 있다.
- 가장 높은 우선순위를 갖는 NMI 같은 경우엔 우선 순위 판단이 불필요하다.
📌 DMA(Direct Memory Access) 입출력
- 이전 두 방식과 다르게 CPU I/O 연산의 부담을 줄이는 방법
- HDD 백업과 같은 대용량 데이터를 옮길 때, CPU를 거치지 않고도 상호작용하는 방법
- 시스템 버스에 연결되어 Memory에 직접 접근하는 DMA Controller가 필요하다. (HW)
🟡 DMA 입출력 과정
- CPU는 DMA Controller에 HDD 주소, 수행할 연산, 백업할 내용이 저장된 Memory 주소 등의 정보와 함께 I/O 작업을 명령한다.
- CPU는 그동안 다른 프로그램을 수행한다.
- CPU는 처음과 마지막 작업에 대한 명령만 수행하면 된다.
- DMA Controller는 CPU 대신 Device Controller와 상호작용하여 I/O 작업을 수행한다.
- 이때 DMA Controller는 필요한 경우 Memory에 직접 접근하여 정보를 읽거나 쓴다.
- I/O 작업이 끝나면 DMA Controller는 CPU에 Interrupt를 걸어 작업이 끝났음을 알린다.
✒️ 사이클 스틸링(Cycle Stealing)
CPU와 DMA Controller는 둘 다 시스템 버스를 사용하는데, 이는 공용 자원이라 동시에 사용할 수 없다.
따라서 DMA Controller는 CPU가 이용하지 않을 때마다 조금씩 이용하거나, CPU에게 일시적으로 허락을 구하고 점유하여 이용한다.
CPU 입장에선 버스에 접근하는 주기를 도둑 맞는 기분이 들어서 cycle stealing이라고 한다는데, 애초에 니가 짬 때린 거잖아...
🟡 입출력 버스(input/output bus)
- 하나의 System Bus를 이용하면 CPU가 그만큼 일을 할 수 없다.
- 입출력 버스를 이용해 DMA Controller와 Device Controlle를 별도의 bus에 연결하면 된다.
- PCI(Periphearl Component Interconnect) 버스, PCI Express(PCIe) 버스 등
- 실제로 대다수의 I/O Device들은 System bus가 아닌 input/output bus에 연결된다.
🟡 입출력 프로세서(IOP; Input/Output Processor)
- DMA가 있어도 대부분의 I/O 명령 인출, 해석, 실행은 CPU가 담당했었다.
- 최근에는 Memory 직접 접근은 물론, I/O 명령 인출·해석·실행까지 하는 I/O 전용 CPU가 만들어졌다.
- 입출력 채널(Input/Output Channel)이라고도 부른다.
- I/O Device 내부에 별도의 CPU가 포함되어 있다.
- CPU가 I/O Channel에 memory에 저장된 특정 명령어 수행을 지시하면, 연산 수행 결과만을 Interrupt로 CPU에 알린다.