## 목차 ##

  1. 시스템 버스
  2. 버스 중재
  3. I/O장치의 접속
  4. 인터럽트를 이용한 I/O
  5. DMA를 이용한 I/O


## 0. Intro ##

이번 챕터에서는 CPU, 메모리, 보조저장장치 및 I/O장치들을 서로 접속할 수 있게 해주는 시스템 버스와 그 매커니즘, 그리고 시스템 버스의 성능 향상을 위해 사용되는 직접 메모리 액세스(DMA)에 대해 알아본다.


## 1. 시스템 버스 ##

시스템 버스는 컴퓨터를 구성하는 요소들 사이에 데이터 전송을 할 수 있는 통로이다.



(1) 시스템 버스 조직

computer_system_bus

컴퓨터를 구성하는 요소들은 시스템 버스를 통해 프로그램 코드, 데이터, 제어명령 등을 교환하며 CPU가 클록 신호를 여기로 내보낸다. 물리적으로 전기신호를 전송하므로 도체로 된 선들로 만들어진다. 선들의 수는 CPU가 발생시키는 주소 비트 수, 워드, 제어 신호의 수에 따라 결정된다. 2챕터에서 말했듯이 시스템 버스는 크게 세 가지로 구분된다.



(a) 데이터 버스(data bus)

시스템 사이의 데이터 전송을 위한 버스이다. 워드(word), 즉 CPU가 한 번에 처리하는 비트 수만큼의 버스선이 필요하다. 데이터는 CPU와 메모리, I/O장치들 사이 양방향으로 발생하므로 데이터 버스는 양방향(bidirectional) 전송을 지원할 수 있어야한다.



(b) 주소 버스(address bus)

CPU가 메모리, 기타 I/O 장치들에 쓰기/읽기를 할 때 메모리의 주소지정을 위한 버스이다. 주소는 CPU가 발생시키기 때문에 주소 버스는 단방향(unidirectional) 전송통로이다.



(c) 제어 버스(control bus)

기억장치 및 I/O장치에 대한 쓰기/읽기 신호들을 내보내는 버스이다.



시스템 버스의 사용 주체가 되는 요소를 버스 마스터(bus master)라고 한다. CPU 및 I/O장치의 제어기등이 버스 마스터가 될 수 있다. 동기식 버스(synchronous)에서는 메모리 역시 버스 마스터가 될 수 있다. 시스템 버스는 모든 요소들이 공유하는 자원이며 한 번에 하나의 버스 마스터만 버스를 점유할 수 있다. 여러 마스터들이 동시에 버스를 사용하고자 하면 순서를 지정해주는 버스 중재(bus arbitration)가 일어난다.

버스 중재를 위해서는 아래의 제어 신호들이 필요하다.

(a) 버스 요구(bus request) : 버스 마스터의 버스 사용 요구
(b) 버스 승인(bus grant) : 버스 마스터에게 버스 사용 허가
(c) 버스 사용중(bus busy) : 다른 마스터에 의해 버스 사용중

버스 중재를 위한 신호선들의 집합을 버스 중재 버스라고 따로 구분하기도 한다. 버스 중재에 대해서는 잠시 후에 자세히 설명한다.

키보드, 마우스등은 비동기식으로 인터럽트를 통해 동작한다. 명령어 인출-실행 단계가 끝나면 I/O장치 제어기들의 인터럽트 비트 레지스터를 확인하여 인터럽트 요구가 있으면 이를 처리한다. 이처럼 인터럽트 메커니즘에는 아래의 두 신호가 필요하다.

(a) 인터럽트 요구(interrupt request) : I/O 디바이스의 인터럽트 요구를 나타낸다.
(b) 인터럽트 확인(interrupt aknowledge) : CPU가 I/O 디바이스의 인터럽트 요구를 인식했다는 것을 나타낸다.

이 신호들을 위한 버스들을 별도로 인터럽트 버스라고 부르기도 한다.

이외에도 제어신호에는 동기식 버스에서 버스 동작 시간을 일치시키기 위한 공통 클록 신호, 모든 시스템 요소들을 초기화시키는 리셋(reset) 신호가 있다.



(2) 시스템 버스의 기본 동작

버스 상의 모든 동작은 쓰기 동작 혹은 읽기 동작 중 하나로 구분된다.

(a) 쓰기 : 버스 마스터 사용권한 획득 -> 주소, 데이터, 쓰기신호 전송
(b) 읽기 : 버스 마스터 사용권환 획득 -> 주소, 읽기 신호 전송 -> 데이터가 올 때 까지 대기



(a) 동기식 버스(synchronous bus)

시간이 버스 클록을 기준으로 모든 버스 동작이 발생한다. 아래는 동기식 버스에서 CPU가 메모리로부터 데이터를 읽어오는 과정을 나타낸 타이밍도이다.

synchronous_bus_timing

버스 동작의 시작 신호를 기준으로 동작이 발생한다. 첫 번째 주기에서 읽기신호와 주소를 내보낸다. 두 번째 주기동안에는 데이터가 인출되어 세 번재 주기에 인출된 데이터가 전송된다. 메모리는 데이터와 함께 확인 신호를 보낸다. CPU는 확인신호를 보고 버스에 요청한 데이터가 실려있다는 것을 알고 데이터를 받는다.

동기식 버스는 회로가 간단하다. 그러나 동시에 발생하는 동작들 중 가장 오래 걸리는 동작이 끝날 때까지 기다려야 한다.



(b) 비동기식 버스(asynchronous bus)

버스 동작 발생이 다른 버스 동작의 발생 여부에 따라 결정된다. 아래는 비동기식 버스의 경우 CPU가 메모리로부터 데이터를 읽어오는 과정을 나타낸 타이밍도이다.

asynchronous_bus_timing

여기에는 클록 신호를 사용하지 않는다. 먼저 CPU가 버스로 주소와 읽기 신호를 보낸다. 신호가 안정될 때 까지 기다린 후 주소와 제어 신호를 보냈음을 알리기 위한 마스터 동기 신호(Master Synch Signal : MSYN)를 보낸다. 메모리는 MYSN을 보고 주소 버스와 제어 버스를 확인 후 메모리의 해당 주소에서 데이터를 인출하여 버스에 싣는다. 이후 슬레이브 동기 신호(Slave Synch Signal : SSYN)를 보낸다. 그럼 CPU가 SSYN을 확인하고 데이터 버스로부터 데이터를 가져간다. 데이터를 다 가져가고 난 후 MSYN와 읽기신호, 주소신호를 제거한다. 이후 메모리는 MYSN가 제거된 것을 보고 SSYN 신호를 제거한다.

비동기식 버스에서는 동작이 완료되고 나면 바로 다음 동작이 발생되므로 시간낭비가 없다. 그러나 위와같은 동작에 필요한 인터페이스 회로가 복잡하다.


## 2. 버스 중재 ##

여러 버스마스터들이 버스 사용을 요구하는 경우 버스 경합(bus contention)이 발생한다. 버스 경합이 발생하면 이들의 순서를 결정해주는 버스 중재(bus arbitration)을 해주어야 한다. 버스 중재를 해주는 모듈을 버스 중재기라고 한다.

버스 중재 방식은 시스템 성능에 큰 영향을 미치기 때문에 버스 시스템의 특성에 따라 알맞게 설계해야한다. 여러 버스마스터 중 중요도가 높은 마스터에게 우선적으로 권한을 부여해야한다. 또한 중요한 것은 어떤 버스 마스터가 오랫동안 버스를 사용하지 못하는 버스 기근(bus starvation)이 발생하지 않도록 해야한다.

버스 중재 방식은 제어 신호들의 연결구조에 따라 두 가지로 분류될 수 있다.

(a) 병렬 중재 방식
(b) 직렬 중재 방식

병렬 중재 방식에서는 각각의 버스 마스터의 버스 요구 신호 및 버스 승인 신호가 버스 중재기와 연결되어 있다. 즉 각각의 버스 카스터가 독립적으로 신호를 발생시킨다.

직렬 중재 방식에서는 버스 요구 신호 및 버스 승인 신호 선이 한 개씩만 있고 각각 버스 마스터들과 직렬로 연결된다. 접속되는 순서에 따라 우선순위가 결정된다.

버스 중재기의 위치에 따른 분류도 존재한다.

(a) 중앙집중식 중재 방식
(b) 분산식 중재 방식

중앙집중식 방식에서는 버스 중재기가 시스탬에 단 한 개만 존재하며 모든 버스 중재가 이 중재기에 의해 이루어진다. 여러 버스 마스터들이 버스 요구 신호를 보내면 중재기가 규칙에 따라 하나의 버스 마스터에게만 버스 승인 신호를 보낸다.

분산식 중재 방식에서는 여러개의 중재기가 존재하며 일반적으로 각각의 버스 마스터가 하나의 중재기를 가진다. 각 마스터는 각각의 중재기에 의해 중재된다.

위의 중재 방식들을 적절히 조합하면 다양한 중재 방식을 구성할 수 있다. 이제 여러 대표적인 중재 방식의 구성을 살펴본다.



(1) 병렬 중재 방식



(a) 중앙집중식 고정 우선순위 방식

고정 우선순위는 각 버스 마스터에 지정된 우선순위가 변하지 않는 방식이다. 아래 그림은 중앙집중식 고정 우선순위 방식의 회로 구성도이다.

centralized_fixed_priority_arbitration

버스마스터 1부터 4까지 차례로 높은 우선순위를 가진다고 가정한다.

병렬 중재방식이므로 각각의 버스 마스터가 버스 요구선(BREQ)과 버스 승인선(BGNT)을 가지고 있다. 또한 중앙집중식이기 때문에 버스 중재기 하나가 모든 마스터에 대해 버스중재를 한다.

여러 버스요구가 동시에 중재기로 들어오면 고정된 우선순위가 가장 높은 마스터에게 버스 승인 신호를 보낸다.

BBUSY 신호는 active-low 신호로 0이면 버스가 사용중임을 나타낸다. 버스 승인 권한을 받은 제어기는 BBUSY 신호가 0이면 기다렸다가 1이 되면 사용을 시작한다. 버스 마스터는 버스를 사용하기 전에 BBUSY신호를 0으로 만들어 다른 버스가 사용하지 못하도록 막는다.

아래 그림은 버스마스터 1이 버스를 사용하고있는 중에 버스마스터 3이 버스 요구신호를 보내는 예시이다.

centralized_fixed_priority_arbitration_example

버스마스터3이 BREQ3 신호를 1로 세트
            ↓
중재기가 BGNT3을 1로 세트하여 버스 사용 허가
            ↓
버스마스터1의 사용이 끝나 BBUSY 신호를 1로 해제
            ↓
버스마스터3이 BBUSY신호가 1인걸 확인하고 다시 0으로 활성화시킨 후 버스 사용 시작

위 그림에서 우선순위를 설정하기 위한 중재기의 회로는 아래 그림과 같다.

cfp_bus_arbitrator_diagram

우선순위가 낮은 마스터의 요구신호는 더 높은 마스터들의 요구신호들의 반전(NOT) 신호와함께 AND 게이트로 들어간다.



(b) 분산식 고정 우선순위 방식

이 방식에서는 버스 마스터들이 각각 중재기를 하나씩 가진다.

dfp_bus_arbitrator_diagram

마스터1,2,3,4가 차례대로 높은 우선순위를 가진다. 각 중재기는 자신보다 높은 우선순위를 가진 마스터들의 버스 요구신호의 반전(NOT)을 입력으로 받기 때문에 더 높은 우선순위인 어떤 마스터의 요구신호도 없을 경우만 자신의 승인 신호를 1로 세트한다.

버스 승인을 받은 마스터는 BBUSY 신호를 검사하여 다른 마스터가 사용중이지 않을 경우에만 버스 사용을 시작한다.


분산식 방식은 중앙집중식 방식에 비해 중재 회로가 간단하고 속도가 빠르다는 장점이 있다. 그러나 고장이 났을 경우 시스템 동작에 영향을 줄 수 있다. 가령 버스 승인 신호를 잘못 발생시켜 두 버스마스터가 동시에 버스를 사용하는 일이 발생할 수 있다.



(c) 가변 우선순위 방식

가변 우선순위 방식에서는 시스템의 상태나 조건에 따라 버스 마스터들에 지정된 우선순위가 계속해서 변하는 방식이다. 우선순위가 높은 마스터의 버스 독점이나 우선순위가 낮은 마스터의 버스 기근을 방지하기 용이하다.

가변적인 우선순위를 부여하는 알고리즘에는 여러 종류가 있다.

(a) 회전 우선순위

    - 중재 동작이 끝나면 모든 마스터들의 우선순위가 1단계씩 낮아지며 가장 낮은 우선순위였던 마스터가 최상위 우선순위를 가지게 하는 방법
        혹은

    - 버스 사용 승인을 받은 마스터를 최하위 우선순위로 보내고 다음 위치의 마스터부터 차례로 상위 우선순위를 부여하는 방법

(b) 임의 우선순위

    버스 중재가 끝나면 말 그대로 랜덤으로 우선순위를 부여한다.

(c) 동등 우선순위

    비동기식 버스에서 사용될 수 있는 방식으로 모든 버스마스터들이 동등한 우선순위를 가진다. 만약 두 개 이상의 버스 요구 신호가 도착하면 중재기는 충돌이 일어나지 않게 중재하는데, 일반적으로 먼저 도착한 요구부터 승인하는 FIFO 방식을 사용한다.

(d) 최소-최근 사용

    더 오랫동안 버스를 사용하지 않은 마스터부터 최상위 우선순위를 부여한다.



(2) 직렬 중재 방식



(a) 중앙집중식 직렬 중재 방식

직렬 중재방식에서는 모든 버스마스터의 요구신호선과 승인신호선이 각각 하나의 공통신호선을 통하여 중재기로 들어간다.

serial_centralized_arbitration

중앙집중식 직렬중재에서는 중재기에 가까운 버스마스터의 우선순위가 높아진다. 위 그림에서는 중재기로 어떤 요구신호가 들어오더라도 가장 가까운 버스마스터에 버스 승인 신호를 보낸다. 그 마스터가 버스 요구신호를 발생시키지 않았다면 다음 마스터로 버스 승인 신호를 보낸다. 이렇게 버스 요구 신호가 세트되어있는 마스터들 중 최상위 우선순위의 마스터에게 승인신호가 전달되면 해당 마스터에 의해 버스 사용이 시작된다.

이 방식에서도 BBUSY 신호가 해제될 때 까지 기다렸다가 버스사용이 시작된다.



(b) 분산식 직렬 중재 방식

분산식 직렬 중재방식에서는 아래 그림과 같이 데이지체인 버스 승인 신호(daisy-chain bus grant signal : DBGNT)선이 버스 중재기들을 순환형으로 접속해있도록 구성된다.

serial_distributed_arbitration

어떤 버스마스터가 사용을 시작하는 순간 DBGNT신호를 우측 마스터로 넘긴다. 해당 마스터의 버스요구신호가 세트되어있으면 중재기가 버스 승인 신호를 해당 마스터로 보낸다. 그러나 버스 요구신호가 없다면 오른쪽 버스 마스터로 DBGNT 신호를 넘겨준다.

이 방식에서는 우선순위가 계속 변한다. 현재 버스를 사용주인 버스 마스터의 오른쪽으로 가장 가까이 위치한 버스마스터들 중 버스 요구신호를 발생시킨 마스터가 최상위 우선순위를 가지게 된다.

중재기가 버스 승인신호를 버스 마스터로 보내더라도 버스 마스터는 BBUSY 비트가 해제된 후 버스 사용을 시작하게 된다.



(3) 폴링 방식

폴링 방식은 버스 중재기가 버스 마스터들의 요구신호를 주기적으로 검사하여 버스 사용 승인 여부를 결정한다.

폴링 순서와 중재 동작이 모두 회로로 구현되어있는 하드웨어 폴링 방식과 소프트웨어를 활용하여 코드로 구현한 소프트웨어 폴링 방식이 존재한다.



(a) 하드웨어 폴링

버스 중재기와 마스터들 사이에 폴링을 위한 폴링선들이 존재한다.

polling_arbitration

중재기가 폴링 주소를 발생하여 검사할 마스터를 지정한 후 버스 사용을 원하는지 검사한다
                            ↓
지정된 마스터가 버스 사용을 원하는 경우 BREQ 신호를 세트한다
                            ↓
BREQ 신호를 세트한 버스마스터에게 버스 사용을 승인한다. 그렇지 않으면 다음 마스터를 검사한다



이 방식에서 우선순위는 중재기가 버스마스터들을 검사하는 순서이다. 마스터가 버스 사용을 시작하면 BBUSY 신호가 세트되고 폴링 동작이 중지된다. 이후 버스 사용이 완료되고 BBUSY 신호가 해제되면 다시 폴링을 시작한다. 이 때 사용이 완료된 마스터의 다음 마스터부터 검사하도록 하는 회전 우선순위 방식을 사용할 수도 있고 다시 처음 마스터부터 폴링을 시작하는 고정 우선순위 방식을 사용할 수도 있다.



(b) 소프트웨어 폴링

소프트웨어 폴링 방식을 위한 회로는 하드웨어 폴링 방식과 동일하다. 그러나 버스 중재기가 프로그램을 실행할 수 있는 프로세서를 가지고 있다. 따라서 하드웨어 폴링방식처럼 하드웨어로 인한 일률적인 중재가 아닌 융통성있는 중재가 가능하다. 중재기의 프로그램은 다음 폴링 순서를 유연하게 결정하는데 사용되거나 혹은 고장이 발생한 버스 마스터를 폴링에서 제외시킬 수도 있다. 다만 하드웨어 폴링방식에 비해 속도가 느리다는 단점이 존재한다.


## 3. I/O 장치의 접속 ##

I/O 장치는 CPU와 메모리(주기억장치) 이외의 모든 장치이다. 여기서는 I/O 장치들의 제어방법 및 주소지정 방법에 대해 알아본다.



(1) I/O 제어

I/O 장치들은 종류가 매우 다양하며 일일이 모든 제어 회로를 CPU내부에 포함시키지 못한다. 이외에도 데이터 전송속도 차이의 문제나 데이터 형식의 차이로 인해 시스템 버스에 직접 접속되지 못한다. 이를 위해 CPU와 I/O 장치 사이에서 인터페이스 역할을 수행해주는 제어기가 필요하다. 이를 I/O 제어기라 한다.

I/O 제어기는 I/O장치 제어, CPU 혹은 메모리와 I/O 사이의 통신, 데이터 버퍼링, 오류 검출 등의 기능을 수행한다. 일반적으로 각 I/O장치를 위한 별도의 제어기가 시스템 버스와 I/O장치 사이의 인터페이스를 담당하도록 되어있다.

예시를 위해 프린터 출력의 경우를 보자.

printer_controller_diagram

(a) CPU가 프린터 제어기의 상태 레지스터의 출력준비 비트(RDY bit)가 세트 되어있는지 검사한다.
(b) 프린터 제어기가 CPU에 검사결과를 전송한다.
(c) 준비가 되어있다면 출력할 데이터와 출력 명령 신호를 프린터 제어기로 전송한다.
(d) 프린터 제어기가 출력할 데이터와 제어신호를 프린터로 보낸다.

위와 같이 CPU는 I/O 장치의 프로세서와 통신하며 I/O장치는 I/O 제어기에 의해 동작된다.



(2) I/O 주소지정

위에서 설명한 내용의 요점은 CPU는 I/O 장치를 직접 제어할 필요 없이 I/O 제어기의 레지스터 값을 읽거나 레지스터에 명령할 내용을 쓰기만 하면된다. 나머지는 I/O 제어기가 알아서 한다.

CPU가 I/O장치를 사용하려면 데이터를 주고받을 주소를 지정해야한다. I/O 장치별로 두 개씩의 주소가 지정된다. 하나는 상태/제어 레지스터 주소이고 하나는 데이터 레지스터 주소이다. 사실 상태레지스터와 제어 레지스터로 분리되어있지만 상태 레지스터의 값은 읽기만 하면되고 제어 레지스터에는 쓰기만 하면 되기때문에 하나의 주소로 사용할 수 있다.

그리고 I/O 레지스터들에 주소를 지정하는 방식에는 크게 두 가지가 있다.



(a) 기억장치 사상 I/O

이 방식에서는 메모리와 I/O 레지스터들을 동일하게 취급하고 I/O 레지스터들에 메모리의 주소영역 일부를 할당한다. 이후부터는 I/O 레지스터들에 메모리와 동일한 방식으로 액세스 할 수 있다.

memory_mapped_io

만약 주소 비트가 10비트라면 1024개의 주소를 지정할 수 있다. 따라서 0번지부터 511번지까지는 메모리에 할당되고 512번지부터 1023번지까지는 I/O장치에 할당된다. 따라서 메모리에 할당할 수 있는 주소 번지의 수가 절반으로 줄어든다는 단점이 존재한다.



(b)분리형 I/O

I/O 레지스터들의 주소가 메모리와는 별도로 할당된다. 그리고 I/O 레지스터들에 액세스 할 때는 메모리와 별도의 명령어(어셈블리어)를 사용한다. 그리고 이러한 명령어들이 수행될 때는 메모리에 대한 것인지 I/O 장치에 대한 것인지를 구분하기 위한 신호(I/O읽기, I/O쓰기)가 CPU로부터 발생되어야한다.

isolated_io

이 방식은 메모리와 I/O의 주소를 별도로 지정하므로 10비트를 가지고 메모리와 I/O 레지스터들 각각에 1024개의 주소를 할당할 수 있다. 그러나 명령어를 별도로 사용해야 하기때문에 프로그래밍이 불편해지는 단점이 존재한다.


## 4. 인터럽트를 이용한 I/O ##

앞에서 설명한 I/O장치 제어 방식은 폴링(polling)이라 부른다. CPU가 주기적으로 I/O 상태 레지스터의 값을 확인하고 동작에 계속 관여해야한다. 따라서 CPU 시간이 낭비된다. 특히 속도가 느린 I/O 장치일수록 대기시간이 길어져 낭비가 더욱 심해진다.

그러나 인터럽트(interrupt) 방식을 사용하면 I/O 동작이 수행되는 동안 CPU는 다른 일을 처리할 수 있다. 아래는 인터럽트에 의한 프린터 I/O 동작 순서이다.

printer_interrupt_example

CPU가 I/O제어기로 인터럽트 요구를 보내놓고 다른일을 처리하면 I/O동작이 수행되고 완료가 되면 다시 CPU로 인터럽트 신호를 보낸다. CPU는 인터럽트 신호를 보고 동작 수행의 완료를 알 수 있다.



컴퓨터 시스템에는 여러개의 I/O 장치가 접속되어있다. 만약 여러개의 I/O 동작이 완료되고 CPU로 동시에 인터럽트 신호를 통해 완료보고를 보낼경우 어떤 서비스부터 처리할 것인지 결정해야 한다. 여기에는 여러가지 방법이 있다.



(a) 다중 인터럽트 방식

각각의 I/O 제어기마다 CPU와의 사이에 인터럽트 요구신호선(INTR)과 인터럽트 확인 신호선(INTA)이 있다.

multi_interrupt_io

두개 이상의 I/O장치들이 동시에 인터럽트 요구 신호를 보내면 우선순위에 따라 인터럽트 확인 신호를 보내고 서비스 루틴을 수행한다.

만약 인터럽트 플래그(interrupt flag)가 disable 상태라면 인터럽트 서비스 루틴을 처리하는 도중에는 다른 인터럽트 요구를 무시하지만 enable 상태라면 더 높은 우선순위를 가진 인터럽트가 들어오면 현재 실행중인 루틴을 중지하고 높은 우선순위의 인터럽트 서비스 루틴으로 이동한다.



(b) 데이지 체인 방식

이 방식에서는 INTR 신호선이 하나만 있다. 또한 INTA 출력선은 CPU와 가장 가까운 제어기로만 입력된다. INTA 신호는 계속해서 다음 제어기들로 직렬로 연결된다.

daisy_chain_interrupt_io

이 때 하나 이상의 INTR 신호가 세트되면 CPU는 INTA 신호를 가장 가까운 제어기로 보낸다. 만약 이 제어기가 INTR 신호를 세트한 상태라면 데이터 버스를 통해 자신의 ID를 CPU로 보낸다. 이 ID를 인터럽트 벡터(interrupt vector)라고 부르는데 CPU가 해당 I/O장치를 위한 인터럽트 서비스 루틴의 시작 주소를 찾는데 사용된다.

첫 번째 제어기가 INTR을 세트한 상태가 아니라면 INTA 신호는 바로 다음 제어기로 넘어간다. 이 과정은 INTR을 세트시킨 제어기를 찾을 때 까지 반복된다.

이 과정으로 인터럽트를 하나 처리하고 남아있는 인터럽트가 있다면 여전히 INTR 신호선의 상태는 세트일 것이기 때문에 CPU는 곧바로 INTA 신호를 다시 내보낸다.



(c) 소프트웨어 폴링 방식

이 방식에서는 공동의 INTR 신호 하나만 사용한다. 그리고 TEST I/O선이 CPU와 모든 제어기 사이에 연결되어 있다. 모든 제어기는 인터럽트 플래그가 있는데, TEST I/O 선은 제어기의 인터럽트 플래그가 세트 되었는지 검사하기위해 사용된다.

software_polling_interrupt_io

한 개 이상의 제어기가 인터럽트 플래그를 세트시키면 INTR 신호선의 상태가 세트 된다. 그러면 CPU는 TEST I/O선을 통해 순서대로 제어기들의 인터럽트 플래그를 검사한다. 인터럽트 플래그가 세트된 제어기를 발견하면 해당 인터럽트 서비스 루틴을 수행한다.

인터럽트 플래그를 검사하는 과정에서 마이크로프로그램을 사용하기 때문에 소프트웨어 폴링 방식이라 부른다.


## 5. DMA를 이용한 I/O ##

인터럽트 I/O 방식은 폴링 I/O 방식보다 효율적이지만 여전히 읽기/쓰기 과정에서 I/O 장치와 메모리 사이에서 데이터가 이동할 때 CPU를 경유해야 하는 문제점이 존재한다. 특히 이동해야 할 데이터 블록이 크다면 CPU의 시간 소요가 더 길어진다.

직접 기억장치 액세스(Direct Memory Access : DMA)는 이러한 문제점을 해결하기 위해 개발되었다. DMA 방식을 사용하면 메모리와 I/O장치 사이에 직접 데이터 전송이 이루어질 수 있다.

DMA를 사용하기 위해서는 내부 시스템버스에 DMA 제어기가 포함되어야한다.

systembus_with_dma_controller

메모리와 I/O장치 사이에 데이터 전송이 필요한 경우 CPU는 DMA 제어기에 아래의 정보가 포함된 명령을 보낸다.

(a) I/O장치 주소
(b) 쓰기 혹은 읽기 지정자
(c) 데이터가 읽혀지거나 쓰여질 메모리의 시작 주소
(d) 전송될 데이터 단어들의 개수

CPU는 명령을 DMA 제어기에 보낸 후 다른일을 한다.

DMA는 한 번에 데이터를 한 개씩 보낸다. 워드가 1바이트이고 총 보내야할 데이터가 1kB라면 1024개의 데이터 전송이 필요하다. 그런데 하나의 데이터를 전송할 때 I/O장치와 한 번 액세스, 메모리와 한 번 액세스 해야하기 때문에 총 1kB 전송을 위해 총 2048번의 버스 점유가 필요하다. 이때문에 성능 이슈가 발생할 수 있다. 이러한 문제를 개선하기 위해 아래와 같은 방식을 고려할 수 있다.

systembus_with_dma_controller2

이렇게 하면 메모리 액세스를 할 때만 버스를 점유하므로 점유시간이 절반으로 줄어든다. 그러나 이런 방식을 사용하면 DMA 제어기에 접속할 수 있는 I/O제어기가 한계가 있기때문에 여러개의 DMA 제어기가 필요하다. 이를 개선하기 위한 시스템이 아래 그림이다.

systembus_with_dma_controller3

DMA 제어기와 I/O 장치들 간에 별도의 버스를 두었다. 하지만 이렇게 해도 매우 다양한 종류의 I/O 장치들을 지원하기에는 한계가 있다. 또한 디스크의 경우 블록 단위가 크므로(ex. 512바이트) 이 데이터를 임시저장하기 위한 버퍼까지 필요하게 된다.

이러한 이슈를 해결하기 위해 최근 고성능 컴퓨터들은 DMA 제어기를 확장시킨 I/O 프로세서 라는것을 사용한다.

systembus_with_io_processor

I/O 프로세서는 I/O를 제어하기 위한 프로그램을 실행하며 큰 크기의 데이터 블록 저장을 위한 버퍼를 가지고 있다. 또한 시스템 버스 사용을 위한 버스 마스터 회로와 I/O 버스 인터페이스를 가지고 있으며 I/O장치들간의 중재를 위한 기능을 한다.

I/O 프로세스가 개발됨으로써 CPU가 I/O 동작 수행의 부담에서 벗어날 수 있었다.

+ Recent posts