/ #기타

입출력장치

장치 컨트롤러(Device Controller)

입출력장치는 하드디스크, 마우스, 모니터 등과 같이 컴퓨터 외부에 연결되어 CPU와 정보를 교환할 수 있는 장치입니다.

입출력 장치는 종류가 다양하기 때문에 CPU와 정보를 주고 받는 방식을 규격화하기 어렵습니다. 또한 CPU에 비하여 데이터 전송률이 낮기 때문에 CPU와 직접적으로 통신하게 되면 CPU의 성능이 좋더라도 이를 활용할 수 없게 됩니다. 이러한 문제를 해결하기 위한 하드웨어를 장치 컨트롤러(Device Controller)라고 합니다.

하드디스크의 장치 컨트롤러

img098

장치 컨트롤러는 CPU와 입출력장치 간의 통신을 중개하여 각 장치들을 규격화 해주며, 오류를 검출하고 버퍼링을 통해 CPU와 데이터 전송률을 맞추는 역할을 합니다.

장치 컨트롤러는 데이터 레지스터, 상태 레지스터, 제어 레지스터로 구성되며, CPU는 버스를 통해 장치 컨트롤러에 데이터를 전송합니다.

img099

데이터 레지스터는 CPU와 입출력장치 사이에 주고 받을 데이터를 저장하는 레지스터로, 버퍼 역할을 합니다. 최근에는 입출력 장치와 주고 받을 데이터가 많아졌기 때문에 데이터 레지스터 대신에 RAM을 사용하기도 합니다.

상태 레지스터는 입출력장치가 입출력 작업할 준비가 되었는지, 입출력 작업 완료가 되었는지, 입출력장치에 오류가 없는지 등의 상태 정보를 저장하는 레지스터 입니다.

제어 레지스터는 입출력장치가 수행할 내용에 대한 제어 정보를 저장하는 레지스터 입니다.

장치 드라이버(Device Driver)

장치 드라이버(Device Driver)는 장치 컨트롤러의 동작을 감지하고 제어하는 프로그램 입니다.

장치 컨트롤러가 입출력장치를 연결하는 하드웨어라면, 장치 드라이버는 입출력장치를 연결하는 소프트웨어 입니다. 장치 드라이버를 통해 CPU가 입출력장치를 제어할 수 있습니다.

USB 장치 드라이버

img100

요즘은 OS가 장치 드라이버를 자동으로 설치해주는 경우가 많은데, 이전에는 프린터를 컴퓨터에 연결하여 사용하려면 해당 프린터에 대한 프린트 드라이버를 설치해야 했습니다. 장치 드라이버가 설치되지 않는다면 CPU가 프린터를 동작시키는 방식을 모르기 때문에 해당 프린터를 사용할 수 없게 됩니다. 즉, 장치 드라이버를 인식하고 실행하는 주체는 운영체제(OS) 입니다.

입출력 방식

입출력장치가 CPU와 정보를 교환하는 방식에는 프로그램 입출력, 인터럽트 기반 입출력, DMA 입출력이 있습니다.

프로그램 입출력(Programmed Input/Output, PIO)

프로그램 입출력(Programmed Input/Output, PIO)은 프로그램 명령어를 통해 장치 컨트롤러를 제어하는 방식입니다. CPU에서 명령어를 전송한 후 입출력장치의 상태를 주기적으로 확인하여 데이터 송수신을 제어합니다.

예를 들어 메모리에 저장된 정보를 하드디스크에 저장한다고 한다면 CPU는 쓰기 명령어를 전송하고 상태 레지스터의 확인하고 입출력 장치가 사용가능하다면 데이터를 전송합니다.

하드디스크 쓰기 제어

img101

아래와 같이 주기적으로 상태 레지스터를 확인하는 과정을 폴링(Polling)이라고 하며, 그러므로 프로그램 입출력 방식을 폴링 방식이라고도 합니다.

폴링 순환

img102

이 입출력 방식은 가장 간단하고 최소의 하드웨어를 필요로 하지만, 반복적으로 입출력장치의 상태를 점검하여 CPU의 효율을 저하시키키며 입출력이 완료될 때까지 CPU가 동작하지 못한다는 단점이 있습니다.


프로그램 입출력 방식은 CPU가 입출력장치에 접근하는 방식에 따라 메모리 맵 입출력고립형 입출력으로 나눌 수 있습니다.

메모리 맵 입출력(Memmory-mapped I/O)

메모리 맵 입출력(Memmory-mapped I/O)은 메모리에 접근하기 위한 주소 공간과 입출력장치에 접근하기 위한 주소 공간을 하나의 주소공간으로 취급하여 접근하는 방식입니다.

메모리의 일부 공간을 입출력 포트에 할당하여 메모리 주소 공간이 축소되지만, 메모리에 접근하는 명령어와 입출력장치에 접근하는 명령어가 동일하기 때문에 CPU 로직이 단순해집니다. 주로 ARM 계열의 RISC에서 사용하며, LOAD나 STORE 명령을 통해 접근할 수 있습니다.

고립형 입출력(Isolated I/O)

고립형 입출력(Isolated I/O)은 메모리에 접근하기 위한 주소 공간과 입출력장치에 접근하기 위한 주소 공간을 분리하는 입출력 방식입니다.

입출력장치에 접근하기 위한 별도의 명령어가 필요하고 CPU 로직이 복잡해지지만, 메모리 주소 공간 전체를 활용할 수 있습니다. 주로 x86 계열의 CISC에서 사용합니다.

인터럽트 기반 입출력(Interrupt-Driven I/O)

인터럽트 기반 입출력(Interrupt-Driven I/O)은 인터럽트를 기반으로 장치 컨트롤러를 제어하는 방식입니다. CPU에서 명령어를 전송하면 장치 컨트롤러에서 명령어를 수행한 후 CPU에 인터럽트 요청 신호를 보냅니다. 인터럽트 요청신호를 받은 CPU는 하던 일을 멈추고 인터럽트 서비스 루틴을 실행합니다.

여러 입출력장치에서 인터럽트가 동시에 발생한 경우 우선순위를 고려하여 우선순위가 높은 인터럽트를 먼저 처리합니다. 우선순위를 반영한 인터럽트를 처리하는 방식에는 여러 방식이 존재하지만 일반적으로 프로그래머블 인터럽트 컨트롤러(Programmable Interrupt Controller, PIC)라는 하드웨어를 사용하여 처리합니다.

PIC

img103

PIC는 장치 컨트롤러와 CPU 사이에서 어떤 인터럽트를 먼저 처리할 것인지를 판단하여 CPU에게 인터럽트 신호를 전송합니타.

img104

PIC는 보통 여러 개를 계층적으로 사용하여 사용하는 경우가 많습니다.

DMA 입출력(Direct Memory Access I/O)

DMA 입출력(Direct Memory Access I/O)은 입출력장치와 메모리가 CPU를 거치지 않고 상호작용할 수 있는 입출력 방식입니다.

프로그램 입출력과 인터럽트 기반 입출력은 입출력장치와 메모리 사이에 전송되는 모든 데이터가 반드시 CPU를 거치게 되어 하드디스크 백업과 같은 대용량 데이터의 전송이 필요하다면 CPU의 부담이 커지게 됩니다. 이를 해결하기 위한 입출력 방식이 DMA 입출력 방식이며, DMA 입출력 방식은 입출력장치가 CPU를 거치지 않고 직접 메모리에 접근할 수 있습니다.

DMA 입출력을 위해서는 시스템 버스에 연결된 DMA 컨트롤러라는 하드웨어가 필요합니다. CPU가 DMA 컨트롤러에 명령어를 보내면 DMA 컨트롤러는 CPU를 대신하여 입출력 작업을 수행하고, 입출력 작업이 끝나면 인터럽트 신호를 통해 CPU에게 입출력 작업이 끝났음을 알립니다. 그동안 CPU는 다른 작업을 할 수 있게 됩니다.

img105 img106 img107

여기서 시스템 버스는 공용 자원이기 때문에 CPU와 DMA 컨트롤러는 동시에 시스템 버스를 사용할 수 없습니다. 그러므로 DMA 컨트롤러는 CPU가 시스템 버스를 사용하지 않을때 조금씩 시스템 버스를 사용하거나 CPU가 일시적으로 시스템 버스를 사용하지 않도록 요청을 보내고 시스템 버스를 사용합니다.

DMA 컨트롤러는 메모리에서 데이터를 가져오기 위해 시스템 버스를 한 번, 장치컨트롤러에 데이터를 전송하기 위해 시스템 버스를 또 한 번 사용하여 총 2번 사용하게 됩니다. 그만큼 CPU가 시스템 버스를 사용하지 못하는 문제가 발생하는데, 이를 해결하기 위해 입출력장치를 입출력 버스(I/O Bus)라는 별도의 버스에 연결하여 사용할 수 있습니다.

img108

예를 들어 그래픽 카드나 SSD를 연결하는 PCIe 슬롯은 입출력 버스와 연결됩니다.

img109