I/O 디바이스들이 주소를 가지고 메모리, CPU와 통신하는 방식을 크게 3가지로 알아보자.
CPU가 I/O 장치에 접근하기 위해 데이터 전송을 위한 하드웨어인 system bus를 거치게 된다.
크게 Address bus, Data bus, Control bus 세 가지로 나뉜다.
- Address bus: source와 destination을 지정하기 위한 장치이다.
- Data bus: 실제 데이터 전송을 위한 장치이다.
- Control bus: 읽기, 쓰기 등의 명령어 전송을 위한 장치이다.
- I/O controller: CPU 대신 I/O 장치들의 연산을 수행하는 장치이다.
별도의 프로세서, 메모리가 존재한다.
I/O controller의 구현과 기능은 내부적 요인이고, CPU와 이와 상호작용할 수 있는 인터페이스를 제공한다.
I/O controller는 버스에 세 개의 주소를 제공한다. 각각은 controller 안에 있는 레지스터들과 상응한다. 이 레지스터들은 위의 주소를 제공하고 CPU가 접근 가능하다. 이 주소들을 I/O port라 칭한다.
I/O 장치들도 주소가 존재한다. 이 주소들은 CPU와 상호작용하기 위한 주소이다. 이를 I/O device address space라 부른다. 두 가지 주소체계를 알아보자.
- Port-mapped I/O(I/O instructions): 메모리 주소체계와 별도로 아예 분리된 주소체계이다.
각 디바이스마다 별도의 Port register들을 별도의 주소로 mapping한다.
추가의 I/O instruction이 필요하다. ex) in and out instruction(x86)- Memory-mapped I/O: 메모리 주소체계와 동일한 주소체계를 사용한다.
단점은 실제 메모리 공간을 사용할 수 없게 된다.
이제 I/O 장비와 통신하는 방법을 알아보자. 그 중 가장 단순한 형태가 Programmed I/O또는 Polling I/O라고도 부른다.
I/O 디바이스와 통신하기 위해 I/O controller에 있는 command register에 있는 명령어를 디바이스에 작동시킨다.
프로그램 입장에선 반복적으로 디바이스가 작동을 할 수 있는지, 수행 중인지 등의 상태를 저장하는 status register를 반복적으로 확인해야한다.
만약 명령어를 수행할 수 있는 상태라면, 명령어 수행 이후 data register를 통해 수행된 데이터를 읽어와 memory에 저장한다.
프로그램은 command register에 명령어를 저장한다 -> controller는 command register를 읽는다. -> 프로그램은 status를 반복적으로 체크한다.(busy waiting) -> I/O device가 수해을 완료한다. -> data register나 로컬 버퍼에 있는 data를 읽어와 메모리에 저장한다.
device가 빨라야 busy-waiting이 효율적이다.
Polling I/O의 busy waiting 문제를 해결하기 위한 두 번째 방법인 Interrupt-Driven I/O를 알아보자. 이 방법은 아까와 다르게 device, cpu 모두 일을 하는 병행성이 보장되어 utilization이 증가한다.
I/O controller에 의해서 장치는 수행하고, 명령이 종료되면 CPU에게 interrupt를 보낸다.
interrupt 방식은 mode switch에 대한 overhead가 발생한다.
hard disk drive와 같은 block 단위의 연산을 하는 장치들은 좀 더 효율적인 기법이 필요하다.
매 word마다 interrupt을 발생시키지 않고 block 단위의 연산을 통해 일이 전부 끝나고 interrupt를 발생시키는 기법이다.
CPU의 개입을 최소화하는 기법이기 때문에 I/O controller가 직접 메모리에 접근을 할 수 있어야 한다.
DMA 방식으로 통신하기 위해 DMA controller에게 command의 집합(block)을 전송해야한다.
이 명령의 집합은 source address의 data를 destination address에 복사하는 read operaton이 될 수 있다. 이 block의 크기가 C bytes라면 이 C가 0이 될 때 CPU에게 interrupt를 발생시킨다.
DMA controller는 system bus상에 존재할 수 있고, I/O controller와 통합될 수 있다.
세 가지를 비교하는 그림이다.
- Polling: CPU는 I/O 디바이스의 수행이 종료될 때까지 status register를 확인한다.
- Interrupt_driven I/O: I/O 디바이스의 수행이 종료될 때 CPU에게 Interrupt를 보낸다.
- DMA: DMA controller가 블락단위의 데이터를 로컬 버퍼에서 메모리로 CPU의 개입없이 전송하고 Interrupt를 발생한다.
하나의 processor를 사용하는 시스템에 uniprocessor라 하고, 2개 이상의 processor를 사용하는 시스템을 multiprocessor(다중 처리기)라 한다. 메모리와 I/O를 공유하며 처리기를 여러개를 가지면, 단위 시간당 처리할 수 있는 작업의 양(throughput)이 많아진다. 또한 오작동을 남은 프로세스로 처리할 수 있기 때문에 신뢰도도 높아진다.
이렇게 multiprocessor를 구현할 때 두가지의 다중 처리기가 존재한다. 하나는 Symmetric Multiprocessor 또 다른 하나는 Asymmetric Multiprocessor이다.
SMP는 이 각각의 프로세서가 대등한 역할을 하는 방식을 말한다. 반면에 ASMP는 프로세서마다 역할이 다른 경우를 말한다.
이러한 Multiprocessor들을 하나의 칩에 만든 경우를 on-chip이라 부른다.
SMP에서 device에 초점을 맞추면, 전체 시스템에서 공유되는 device가 있을 것이다. 외부 device의 interrupt에 대해선 PIC이 사용되었었다. 간단하게 이의 역할은 Interrupt signal을 벡터로 변환한다 했었다. Interrupt를 처리할 processor가 여러개이니, 이 중 하나를 대등하게 선택하여 interrupt를 처리한다.
또한 local device(e.g. timer)에 대한 interrupt를 처리할 수 있는 local PIC도 필요하다.