Search

IO Systems

IO Systems

CPU -> IO Controller

1.
Direct IO vs Memory-mapped IO: CPU가 메모리장치에게 명령을 내리는 방식의 차이
2.
IR&DR: CPU가 IO컨트롤러에게 명령을 전달할때 IO 컨트롤러에는 CPU가 내리는 명령을 저장하는 IR레지스터 와 데이터를 저장할 수 있는 DR이 존재한다.
3.
graphics controller, SCSI controller, disk controller, memory controller등이 빠른 i/o를 위해서 PCI버스와 연결 되어있고 키보드 등의 느린 IO장치는 expansion버스에 연결되어있다.

IO디바이스 명령어 수행

1.
Programmed IO: IO장치에서 처리한 결과를 CPU레지스터에 직접 전달하는 방식. IO의 결과 입출력이 적은 키 보드, 마우스 같은 경우 사용한다.
2.
Interrupt: IO장치가 처리가 완료되었을때 CPU에게 알려주는 방법
3.
DMA: 디스크에서 많은 데이터를 메모리로 로드해야하는 경우 사용. 디스크에 존재하는 DMA컨트롤러가 CPU에게 허락을 받고 이후에는 CPU를 거치지 않고 버스를 통해서 바로 메모리로 데이터를 로드하는 방식

Direct IO

1.
Intel CPU에서 사용하는 방식. 다양한 IO디바이스 각각에 적합한 Instruction을 CPU에 전부 따로 넣고 명령을 처리하는 레지스터도 별도로 구현. CPU입장에서는 메모리도 IO장치이다. CPU설계상에 Instruction이 핀 형태로 구현되어 수행되기 때문에 IO처리에 불필요한 메모리 사용이 없고 빠른 처리가 가능하다. 하지만 Instruction의 수가 늘어나면 각 IO디바이스 대상으로 명령을 수행하는 버스를 따로 둬야 하고 CPU의 복잡도가 증가하며 생 산가격도 증가한다.

Memory Mapped IO

1.
ARM코어에서 사용하는 방식. Instruction의 개수가 많아져서 CPU가 복잡해지는것을 방지하기 위해서 가장 많이 사용하는 IO명령인 메모리의 Input Output방식을 다른 디바이스의 IO에도 활용한다. 특정 메모리 영역을 컨트롤러와 연결해놓고 CPU가 디스크 IO를 수행하면 메모리의 특정 영역에 write을 수행하고 그 데이터가 메모리를 거쳐서 디스크에 저장된다. Direct IO보다 느리지만 MEMR MEMW 명령어 한 세트만 가지고 메모리와 IO명령을 관리할 수 있어서 하드웨어 복잡도가 떨어지고 전력소모도 줄어든다. 어떤 방식을 쓰느냐는 CPU 아키텍쳐가 CISC인지 RISC인지에 따라서 다르다.

Kernel IO Structure

1.
하드웨어 단에 IO디바이스들이 존재하고 각각의 디바이스들의 컨트롤러가 존재한다. 컨트롤러를 소프트웨어적으로 제어하기 위해서 드라이버라는 시스템 소프트웨어를 컨트롤러마다 제조사에서 제공한다. 드라이버는 특정 하드웨어 dependent한 내용을 다루는 소프트웨어이다. 요즘에는 복잡한 IO장치가 아니라면 Universal Drive가 존재하지만 기능이 많거나 처리할 데이터가 많으면 제조사에서 드라이브를 제공한다. 드라이버들은 IO컨트롤러에 일대일 매핑된다. Kernel IO서브시스템은 드라이버들의 공통적인 부분들을 표준화하여 처리한다. 프리징 된 상태에서 클릭 명령이 여러번 중복되어 들어가서 오버헤드가 발생하면 Kernel IO Subsystem은 이미 요청한 것에 대해서 처리가 되었는지 확인하고 동일한 명령을 무시하도록 처리한다. 이러한 빈번한 IO를 중재하고 커널에서 어떤 드라이버에 명령을 전달할지, 드라이버에서 전달받은 데이터를 어떤 앱에 전달할지 등을 통합해서 관리하는 시스템이다. Device Independent IO Software라고 한다.

IO 요청 순서

1.
user어플리케이션에서 system call로 요청이 들어오면 커널이 올라오고 커널은 IO서브시스템 함수를 호출한다. 버퍼 캐시에 요청이 캐싱되어있다면 바로 시스템 콜 요청결과로 전달한다. 캐싱되어 있지 않으면 어떤 드라이버에 요청을 보낼지 확인해서 요청을 보내고 드라이버는 컨트롤러가 이해할 수 있는 형태로 명령을 내린다. IO처리가 완료되면 컨트롤러가 인터럽트를 발생시키고 인터럽트 핸들러가 동작하고 인터럽트 핸들러가 드라이버로 정보를 전달한다. 드라이버는 IO서브시스템 거치지 않고 요청한 어플리케이션에 결과를 전달한다.
2.
채팅 어플리케이션 예시: 키보드로 들어온 데이터로 인해 Programmed IO로 인터럽트가 걸리고 인터럽트 핸들러가 동작한다. 그다음 드라이버로 데이터를 넘겨주고 유저 프로세스로 넘겨준다. 엔터가 입력되면 네트워크 어뎁터에게 데이터를 보내고 받는 쪽에서도 데이터를 네트워크 데몬에게 보내서 IPC를 통해 유저 프로세스에 전달한다.
3.
IO와 관련된 기능을 구현할때는 프로세싱이 필요없는 하드웨어로 구현하는게 빠르다. SSD컨트롤러가 수행하는 웨어레벨링 기술이 하드웨어로 구현된 예시다. Abstraction이 좋아지므로 어떻게 구현된건지 알 필요가 없다. 하지만 하드웨어는 변경이 불가능하기때문에 flexibility가 떨어진다.

IO System Layers

1. User Process가 커널에 시스템 콜 요청하고 커널은 Device Independent Software = Kernel IO Subsystem에 데이터를 넘겨주고 공통적인 작업인 Naming, Protection, blocking, buffering등을 수행하고 디바이스에 특화된 동작을 Device Driver를 통해 수행하고 하드웨어 컨트롤러에게 명령을 전달하면 하드웨어적으로 동작시키고 인터럽트 발생시키면 인터럽트 핸들러 동작하고 핸들러 유형에 따라 처리하고 디바이스 드라이버에 전달하면 디바이스 드라이버는 IO서브시스템에 전달하고 IO서브시스템은 유저 프로세스에 전달한다.
네트워크 데이터인 경우에는 4계층에서 세그먼트, 3계층에서 패킷, 2계층에서는 프레임의 구조로 데이터가 캡슐화되어있는데 physical layer에서는 비트스트림으로 만들어서 전달하고 받은 쪽에서는 디지털화해서 프레임으로 만들고, 모아서 패킷, 세그먼트로 만들어서 어플리케이션 단으로 전달한다. 이러한 capsulation, decapsulation과정도 드라이버와 Kernel IO서브시스템 동작에 포함된다.

Device Independent IO Software

1.
Uniform interfacing: 유닉스에서는 모든 io디바이스를 파일기반으로 관리하며 파일 디스크립터를 사용한다. 파일에 있는 내용이 IO디바이스와 연결되어 open, read, write, close등의 시스템콜을 통해 IO디바이스를 어플리케이션 레이어에서 컨트롤 할 수 있도록 한다.
2.
Buffering: 어플리케이션에서 버퍼를 만들어서 사용하는 방법과 커널공간에서 버퍼를 생성하고 어플리케이션 버퍼로 옮겨서 쓰는 방식 등이 있다. 신뢰성이 많이 필요한경우 커널에 더블퍼버를 만들고 어플리케이션 버퍼로 옮겨서 사용한다.
3.
Error reporting: 에러가 발생했을때 서브시스템에서 에러를 받아오고 시스템 콜의 리턴형태로 에러코드를 던져주고 에플리케이션이 핸들링하는 방법이 있다. ARQ프로토콜은 2계층에서 ACK가 안오면 최대 3번까지 재존송한다. 메모리에서 corruption이 발생하면 시스템을 강제종료하는 방식을 watch dog이라고 한다. 시스템이 정지되어있으면 타이머가 동작해서 오랫동안 정지한 상태이면 시스템을 재부팅한다. 하드웨어 dependent한 방식이다.
4.
Block size: 여러개의 섹터를 하나의 logical block으로 처리한다. 1바이트를 사용해도 고정된 블록단위인 4kbyte를 사용한다. 각 디바이스마다 데이터 크기의 단위가 다르면 컨트롤하기 어렵기 때문에 block단위로 처리한다.

User Space IO Software

1.
IO처리 인터페이스는 시스템 콜이고 프로그래밍 언어에서 제공하는 라이브러리를 통해 IO처리한다.
2.
스풀링: IO디바이스 중에서도 느린 프린터는 계속해서 요청이 들어오면 job이 처리되지 못하고 쌓인다. 이미지라서 사이즈가 크기 때문에 피지컬 메모리도 많이 사용한다. IO처리시에 필요한 데이터를 메모리에서 보관하는것이 아니라 파일로 만들어놓으면 좋다. 디스크에 저장되어있어도 프린터 자체의 속도가 느리기때문에 상관없다. 용량이 큰 작업에 IO디바이스의 속도가 느려서 메모리를 많이 차지하는 경우 task를 파일로 저장해놓는것을 스풀링이라고 한다.