CS 및 면접 질문

Block I/O vs Non-Block I/O

ho-bolt 2022. 6. 15. 23:16

 

I/O 종류


I/O란 Input/Output인 입출력을 말한다.

  • network(socket)
  • file
  • pipe (process 간에 통신할 때 사용되는 개념)
  • device (모니터, 키보드, 등): 네트워크 통신은 소켓을 통해 데이터가 입출력 된다.
  • socket

소켓

: 네트워크 통신은 소켓을 통해 데이터가 입출력 된다.

2개의 컴퓨터의 프로세스가 데이터를 주고 받기 위해서는 소켓을 열고 소켓을 통해서 데이터를 주고받을 수 있다.

backend server

: 네트워크 상의 요청자들과 각각 소켓을 열고 통신한다.

밖에 있는 클라이언트들이 소켓을 열고 요청을 한다.

백엔드도 소켓을 열고 받은 요청의 클라이언트와 상호작용한다.

OS 레벌에서 Block I/O와 Non-Block I/O가 어떻게 동작하나

Block I/O


: I/O 작업을 요청한 프로세스/스레드는 요청이 완료될 때까지 블락됨

  1. 스레드에서 작성된 코드가 쭉 실행
  2. 1번을 실행하다 blocking sysetmcall이 입력되면 스레드는 블락됨 => 스레드가 동작을 멈춤
  3. 시스템 콜에 의해 커널로 감
  4. 커널에서는 read I/O 실행
  5. 해당 디바이스에서 읽을 준비 됐다고 응답 줌
  6. 커널이 응답 받고 준비된 데이터를 커널 스페이스에서 유저 스페이스로 옮김
  7. 그때 블락되었던 스레드가 풀림
  8. 나머지 코드 실행

소켓에서 Block I/O

  • Socket S에서 A로 데이터를 보내려고 한다면 A는 기다려야 함
    • 여기서 기다린다는 의미란 !?!
    • 소켓에는 2가지 버퍼가 있다.
    • READ SYSTEM CALL이 오면 recv_buffer에 데이터가 들어올 때까지 read system call을 요청한 스레드는 블락됨
  • Socket S입장
    • write 하면 send_buffer에 전송하려는 데이터를 씀
    • 이 때 send_buffer에 데이터가 차는 데 가득 차면 비워질 때까지 블락됨
  • 정리
    • 각각의 send_buffer, recv_buffer의 상태에 따라 블락이 된다.

Non-Block I/O


: 프로세스/스레드를 블락시키지 않고 요청에 대한 현재 상태를 즉시 리턴 

1. 스레드에서 non-bolcking으로 read systemcall 호출

2. system call하는 순간 커널모드로 스위칭

3. 커널에서 read I/O 실행 

4. 커널에서 바로 리턴 때림 (리눅스 기준 -1, EAGAIN, EWOULDBLOCK)의 에러와 같이 

5. 블락이 아니라 바로 스레드는 다음 코드를 실행 

6. 그러던 중 I/O 디바이스로부터 데이터 읽을 준비 됐다는 응답이 커널로 옴 

7. 커널은 데이터 준비 함 

8. 스레드는 non-bolcking으로 다시 시스템 요청 

9. 이때 전에 요청했던 데이터가 리턴되면서 유저 스페이스로 옮겨감 

10. 받은 데이터 읽고 나머지 작업 실행 

 

정리 

non-block I/O는 블락되지 않고 즉시 리턴하기 때문에 스레드가 다른 작업을 수행할 수 있다. 

 

소켓에서 Non-Block I/O

  • S에서 A로 데이터 보냄 
  • recv_buffer에 데이터가 있는 지 read로 확인 
  • 데이터가 없으면 없다고 알려주고 read system call은 바로 종료 ( 블락 안됨 ) 
  •   send_buffer에 데이터가 가득 쳤어도 write system call이 종료되는 게 아니라 해당하는 에러코드와 함께 반환된다. 

 

 

Non-block I/O 결과 처리 방식

non-block I/O 이슈 

 그렇다면 I/O 작업 완료는 어떻게 확인하는 것인가? 

1. 완료되었는 지 반복적으로 확인 

  •  완료된 시간과 완료를 확인한 시간 사이의 갭으로 인해 처리 속도가 느려질 수 있음 
  • 반복적으로 확인하며 cpu 낭비가 발생 

 

2. I/O multiplexing (다중 입출력) 사용 


: 관심있는 I/O 작업들을 동시에 모니터링하고 그 중 완료된 I/O 작업들을 한 번에 알려줌 

 

 

  • multiplexing 으로 system call을 하면 상태에 따라 스레드를 블락시킬 수도 있고 안시킬 수도 있다. 

I/O 멀티 플렉싱 종류 

  • select
  • poll
  • epoll
  • kqueue
  • IOCP(I/O completion port) 
  • => 이 3개가 많이 쓰임 

 

3. callback/singal 사용

  • aio_read를 non-bolcking으로 호출 
  • 커널에서 read i/o실행
  • 스레드는 독립적으로 실행 
  • 이때 데이터 응답이 오면 callback이나 singal 형태로 실행 

callback/signal 종류 

  • POSIX AIO (여러 운영체제에서 표준화된 것 ) 
  • LINUX AIO

=> 하지만 많이 사용되지는 않음 

 

결론 

Non-Block I/O를 통해 I/O요청의 완료 전에도 다른 일을 할 수 있다!!! 

 

 

 

 

참조

쉬운 코딩님의 강의를 들으면서 정리한 겁니다. 

https://www.youtube.com/watch?v=mb-QHxVfmcs

728x90