입출력

입출력(I/O)이란 컴퓨터 시스템이 컴퓨터 외부의 주변 장치들과 데이터를 주고받는 것을 말합니다.

입출력 방식에는 동기식 입출려과 비동기식 입출력이 있습니다.

동기식 입출력

  • 동기식 입출력은 입출력 요청 후 입출력 작업이 완료된 후에야 CPU의 제어권이 그 프로그램에게 다시 넘어갈 수 있는 방식을 말합니다.

예시

프로그램이 디스크에서 어떠한 정보를 읽어오라는 요청을 했을 때, 디스크 입출력이 완료되기까지는 어느 정도의 시간이 걸리게 됩니다.

이 때, 동기식 입출력은 입출력이 진행되는 동안 그 프로그램의 다음 명령을 수행하지 않고 기다리게 됩니다.

그러다가 입출력이 완료되어 인터럽트를 통해 그 사실이 전달된 후에야 CPU의 제어권이 그 프로그램에게 넘어가서 다음 명령을 수행할 수 있게 됩니다.

따라서, 동기식 입출력에서는 입출력 연산이 끝날 때까지 CPU는 아무 일을 할 수 없게 됩니다.

이 경우는 논 블록 동기 입출력입니다.

단점

CPU의 명령 수행 속도는 빠른 반면 외부 장치에서 데이터를 읽어오는 등의 입출력 연산은 상대적으로 속도가 느립니다. 그럼에도 불구하고 입출력이 완료될 때까지 기다렸다가 사용자 프로그램에게 CPU 제어권을 방식은 CPU가 입출력이 완료될 때까지 아무 일도 하지 못하기 때문에 자원의 낭비가 발생합니다.

블록 동기 입출력

따라서 일반적으로 프로그램이 입출력을 수행중인 경우 CPU를 다른 프로그램에게 이양해 CPU가 계속 쉬지 않고 일할 수 있도록 관리합니다.

입출력이 완료될 때까지 그 프로그램에 CPU를 할당하더라도 명령을 수행하지 못하는 상태를 만들어야 합니다.

위와 같은 상태를 봉쇄 상태(block state)라고 합니다.
봉쇄 상태의 프로그램에게는 CPU를 할당하지 않고, CPU를 할당하면 곧바로 작업을 수행할 수 있는 프로그램들에게만 CPU를 할당합니다.


다수의 입출력 연산이 동시에 요청되거나 처리되는 경우

예시
A라는 프로그램이 디스크에 원래 1이던 파일의 내용을 3으로 바꾸는 입출력 연산을 요청했습니다.

입출력 연산을 수행중일 때 A에게서 CPU를 선점해 B에게 할당했습니다.

프로그램 B가 CPU를 할당받고 수행중일 때, 이 프로그램 역시 입출력 요청을 할 수 있습니다. 프로그램 B가 요청한 입출력 연산이 A가 접근하려는 곳과 동일한 파일의 내용을 1 증가시키는 연산입니다.

A => 1->3
B => 1 증가

이 경우 매 시점 두 개 이상의 입출력 연산을 수행할 수 있다면, 컨트롤러는 A와 B의 순서를 바꾸어 수행할 가능성이 있습니다.

즉, 1 -> 3 -> 4로 바뀌어야 하는데, 1 -> 2 -> 3으로 바뀔 수도 있다는 것입니다.

해결 방법

따라서 동기식 입출력에서는 입출력 요청의 동기화를 위해 장치별로 큐(queue)를 두어 요청한 순서대로 처리할 수 있도록 했습니다.

프로그램 A가 먼저 요청했으면 이를 먼저 큐에 넣고, 그 후에 발생한 B의 요청을 A의 요청 뒤에 삽입합니다.

  • [그림 1] 디바이스 큐

동기식 입출력은 입출력이 완료될 때까지 입출력과 관련 없는 프로그램을 수행하도록 하고, 요청된 입출력 연산이 완료되면 CPU에게 입출력이 완료되었음을 알려주는 방식으로 진행합니다.

연산 완료의 통보는 인터럽트를 통해서 수행되며, 이 경우 운영 체제 커널은 인터럽트 처리 루틴으로 가서 입출력 연산을 끝낸 프로그램이 CPU를 할당받을 수 있도록 그 프로그램의 상태를 봉쇄 상태(block state)로부터 해제시키게 됩니다.

비동기 입출력

비동기식 입출력은 입출력 연산을 요청한 후에 연산이 끝나기를 기다리는 것이 아니라 CPU의 제어권을 입출력 연산을 호출한 그 프로그램에게 곧바로 다시 부여하는 방식을 말합니다.

비동기식 입출력에서는 입출력이 필요없는 작업을 먼저 수행하고, 읽어오는 데이터가 반드시 있어야 수행할 수 있는 일들은 입출력이 완료된 후에야 수행하게 됩니다.

또한, 입출력 요청이 디스크에서 읽어오는 요청이 아니라 디스크에 쓰는 요청이라면 쓰기 작업이 완료되기 전에도 다음 명령을 수행할 수 있으므로 비동기식 입출력이 사용될 수 있습니다.

비동기식 입출력과 동기식 입출력의 비교

  • [그림 2] 동기식 입출력과 비동기식 입출력

동기식 입출력

  1. 사용자가 I/O 요청을 하면 동기식 입출력에서는 먼저 운영 체제의 커널로 CPU의 제어권이 넘어와서 입출력 처리와 관련된 커널의 코드가 수행됩니다.
  2. 입출력을 호출한 프로세의 상태를 봉쇄 상태(block state)로 바꾸어 입출력이 완료될 때까지 CPU를 할당받지 못하도록 합니다.
  3. 입출력이 완료되면 I/O 컨트롤러가 CPU에게 인터럽트를 발생시켜 입출력이 완료되었음을 알려줍니다.
  4. 그러면 이 프로세스의 봉쇄 상태를 해제시켜 CPU를 할당받을 수 있는 권한이 다시 생기게 됩니다.

비동기식 입출력

  1. CPU의 제어권이 입출력을 요청한 프로세스에게 곧바로 다시 주어지게 되며, 입출력연산이 완료되는 것과 무관하게 처리 간으한 작업부터 처리합니다.
  2. 입출력 연산이 완료되면 동기식과 마찬가지로 인터럽트를 통해 이를 CPU에게 알려 주게 됩니다.
  3. 그러면 그 시점부터 읽어온 데이터를 필요로 하는 명령을 수행할 수 있게 됩니다.

일반적으로는 입출력 요청을 운영 체제에게 하게 되면 해당 프로그램의 입출력이 완료될 때까지 그 프로그램을 봉쇄시키는 동기식 입출력을 사용합니다.

이 때 운영 체제는 장치별로 입출력 처리를 기다리는 프로세스를 줄 세워 관리함으로써 동기성을 보장하게 됩니다.

마지막으로 비동기/동기, 블록/논블록에 대해서 잘 정리한 포스트를 소개합니다.
https://musma.github.io/2019/04/17/blocking-and-synchronous.html
https://homoefficio.github.io/2017/02/19/Blocking-NonBlocking-Synchronous-Asynchronous/
https://deveric.tistory.com/99

profile
데이터데이터데이터!!

0개의 댓글