센로그

12. I/O System 본문

CS/운영체제

12. I/O System

seeyoun 2023. 12. 6. 01:21

◆ 요점 정리

 

1. I/O 명령 전달 방식

  • Direct I/O
  • Memory Mapped

 

2. I/O 처리 방식

  • Polling
  • Interrupt
  • DMA 
    • CPU 거치지 않고 디스크로부터 바로 메모리로 올림

 

3. I/O 요청 후 동작 방식

  • Blocking: I/O 데이터 준비될 때까지 기다림
  • Non-Blocking: I/O 데이터 없으면 걍 리턴
  • Asynchronous: I/O 데이터 준비될 시 시그널(인터럽트)

 


◆ I/O Hardware

I/O 하드웨어들은 signal을 보냄으로써 컴퓨터 시스템과 통신함.

 

대표적인 I/O 하드웨어들의 종류는 다음과 같다.

  • 포트: 어떤 디바이스가 연결되어있는 지점
  • 버스: 데이터나 명령어가 움직이는 공간.
    - 다양한 종류가 있음.
        - GPU 같은 거 연결하는 PCIe bus
        - USB나 키보드 등 비교적 느린 디바이스을 연결할 때 사용하는 expansion bus
        - SAS 컨트롤러는 디스크를 연결하기 위한 컨트롤러. 디스크를 연결하는 버스의 느낌.
  • 컨트롤러: 포트, 버스, 디바이스들을 동작시키는 장치.

 

이전에 배웠듯, 디바이스 드라이버OS속해있는 SW이고, 얘네가 각자의 디바이스 컨트롤러(HW)연결되어 있음

 

  • 디바이스 드라이버컨트롤러에 있는 특별한 레지스터에 접근해서 명령이나 주소, 데이터들을 쓰거나 읽음.
    • 종류: Data-in register, data-out register, status register, control register

 

각 디바이스들에는 address가 있는데, 이는 CPU가 I/O 디바이스에게 명령을 내릴 때 사용된다.

 


 CPU가 I/O 디바이스에게 명령을 전달하는 방식

CPU는 입출력을 수행하기 위해서 컨트롤러에게 데이터와 명령을 어떻게 전달하는가?에 관한 이야기.

 

다음 두 가지 방식이 있다. 

  • Direct I/O 방식
    : 원하는 포트의 address로 데이터를 보내는 작업을 I/O instruction으로 실행하는 것
    • 즉 데이터를 보낼 포트 주소를 가지고, 직접 버스를 통해서 데이터를 주고받는 명령 실
※ 메모리와 I/O장치 영역을 분리하는 방식으로, 메모리에서 데이터를 읽고 쓰는 명령어와 I/O장치에서 읽고 쓰는 명령어가 다름!

 

  • Memory mapped 방식 [요즘은 보통 이 방식 사용]
    • 메모리 맵 사용
      : 메모리의 특정 영역에 접근하면 I/O 디바이스에 접근할 수 있도록 매핑해주는 것.
      • 각 디바이스에 접근할 수 있는 메모리 주소가 정해져 있고, 해당 메모리 공간에 데이터를 쓰거나 읽으면서 디바이스와 소통하는 방식. 
        위 예시 그림에서, 메모리주소 9000-90FF번은 사운드 컨트롤러에 매핑되어 있는 것임.

 


◆ I/O 방식

방금 본 것은 디바이스에게 I/O 명령을 전달하는 방식이었고. 이번엔 실제 I/O 처리 방식을 보자.

 

입출력 방식으로 다음 세 유형이 존재한다.

  • Polling (busy waiting)
  • Interrupt
  • DMA

하나하나 살펴보자.

 


◆ Polling

- 현재 이 디바이스 컨트롤러가 busy한지(뭔가 처리하고 있는지) 아닌지를 계속 체크함.(busy bit 체크)
- 그러다가 Busy한 상태가 아닐 때, 즉 데이터를 읽고 쓸 수 있는 상태가 되면 data in 또는 data out 레지스터에 접근하는 방식

 

 

< 과정 >

다음은 polling 방식으로 I/O 디바이스에 writing하는 과정이다.

  1. 호스트는 컨트롤러의 busy bit가 지워질 때(0이될 때)까지 상태 레지스터(status register)를 반복해서 읽음
  2. 호스트가 명령 내용에 따라 커맨드 레지스터(command register)의 write bit를 1로 설정함. 
    - 그리고 실제 write할 데이터를 data out 레지스터에 복사해놓음.
  3. 호스트가 command-ready bit를 1로 설정함.
    - command-ready bit는 디바이스가 명령을 받았는지 체크하는 비트임
  4. 컨트롤러가 busy bit를 1로 설정하고, 전송을 실행함
    - 컨트롤러가 커맨드 레지스터를 보고 자신에게 온 커맨드가 write임을 판독함
    - 실제로 데이터가 기록이 된 data out 레지스터를 읽어서, bit정보를 가져와서 디바이스에 출력함.
  5. 전송이 완료되면 컨트롤러가 command-ready bit를 0으로 지움
    - 그리고 입출력 성공을 알리기 위해 상태 레지스터의  busy bit, error bit도 0으로 지움

 

 

* 주의할 점은, 이 방법은 Busy Waiting 방식이라는 것.

1번 과정에서 장치로부터 입출력 완료를 대기하는 과정에서 busy waiting이 발생

  • 따라서 입출력 장치가 느리다면, 비효율성을 초래함
    → Controller가 CPU에게 통보하는 Interrupts방식이 더 효과적!

 


◆ Interrupt

 

- CPU는 프로세스의 각 instruction을 실행할 때마다 매번 interrupt-request line(CPU의 핀들 중에 전기적 interrupt 시그널을 받을 수 있는 라인)을 체크함. 
- 만약 인터럽트 발생한 경우, 현재 상태를 저장한 후 인터럽트 벡터(인터럽트 핸들러의 주소를 가리키고있는 벡터)로 점프해서 인터럽트 핸들러 루틴 실행. (각 인터럽트에 대해 인터럽트 핸들러 갖고 있음)

 

대부분의 CPU는 두 개의 Interrupt request line을 갖고 있음.

이들은 아래 두 종류의 인터럽트를 받는 각각의 라인임

  • Nonmaskable 인터럽트: 메모리 에러같은 거 발생했을 때 나는 인터럽트
    → 즉시 처리되어야 함!!!
  • Maskable 인터럽트: 일반적인 인터럽트. I/O 디바이스 따위에서 에서 오는 인터럽트
    → 무시되거나 연기될 수 있음.

 

인터럽트 벡터 (Interrupt vector)
: 인터럽트를 올바른 인터럽트 핸들러로 디스패치함

  • 특정 인터럽트 핸들러의 주소를 저장하고 있음
  • 한 인터럽트 넘버가 서로 다른 디바이스를 처리하는 경우가 있기도 함ㅇㅇ
    이때 실제로 필요한 디바이스가 뭔지 확인해서 처리하는 것을 Interrupt chaining 이라고 함.
  • OS는 대응하는 인터럽트 핸들러를 부트 시에 설치함.

 

 

인터럽트는 사실 굉장히 많은 상황에서 쓰임

  • Exception (0으로 나누기 등)
  • Page fault (메모리 접근 에러)
  • System call (trap을 통한 커널 호출)
  • etc...

 

 

  • 멀티 프로세서 시스템의 경우 각 CPU가 인터럽트를 concurrently하게 처리할 수도 있음.
    (물론 운체가 지원해주는 경우에.)
  • 폴링은 busy waiting이라 하던 일을 중단하지 못하지만, 인터럽트는 잠시 중단하고 실행하는 것임
    → 시간에 민감한 프로세스에 사용됨.

 


Direct Memory Access (DMA)

디스크가 CPU를 거치지 않고 바로 메모리에 접근하는 방식
  • 용량이 큰 데이터의 이동을 위하여 programmed I/O 방식을 회피하는 것
※ Programmed I/O (one byte at a time)
: 상태 비트를 감시하고, 한번에 1바이트씩 controller register에 옮기는 것

 

  • 지금까지는 CPU를 거쳐서 (Directy I/O나 Memory mapped 같은 방식을 사용해서) 메모리 접근했음.
  • 그러나 DMA 방식은 프로세서와 관련 없이, 디스크에서 메모리로 데이터를 바로 올리는 것.
    → I/O 디바이스 사용할 때 보다는 효율적 접근 가능
    • 프로세서는 디스크에서 메모리로 데이터를 올리는 사이에 다른 작업을 할 수 있음.
    • 데이터 전송이 완료되면 CPU가 곧바로 데이터에 접근할 수 있음.

 

  • 보통 대용량 데이터를 옮길 때 사용함
    CPU가 "DMA 사용해서 큰 데이터 옮겨놔~" 한 다음에 다른 작업 처리하러 가면 됨. 
  • DMA 컨트롤러가 있어야 함. 

 


◆ Kernel I/O Structure

  • 커널은 I/O 시스템 콜을 통해 실제 디바이스의 동작들을 캡슐화 함
    사용자가 불법적인 입/출력을 못하게 함.
  • 디바이스 드라이버 계층이 여러 I/O 하드웨어들의 차이점을 숨기고, 이들을 간단한 표준 인터페이스들로 보이도록 포장함.
    I/O subsystem이 하드웨어와 독립적으로 되어서 OS 개발자의 작업을 간단하게 해줌.

 


◆ Block and Character Devices

어떤 단위로 움직이느냐에 따른 I/O 디바이스의 두 가지 유형이 있다.

  • Block Device
    : 블록 단위로 움직이는 I/O 디바이스. (ex: 디스크)
    - (블록 내에서) 읽고(read()), 쓰고(write()), 위치를 옮기고(seek()).. 이런 커맨드들을 제공함
    - 직접적으로 디바이스에 접근할 수도 있고, 파일 시스템을 통해서 접근할 수도 있음. 보통은 파일 시스템 인터페이스를 통해서 디스크에 접근함
  • Character Device
    : 캐릭터 단위로 움직이는 I/O 디바이스. (ex: 키보드. 키보드 누르면 캐릭터 하나가 움직임)
    - get(), put() 등 하나의 데이터를 주고받을 때 사용하는 커맨드를 제공함.

 


◆ Clocks and Timers

시간과 관련한 I/O 디바이스로는 ClockTimer가 있다.

 

  • Clock
    : 1, 0이 반복되는 주기적인 signal을 의미함.
    • CPU가 동작할 때 Clock에 맞추어 동작한다.
    • Clock이 1→0으로 움직이는 걸 한 사이클이라 함.
    • 한 Clock 사이클 동안 여러 instruction을 처리할 수도 있음 ㅇㅇ
  • Timer
    : 고정된 시간마다 어떤 Task를 해야 할 때 사용됨. (타이머 인터럽트; 주기적인 인터럽트)
    • 하드웨어로 구현된 타이머 중에 Programmable interval tiemer라는게 있음
      : Clock 한 칸마다 count value(초기값은 0)를 올리는데, 이때 어떤 임계점을 정해놓고 임계점에 도달했을 때 interrupt를 발생하도록 하는 것.

 


◆ Nonblocking and Asynchronous I/O

I/O 요청을 한 후에 어떻게 동작할지에 관한 이야기.

 

다음 세 방식 중 하나로 동작함.

  • Blocking: I/O 요청한 다음에 I/O 데이터가 준비될 때까지 기다림
  • Nonblocking: I/O 요청해보고, I/O 데이터가 없으면 안 기다리고 리턴함
  • Asynchronous: 인터럽트 처럼, I/O요청한 다음에 다른 거 하고 있고, I/O 데이터가 준비가 되면 알림을 받는 방식.

 


◆ I/O Request Life Cycle

일반적인 I/O 요청 생명 주기.

 

기본적으로 유저 리퀘스트 시스템 콜을 통해 커널에게 I/O 요청함.

커널이 시스템 콜 핸들링. 이 요청을 바로 처리할 수 있는지 아닌지 확인함.

(Yes) 만약 (커널이 미리 캐싱해놔서) 바로 처리할 수 있다면? 처리 결과를 시스템 콜에 대한 응답으로 바로 알려줌

(No) 그게 아니라면, 디바이스 드라이버한테 요청을 전달하고, 얘디바이스 컨트롤러한테 데이터 달라고 요청 함.

→ 그러면 디바이스 컨트롤러는 실제로 I/O를 수행하고, 수행이 종료되면 다 했다고 인터럽트 보냄

인터럽트 핸들러가 디바이스 드라이버에게 그 동작을 전달해줌

  디바이스 드라이버가 시스템 콜에 대한 응답으로써 유저 프로세스에게 처리 결과를 갖다줌

'CS > 운영체제' 카테고리의 다른 글

15. File-System Internals  (0) 2023.12.11
13. File-System Interface  (0) 2023.12.06
11. Mass-Storage Structure  (0) 2023.12.05
10. Virtual Memory  (0) 2023.12.04
9. Main Memory  (0) 2023.12.04
Comments