- 정보를 블록 단위로(fixed-size) 저장
- 각 블록들은 주소를 갖는다.
- 블록 당 512B~32KB의 크기를 갖는다.
- 각 블록에서 Read or Write를 독립적으로 수행할 수 있다.
Character device(Low speed)
- characters의 stream으로(들어오는 순서대로) 데이터를 주고 받는다.(delivers and accepts)
- 주소가 없고(순서대로 전달) and no seek operation
- Mechanical component
- Electronic component has device controller
- Device controller는 여러 개의 device를 handle할 수 있다.
Device controller의 주요 역할은 bit stream 즉, 어떤 데이터들이 실제로 오게 되면 그것들을 변환해서 메인 메모리에 보일 수 있도록 제공해주는 역할이다. 필요하다면 error correction을 수행한다.
- 보통 registers를 이용해서 처리를 하게 된다.
- 이 레지스터를 보고 Device Driver는 레지스터에 명령을 주게 된다. 어떤 주소에 어떤 값을 써넣으면 무엇을 하는지 명령한다.
- 각 divice는 주소를 갖는다. 다음에 의해 사용되는
-> Direct I/O 명령
-> Memory-mapped I/O : register에 명령을 주는 형태
I/O instructions and I/O port address도 제공한다.
Memory-mapped I/O
사실 모든 Device를 Direct I/O방식으로 컨트롤할 수 없다. 왜냐하면 새로운 device가 추가될 수도 있다. 이렇게 하려면 CPU 설계를 처음부터 이 디바이스가 포함되도록 해야한다. 그게 불가능하여 생겨난 방식이다.
1. device control registers를 프로세서의 address space에 맵핑한다.
-> CPU가 I/O 요청을 일반적인 data 전송 명령으로 처리할 수 있다.(메모리에 있는 값 바꾸기)
2. 이러한 방식으로 device driver를 C로 쓸 수 있다는 장점이 있다.
3. 별도의 protection mechanism이 필요하지 않다.
-> PTE을 통해 protection(protection field)을 할 수 있다.
4. 어떤 값을 읽고 보는 것을 single instruction만으로 가능하다.
- CPU가 계속 device가 준비되었는지 물어본다(poll)
장점 : 단순하다. sw로 컨트롤하기도 굉장히 쉬워지고 device가 준비되었을 때 cpu가 device를 찾는데 효율적이다.
단점 : CPU 사용량이 굉장히 높아진다. CPU가 다른 일을 못하고 polling하는데 시간을 소비한다.Interrupt-driven I/O
- I/O device가 Interrupt를 요청하는 방식이다.
- ISR(Interrupt service routine)가 어떤 device가 interrupt를 요청했는지 알 수 있다. CPU가 이를 처리해주면 device가 준비되었음을 인지하고 다른 일을 한다.
- interrupt는 여러 디바이스들과 공유할 수 있다.
장점:
1) CPU가 필요할 때만 쓰인다.
2) polling에 비해 일반적으로 효율적이다.(항상 그런 것은 아니다.)
단점:
1) 과도한 interrupt가 발생하면 program 실행이 느려질 수 있다.
2) 오버헤드 발생(interrupt하는데 데이터가 전송된다.)
- CPU가 직접 관여를 해서 CPU가 I/O device와 메모리 사이에서 데이터를 옮긴다.
- 별도의 instructions이 필요없이 vs memory-mapped I/O
DMA(Direct Memory Access)
CPU가 디바이스에 있는 데이터를 어느 메모리 위치에 전송할지 명령만 주면 된다. DMA controller가 CPU를 거치지 않고 알아서 처리한다.
1. 똑똑한 device가 있다면 그 디바이스가 메모리 액세스하는 속도로 디바이스 스스로 알아서 데이터를 전송한다.(물론 direct memory, controller, memory의 지원이 필요)
2. device controller가 CPU의 간섭없이 특정 block의 데이터들을 스토리지로부터 읽어서 메인 메모리까지 다 전송한다.
3. 다 끝나면 interrupt를 요청하여 CPU에 다 끝냈다고 알린다.
- I/O가 끝날 때까지 어떤 프로세스가 멈춰있는 것이다.
- 사용하기 쉽고 이해하기 쉽다.
- read, write : 파일을 읽거나 쓸 때 이것이 끝날 때까지 프로그램이 멈춰있다.
Non-blocking I/O
어떤 I/O를 요청하고 나서 그것이 다 끝나지 않았음에도 프로그램이 다른 작업을 할 수 있도록 block되지 않고 처리해주는 방식(network, disk.. etc)
1. I/O가 요청하면 바로 리턴한다. 명령을 주면 실제로 I/O가 끝나지 않더라도 바로 리턴한다. 리턴 값은 얼마만큼의 바이트가 전송되었는지를 나타낸다. 실제로는 디스크에서 다 읽지 못한 상태로 리턴하는 것이다.
2. select()를 통해서 데이터가 준비되었는지 찾는다.
3. 멀티 스레딩을 통해 구현된다.