I/O System

Seongho·2022년 6월 6일
1

운영체제

목록 보기
11/12

Kernel I/O Structure

kernel에 입출력 장치마다 device driver가 있는데, 얘네가 입출력을 담당한다.

I/O Device를 나누는 기준

  • Block Device : 고정 크기의 블록단위로 데이터를 주고받는다. 버퍼를 사용하고, 순서가 없이 각각의 주소를 이용해 접근하고 seek operation이 필요하다.
    ex) Disk,,,...
  • Character Device : 데이터가 스트림으로 한 문자씩 전송되고 순서가 있다. 주소를 이용해 접근하지 않아 seek operation이 필요 없다.
    ex) 키보드, 마우스, 프린터,,,

Device Controller(하드웨어 장치)

디바이스 컨트롤러는 비트 스트림을 블록 단위로 변경(하드웨어->소프트웨어)하고 메인메모리에 이용할 수 있게 해준다. 또한, 여러 장치를 다룰 수 있다.

Device Driver

입출력 장치들은 각각의 레지스터들을 갖고 있다 예를들면, 프린터기에서 잉크가 있는지 없는지 set하는 레지스터.. 이런거.. 그래서 각각의 디바이스 드라이버는 각 장치에 맞는 레지스터를 다루는 명령어를 갖고 있다. 그래서 삼성 프린터기 설치한다 하면 같이 설치하는 소프트웨어로 삼성 프린터기 드라이버를 같이 설치함..

입출력 장치에 접근하는 방법

  • Direct I/O : I/O 포트 주소에 대한 특별한 명령어를 사용해 접근한다.
  • Memory-mapped-I/O : 메모리의 일부 주소를 입출력장치에 할당하는 방법으로, CPU는 표준 입출력 명령으로 입출력을 수행한다. 입출력 디바이스 드라이버는 보통 C로 만들어지고 특별한 입출력장치 보호 매커니즘이 필요 없다.

CPU가 I/O작업이 끝났는지 아는 방법

  • Polling : cpu가 컨트롤러에 계속 물어보는 방법으로, 간단하고 입출력이 간단히 빨리 끝나는 경우에만 효율적이다. 하지만, 보통은 비효율적이고 낮은 우선순위의 장치는 한번도 CPU의 제어를 당할 수 없을 수도 있다.
  • Interrupt : I/O 관련 명령어를 수행한 CPU는 다른 명령어를 수행하고, 명령어 하나를 처리할 때마다 인터럽트 발생 여부를 확인한다. I/O controller가 작업이 끝나면 Interrupt controller에 신호를 보내면 interrupt 발생시키고 CPU가 인터럽트를 확인하면 CPU의 레지스터 값들을 저장하고 어떤 종류의 인터럽트인지 확인한 후 ISR(인터럽트 서비스 루틴) 코드를 실행한다.
    보통 Polling보다 효율적이고, CPU가 입출력 작업동안 다른 일을 할 수 있지만, 인터럽트 작업이 프로그램 실행을 느리게 만들 수 있고, 아주 작은 입출력에는 오버헤드가 발생한다. (1byte 읽어오는데 인터럽트?->비효율)

Programmed I/O vs DMA

  • Programmed I/O : 입출력을 하는동안 CPU가 계속 사용된다.
  • DMA : 원칙적으로 메모리는 CPU에 의해서만 접근 가능한 하드웨어인데, CPU가 모든 입출력 작업을 담당하면 비효율적이기 때문에 이를 해결하기 위해 DMA가 만들어졌다. 디바이스 컨트롤러가 I/O 버퍼로부터 byte단위로 정보를 읽어오는게 아니라 block단위로 정보를 읽어와 CPU에 인터럽트를 발생시켜 해당 작업의 완료를 알린다. Block 단위로 데이터에 접근하기 때문에 대용량을 빠르게 전송하는 경우에 사용한다.
    **대용량 전송-DMA / 작은 데이터 전송-PIO

Blocking vs Non-blocking I/O

  • Blocking I/O : I/O가 완료될 때까지 프로세스가 일시 중단되고 대기하고 있는다.
    예를들면, 카카오톡으로 메세지를 보낼 때, 메세지를 보낼 때까지 계속 대기하고 있는 것이다.
  • Non-blocking I/O : 입출력을 수행하면 일단 리턴을 빠르게 하고, CPU는 다른 작업을 수행한다.
    Blocking이 좋은지, Non-Blocking이 좋은지는 정해진 것이 없다!!!

입출력 소프트웨어 계층

  • Device Driver : Device-independent-I/O-Software와 상호작용하는 소프트웨어이다. OS와 상호 작용하는 방식에 대한 잘 정의된 모델 및 표준 인터페이스를 정의해야 한다. 디바이스 드라이버를 구현하는 방법에는 세가지가 있는데,
  1. 운영체제에 고정적으로 구현하는 방법
  2. 모듈로 만들어서 부팅할 때 로딩되는 방법
  3. 동적으로 입출력을 사용할 때 로딩되는 방법
    **윈도우 운영체제에서 블루스크린이 매우 심했는데, 이는 윈도우의 문제가 아니었다. 디바이스 드라이버의 문제였다.
  • Device-independent I/O Software : Device Driver와 상호작용하는 소프트웨어로, 운영체제를 만드는 회사에서 개발한다. 유닉스에서는 Device를 file로 생각하고 관리하는데, 이는 파일 입출력을 할 때 쓰는 open(), read(), write(), close(), ioctl()과 같은 시스템 콜을 통해서 Device를 컨트롤 한다는 뜻이다. 그래서 파일의 이름을 각 Device에 매핑되도록 한다. 일반적인 protection rule을 file에서 쓰는 것과 함께 쓸 수 있다는 장점이 있다(통일된 방식으로 모든 디바이스를 다룰 수 있다). Device-independent I/O Software가 에러 발생에 대해 해야할 일이 있는데, 그것은 error reporting과 handling error이다.
  1. error reporting - 어떤 디바이스에 대한 어떤 에러인지 사용자에게 reporting 해줘야 하고 에러가 프로그래밍 에러인지, I/O 에러인지 판단해야 한다.
  2. handling error - 에러 코드와 함께 시스템 콜을 리턴하고 몇번 다시 시도한다. 무시해도 ㅗ디는 에러인 경우 무시하고 에러가 심각한 경우 프로세스를 죽이거나 시스템을 다운시킨다.
  • User-Space I/O SW : C에서 fopen(), open() 처럼 라이브러리 형태로 제공되고 이 라이브러리들은 다양하게 제공된다. 라이브러리를 이용하여 자신만의 라이브러리를 만들 수 있다.
    fopen()은 라이브러리 콜로, 내부에 open()을 호출하고, open()은 시스템 콜인데, 그러면 fopen()을 쓰는 것이 좋은가? open()을 쓰는 것이 좋은가? fopen()은 내부에 버퍼를 두고 효율적으로 작동하게 만들어졌다. 파일이 아닌 다른 장치에는 open()을 사용하는 것이 효율적이다. 따라서, 그냥 상황에 따라 프로그래머가 선택하여 사용하는 것이다.
profile
Record What I Learned

0개의 댓글