본문 바로가기
Computer Science/컴퓨터 구조

[컴퓨터 구조] ep8) 입출력장치(I/O)

by 클레어몬트 2024. 3. 1.

이번 절에서는 장치 컨트롤러장치 드라이버라는 개념을 통해 다양한 외부 입출력장치가 컴퓨터 내부와 어떻게 연결이 되고 소통하는 지를 알아보겠다 참고로 이번 장에서 언급하는 입출력장치에는 보조기억장치도 포함된다 (보조기억장치가 컴퓨터 내부와 정보를 주고받는 방식은 입출력장치와 크게 다르지 않다)
 
 
장치 컨트롤러에 대해 알아보기 전에 먼저 I/O를 다루기 까다로운 이유 2가지를 알아야 한다
1. I/O에는 종류가 너무 많다

이 말은 곧 규격이 너무 많다는 것과 같다
비유하자면 CPU와 메모리가 한국어를 사용하지만, 프린터는 영어, 스피커는 중국어, 모니터는 일본어를 사용하는 상황과 같다
 
2. 보통 CPU와 메모리의 데이터 전송률은 높지만 I/O의 데이터 전송률은 낮다

여기서 전송률(transfer rate)란 데이터를 얼마나 빨리 교환할 수 있는지를 나타내는 지표이다
(컴퓨터 네트워크때 또 배운다)
 
이러한 문제들을 해결해주는 게 바로 장치 컨트롤러의 역할이다
ㅇ장치 컨트롤러 (Device Controller) = 입출력 제어기 = 입출력 모듈

장치 컨트롤러는 3가지의 역할이 있다
1. CPU와 I/O간의 통신 중개 - 번역가 역할(1.규격화 문제 해결)
2. 오류 검출 - 에러 체크
3. 데이터 버퍼링(2.전송률 문제 해결)
 
 
(중요!!) 여기서 데이터 버퍼링이란?

버퍼링은 버퍼라는 임시 저장 공간에 데이터를 저장하는 작업이다 따라서 이와 같은 방법을 통하여 전송률이 높은 장치와 낮은 장치 사이에 주고받는 데이터를 버퍼에 저장하여 전송률을 비슷하게 맞춘다
쉽게 말해 버퍼링은 '버퍼에 데이터를 조금씩 모았다가 한꺼번에 내보내거나, 데이터를 한 번에 많이 받아 조금씩 내보내는 방법'
 
 
이번에는 장치 컨트롤러의 간략화된 내부 구조를 살펴보자

장치 컨트롤러의 간략화된 내부 구조

 
실제로는 복잡하지만 우리가 기억해야 하는 것은 데이터 레지스터, 상태 레지스터, 제어 레지스터 3가지다
상태 레지스터와 제어 레지스터는 하나의 레지스터(상태/제어 레지스터)로 사용되기도 한다
 
데이터 레지스터: 버퍼역할(데이터가 너무 많으면 레지스터 대신 RAM을 사용)
상태 레지스터: 상태 정보 저장
제어 레지스터: 제어 정보와 명령 저장
 
이 레지스터들에 담긴 값들은 버스를 타고 CPU나 다른 I/O로 전달되기도 하고, 장치 컨트롤러에 연결된 I/O에 전달된다
 
 
 
ㅇ장치 드라이버 (Device Driver): 장치 드라이버의 동작을 감지하고 제어

드라이버는 메모리에 적재되어 있다

 
장치 드라이버는 "프로그램"이다 (실행과정에서 메모리에 저장)
장치 컨트롤러가 I/O를 위한 하드웨어적 통로라면, 장치 드라이버는 I/O를 위한 소프트웨어적 통로이다
 
 
드라이버를 인식하고 실행하는 건 운영체제가 맡아서 한다

운영체제가 드라이버를 기본으로 제공하는 것도 있지만, 그 회사의 홈페이지에서 따로 드라이버를 다운받아야 하는 경우도 많다 e.g. 오디오 인터페이스(오인페) 드라이버, 마우스 드라이버
 
 
 
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

장치 컨트롤러와 CPU가 정보를 주고받는 데에는 3가지 입출력 방법이 있다
1. 프로그램 입출력
2. 인터럽트 기반 입출력
3. DMA 입출력
 
 
 
1. 프로그램 입출력(Programmed I/O): 프로그램 속 명령어로 I/O(장치 컨트롤러)를 제어
상황) 메모리의 정보를 HDD에 백업 = HDD에 새로운 정보 쓰기

 
 
이렇듯 프로그램 입출력 방식은 CPU가 장치 컨트롤러의 레지스터 값을 읽고 씀으로써 진행이 된다
그렇다면 CPU가 이 레지스터들(입출력장치의 주소)을 어떻게 인식하고 알까? 그러니까
⒜ 프린터 컨트롤러의 상태 레지스터를 읽어라
⒝ 프린터 컨트롤러의 데이터 레지스터에 100을 써라
⒞ 키보드 컨트롤러의 상태 레지스터를 읽어라
⒟ 하드 디스크 컨트롤러의 데이터 레지스터에 'a'를 써라
이런 명령어들이 어떻게 명령어로 표현되고 어떻게 메모리에 저장될까? 여기에는 크게 2가지 방식이 있다
 
① 메모리 맵 입출력: 메모리를 위한 주소공간과 I/O를 위한 주소공간을 하나의 주소공간으로 간주하는 방식

 
메모리와 I/O에 같은 접근 명령어 사용이 가능하다
 
 
② 고립형 입출력: 메모리를 위한 주소공간과 I/O를 위한 주소공간을 분리하는 방식

(입출력 읽기/쓰기 선을 활성화시키는) I/O 전용 명령어를 사용한다
 
 

메모리 맵 입출력과 고립형 입출력 차이점 정리

 
 
 
 
2. 인터럽트 기반 입출력(Interrupt-Driven I/O): 비동기 인터럽트(하드웨어 인터럽트) by I/O의 장치 컨트롤러

 
ep3의 인터럽트 파트를 먼저 복습하고 오자 https://claremont.tistory.com/9

 

[컴퓨터 구조] ep3) CPU

컴퓨터의 두뇌 CPU == 프로세서 에 대해서 자세히 알아보자 CPU(Central Processing Unit) = ALU + 제어장치 + 레지스터 ㅇALU(Arithmetic Logic Unit) 산술연산장치 ALU는 플래그를 내보낸다 아래의 표를 보자 이 플

claremont.tistory.com

ㅁ하드웨어 인터럽트의 처리순서ㅁ
1. 입출력장치(I/O)가 CPU에 인터럽트 요청신호(req msg)를 보낸다
2. CPU는 실행사이클이 끝나고 명령어를 fetch하기 전에 항상 인터럽트 여부를 확인한다
3. CPU가 인터럽트 요청신호(req msg)를 확인하고 인터럽트 플래그를 통해서 현재 인터럽트를 받아들일 수 있는 상황인지 확인한다
4. 인터럽트를 받아들일 수 있다면 CPU는 지금까지의 작업을 스택에 백업시킨다
5. CPU는 인터럽트 벡터를 참조하여 인터럽트 서비스 루틴(ISR)을 실행한다
6. 인터럽트 서비스 루틴이 끝나면 스택에 백업해 둔 작업을 복구하여 다시 실행을 재개한다
 
입출력장치에 의한 하드웨어 인터럽트는 정확히 말하면 입출력장치가 아닌 장치 컨트롤러에 의해 발생한다
그렇다면 여러 I/O에서 인터럽트가 동시에 발생한 경우(다중 인터럽트)에는 어떡할까?

 
우선순위를 반영하여 다중 인터럽트를 처리하는 방법에는 여러 가지가 있지만, 많은 컴퓨터에서는 프로그래머블 인터럽트 컨트롤러(이하 PIC)를 사용한다

PIC(Programmable Interrupt Controller)

 
PIC란 하드웨어 인터럽트 요청들의 우선순위를 판별한 뒤 CPU에 알려주는 장치이다

 
 
 
PIC의 다중 인터럽트 처리 과정을 조금 더 정확하게 알아보자
 
ㅁ하드웨어 인터럽트의 처리순서ㅁ
1. PIC가 장치 컨트롤러에서 인터럽트 요청신호(req msg)들을 받아들인다
2. PIC는 인터럽트 우선순위를 판단한 뒤 CPU에 처리해야 할 인터럽트 요청 신호를 보낸다
3. CPU는 PIC에 인터럽트 확인 신호를 보낸다
4. PIC는 데이터 버스를 통해 CPU에 인터럽트 벡터를 보낸다
5. CPU는 인터럽트 벡터를 통해 인터럽트 요청의 주체를 알게 되고, 해당 장치의 인터럽트 서비스 루틴(ISR)을 실행한다

 
 
 
일반적으로는 PIC를 2개 이상 계층적으로 구성한다, 이렇게 PIC를 여러 개 사용하면 훨씬 더 많은 하드웨어 인터럽트를 관리할 수 있기 때문이다

PIC의 계층적 구성

 
NMI(Non-Maskable-Interrupt): 막을 수 없는 인터럽트 e.g. 정전, 하드웨어 고장
 
 
추가) 인터럽트와 자주 비교되고 반대되는 개념 중 하나가 바로 폴링(Polling)이다
폴링은 I/O의 상태가 어떤지, 처리할 데이터가 있는지 주기적으로 확인한다 따라서 인터럽트에 비해 CPU 부담이 높다(인터럽트는 CPU가 인터럽트 요청을 받기 전까지 온전히 다른 일에 집중할 수 있기 때문)
 
 
 
 
3. DMA(Direct Memory Access) 입출력: 메모리와 I/O가 다이렉트로 데이터를 주고받는다(CPU를 거치지 않는다) by DMA 컨트롤러
앞의 두 가지 방법은 모두 CPU가 크게 관여했지만 이 방법은 다르다 CPU의 역할을 DMA 컨트롤러가 대신해준다

 
CPU는 오로지 입출력의 시작과 끝에만 관여한다 (CPU의 작업부담 ↓)

간단한 작업이 아닌 복잡한 작업에 주로 사용되며 3가지 방법 중 제일 효율적이다 (대용량 입출력에 가장 적합)

 
 

하지만 시스템 버스는 동시에 사용이 불가능하다 ㅠㅠ (공용자원)
그래서 DMA 컨트롤러는 CPU가 시스템 버스를 이용하지 않을 때마다 조금씩 이용하거나, CPU가 일시적으로 시스템 버스를 이용하지 않도록 허락을 구하고 시스템 버스를 집중적으로 이용한다

 
CPU 입장에서는 마치 버스에 접근하는 주기를 도둑맞는 느낌일 것이다, 그래서 이러한 DMA의 시스템 버스 이용을 사이클 스틸링(cycle stealing)이라 부른다
 
 
 
이렇게 시스템 버스를 이용하기 너무 치열해서 나온 것이 입출력 버스이다
ㅇ입출력 버스: 대부분의 I/O(장치 컨트롤러)들은 시스템 버스가 아닌 입출력 버스와 연결

e.g. PCI 버스, PCIe 버스(PCI Express)
 
 
 
참고) 그리고 이후에는 입출력 전용 CPU가 나오게 되었다

 
 e.g. 입출력 프로세서(IOP), 입출력 채널
 
 
 
(추가지식) I/O를 지원하기 위한 유명한 외부 인터페이스 표준
- USB(Universal Serial Bus): "삼지창" USB-A, USB-B, USB-C 타입이 있다 (우리가 흔히 말하는 핸드폰 충전 C타입이 이 USB-C 타입이다)
- Thunderbolt(썬더볼트): 애플과 인텔이 공동으로 개발
- PCI Express [PCIe]: 다양한 유형 및 속도의 주변장치들을 접속하기 위한 고속 버스 시스템
Ethernet(이더넷): 유선 네트워크 기술
Wi-Fi(와이파이): 무선 인터넷 액세스 기술
 
 
 
 
 
 
참고 및 출처: 컴퓨터시스템구조론(William Stallings), 혼공컴운(강민철)