: cpu가 io장치에게 명령을 내리는 방식 Direct I/O vs. Memory-mapped I/O 두개가 있다.
cpu가 io명령을 내린다 수행한다는 것은 io 컨트롤러에게 명령을 전달한다는 것이고 특정 데이터도 같이 전달을 해주어야 명령을 수행 할 수 있는 경우도 있다. 이 io 컨트롤러에는 일반적으로 cpu에서 io 자치에게 내리는 명령어가 있고, 그 명령어를 받아와서 저장할 수 있는 ir 이 존재. 또한 데이터를 저장하는 데이터 레지스터가 존재하는 경우가 일반적이다.
Communicates with registers in I/O controller
→ io 컨트롤러가 없다면 os가 다 처리를 해야하는데 그 사이에 io 컨트롤러가 대리해서 처리를 해준다.
IR (Instruction Register) & DR (Data Register)
io 컨트롤러에는 명령어를 가지고 오고 읽고 쓰는
: io 디바이스가 명령을 수행하는 방식
메모리랑 io디바이스 영역을 분리를 한다. 메모리에서 데이터를 읽고 쓰는 명령어와 io장치에서 쓰고 읽는 명령어가 다르다
장점 : 분리되어 있으니 두가지 동작이 완전히 isolation 가능하다.
단점 : cpu 입장에서는 데이터를 쓰고 읽는 것이 같은데 상이한 명령어로 구성을 해야하니 하드웨어 설계가 어려워지고 cpu에 있는 pin수가 늘어난다.
intel 에서 사용
io device와 관련된 input/output instruction set을 따로 만듬 → hardware set을 따로 만들어야 함을 뜻함
정의되어 있는 io디바이스마자 주소가 존재하고, 어느 특정 주소는 메모리에 디스크에 쓴는 등 구분을 지어서 써야하는데 이것이 모두 하드웨어 로직으로 정해져 있다.
RISC → ARM
: 메모리에 데이터를 읽고 쓰는 것 하나로 씀
메모리에 특정 주소를 외부 아이오 디바이스 주소에 매핑을 해두고 사용?
인스트록션 셋의 개수가 줄어드니 더 효율
메모리의 특정 영역은 io 컨트롤러의 명령을 쓰는 것과 mapping을 시킨다.
메모리의 일부분을 io 컨트롤러에게 전달을 하거나 io컴트로러부터 받아오는 어떤 데이터들을 읽는 전용의 메모리 공간으로 mapping을 시켜 사용한다.
위에까진 io HW에 대한 정리 지금부터는 io SW에 대한 정리
시스템 콜을 통해 커널에게 io를 요청
kernel io subsystem이 먼저 확인을 한다. 얘가 봤을 때 버퍼, 캐시에 요청한 io에 대한 자료가 있어 처리를 바로 할 수 있다면 실제 device driver, interrupt, device controller로 내려가지 않고 system call에 요청 결과를 바로 알려준다.
버퍼 캐시가 없으면 커널 아이오 서브 시스템이 일반적인 것을 처리하고 디바이스 드라이버로 디바이스 컨트롤러에 전달해주어야 하는 명령을 전달한다. 디바이스 컨트롤러는 여러것들을 처리를 하고 디바이스 컨트롤러에게 넘겨준다.
그러면 디바이스 컨트롤러는 실제 io를 수행을 하고 수행이 종료되면 io 디바이스가 인터럽트를 걸고 그러면 인터럽트 핸들러가 동작을 하고 인터럽트 핸들러가 디바이스에게 그 동작을 전달해준다.
유저 어플리케이션에게 그 io 수행한 결과를 시스템 콜에 대한 응답으로 전달 한다.
io 시스템이 다 갖춰져 있는 상태에서 뭔가 새로운 기을을 추가하려고 하는 상황에 어디다가 구현을 하는 것이 좋을까.
아래로 가면 갈수록 하드웨어로 구현이 된다. 이렇게 되면 구현이 완료되었을 때 효율이 좋다. 빠르다. 소프트웨어보다 하드웨어가 동작속도가 빠르니끼. 효율은 좋아지지만 개발기간이 늘어나고 비싸진다. 하지만 abstraction이 좋아진다. 운영체제가 하드웨어가 어떻게 동작하는지 몰라도 알아서 잘 되게 해주니까.
유연성이 떨어진다. 새로운 알고리즘이 들어오면 다음세대의 물리적인 하드웨어를 새롭게 만들어야 한다.
반면 윗단으로 갈 수록 유연성이 좋아진다. 더 위로 가면 갈수록 flexibility가 높아진다. 디바이스 code같은 경우 하드웨어 dependency가 아주 높다. application code는 밑에가 abstraction이 잘 되어 있으니 변경을 하기 아주 쉬울 것이다.
Device independence
Uniform naming
: 통합해서 처리, 코드 재사용성
Error handling
: 오류의 후처리
Synchronous vs. asynchronous
: 둘 중에 어떤 것으로 동작시킬것이냐
Buffering
: 성능을높이기 위해 버퍼링 혹은 캐싱
Sharable vs. dedicated devices
: io 디바이스를 공유할 수 있도록 할건지 나만 쓸 수 있도록 할 것인지
Uniform interfacing for device drivers
→ kernel io subsystem 을 이야기하는 것
Buffering
: 버퍼에 데이터를 임시로 저장하는 행위
→ 3,4 캐싱에서 이점도 있고 빠르고 좋다. 그래서 요 두가지를 많이 사용
Error reporting
io device에 protection측면에서훨씬 더 시스템을 안정할 수음
io software단에서 에러 리포팅 관련된 것들은 cpu dependency가 높다.
Allocating and releasing dedicated devices
Device-independent block size
Spooling
버퍼링이랑 비슷한데 application이 io장치에 데이터를 쓰려면 커널한테 시스템 calll을 요청하고 쓸 데이터를 커널한테도 쓴다. 커널이 버퍼에 쓸 내용들을 저장하고 그 내용을 아이오 장치에 전달을 한다. 만약 아이오가 엄청나게 느리면.. 커널의 버퍼링 사이즈가 계속 커져서 메모리 사이즈를 계속 잡아먹게 된다.
- 그래서 어플리케이션에서 커널을 통해서 메모리를 버퍼링하는 것이 아니라 어플리케이션에서 file로 버퍼링을 한다.
- 버퍼링이랑 비슷한데 메모리에 하냐 file에 하냐의 차이다