CS

[CS] Blocking I/O & Non-Blocking I/O

kyoulho 2024. 8. 12. 13:21

블록 I/O

I/O 작업을 요청한 프로세스나 스레드가 작업이 완료될 때까지 대기하는 방식이다. 이 방식은 단순하고 직관적이지만, 블록 상태로 인해 자원 활용에 비효율적일 수 있다.

물론, 스레드가 I/O 작업 때문에 블록 되는 동안, CPU 코어는 다른 스레드에게 할당될 수 있다. 이 경우 CPU는 여전히 다른 작업을 수행할 수 있지만 대량의 스레드가 블록 상태로 대기하면 시스템 자원(메모리, 스레드 관리 오버헤드 등)을 낭비할 수 있다.

동작 과정

  • 스레드가 read 시스템콜을 수행한다.
  • 스레드는 블락 상태가 되어 커널 모드로 전환된다.
  • 커널이 I/O 작업을 수행하고 관련 디바이스에 요청을 보낸다.
  • 디바이스가 요청을 처리하고 커널로 응답을 보낸다.
  • 커널이 유저 스페이스로 데이터를 이동시킨다.
  • 스레드는 작업이 완료되면 다시 실행된다.

Socket에서의 블록 I/O

SocketS가 SocketA로 데이터를 전송하는 예를 든다.

  1. SocketA가 read 시스템콜을 호출한다.
  2. SocketA는 receive 버퍼에 데이터가 들어올 때까지 블락된다.
  3. SocketS가 write 시스템콜을 호출한다.
  4. SocketS는 send 버퍼에 공간이 생길 때까지 블락된다.

 

논블록 I/O

논블록 I/O는 I/O 요청을 보낸 프로세스나 스레드가 대기하지 않고 즉시 상태를 반환받는 방식이다.

프로세스나 스레드가 블락되지 않으므로 자원을 효율적으로 활용할 수 있다.

동작 과정

  • 스레드가 read 시스템콜을 수행한다.
  • 스레드는 커널 모드로 전환된다.
  • 커널이 I/O 작업을 수행하고 관련 디바이스에 요청을 보낸다.
  • 커널이 스레드에 즉시 -1과 EAGAIN 또는 EWOULDBLOCK이라는 에러 코드를 응답한다.
  • 스레드는 대기하지 않고 이어서 다른 작업을 실행한다.
  • 디바이스가 I/O 작업을 처리하고 커널로 응답을 보낸다.
  • 스레드는 I/O 작업의 결과를 확인하기 위해 다시 read 시스템콜을 수행한다.
  • 커널이 유저 스페이스로 데이터를 이동시킨 후, 스레드는 작업이 완료되면 다시 실행된다.

Socket에서의 논블록 I/O

  1. SocketA가 read 시스템콜을 호출한다.
    • receive 버퍼가 비어있으면 시스템콜은 바로 종료된다.
    • receive 버퍼에 데이터가 들어올 때까지 블락되지 않고 즉시 상태를 반환받는다.
  2. SocketS가 write 시스템콜을 호출한다.
    • send 버퍼에 공간이 다 찼다면 시스템콜은 바로 종료된다.
    • send 버퍼에 공간이 생길 때까지 블락되지 않고 즉시 상태를 반환받는다.

 

논블록 I/O 결과 처리 방식

Polling (완료됐는지 반복적으로 확인)

논블록 I/O에서 작업이 완료되었는지 반복적으로 확인하는 방식이다. 이 방법은 주기적으로 시스템 호출을 통해 I/O 작업의 완료 상태를 체크한다. 스레드가 I/O 작업의 완료를 기다리는 동안 계속 상태를 체크하는 데만 CPU 자원을 소모한다.

I/O Multiplexing (다중 입출력)

여러 I/O 작업을 동시에 모니터링하고, 이들 중 완료된 I/O 작업을 효율적으로 처리하는 방식이다. 시스템 콜은 기다리고 있는 I/O 작업이 완료되었을 때만 호출된다.

  • 종류:
    • select: 가장 오래된 I/O 멀티플렉싱 기법으로, 여러 파일 디스크립터를 모니터링하고, 준비된 파일 디스크립터를 반환한다. 파일 디스크립터의 수가 많아질수록 성능이 저하되며, select 호출 시마다 모든 파일 디스크립터를 검사해야 한다.
    • pollselect와 유사하지만, 파일 디스크립터의 수에 제한이 없고, pollfd 구조체를 사용하여 효율적으로 모니터링할 수 있다. 파일 디스크립터가 많아지면 성능 저하가 발생할 수 있으며, 여전히 모든 디스크립터를 검사해야 한다.
    • epoll: Linux에서 제공하는 고성능 I/O 멀티플렉싱 기법으로, selectpoll의 성능 한계를 극복하기 위해 설계되었다. 파일 디스크립터의 상태 변화만을 처리할 수 있다. 대규모 파일 디스크립터를 효율적으로 처리할 수 있으며, 성능이 우수하다.
    • kqueue: BSD 계열 운영 체제에서 제공하는 I/O 멀티플렉싱 기법으로, 파일 디스크립터의 상태 변화를 감지하는 이벤트 기반 시스템이다. 높은 성능을 제공하며, 다양한 이벤트를 모니터링할 수 있다.
    • IOCP (I/O Completion Ports): Windows에서 제공하는 I/O 멀티플렉싱 기법으로, 비동기 I/O 작업의 완료를 효율적으로 처리할 수 있다. 높은 성능을 제공하며, 많은 동시 I/O 작업을 효율적으로 처리할 수 있다.

Callback / Signal

Callback과 Signal은 비동기 I/O 작업을 처리하는 방식으로, I/O 작업의 완료를 비동기적으로 알리고 이를 처리할 수 있게 해 준다. 이 방법들은 특정 이벤트가 발생했을 때 자동으로 호출되는 함수나 신호를 통해 작업의 결과를 처리한다.

  • 종류
    • POSIX AIO (Asynchronous I/O):  POSIX AIO는 POSIX 표준에 따라 비동기 I/O 작업을 지원하는 API이다. I/O 작업의 완료를 비동기적으로 처리하기 위해 aio_read, aio_write 등의 함수와 함께 완료를 알리는 신호를 사용할 수 있다.
    • Linux AIO (Asynchronous I/O): Linux AIO는 Linux 커널에서 제공하는 비동기 I/O API로, I/O 작업의 완료를 비동기적으로 처리할 수 있도록 해준다. io_submit, io_getevents, io_cancel 등의 시스템 콜을 사용하여 비동기 I/O를 관리한다.
728x90

'CS' 카테고리의 다른 글

[Linux] 호스트네임 관리와 네트워크 설정  (0) 2024.08.26
[Linux] 스왑 공간  (0) 2024.08.26
[CS] 스레드의 종류  (0) 2024.08.12
[CS] 운영 체제의 모드와 시스템 콜  (1) 2024.08.11
[CS] CPU Scheduler & Dispatcher  (1) 2024.08.11