IO
IO 종류
- network(socket)
- file
- pipe (IPC pipe)
- device (모니터 키보드 프린터 등등...)
OS 레벨에서 block I/O 동작 원리
thread -> read blocking system call 실행 -> 커널 모드 전환 및 thread block -> kernel에서 read I/O 실행(initiate read I/O) -> 커널에서 실행 완료 후 응답 받을 준비 됐다고 알림(read response) -> IO 처리 결과인 데이터를 kernel space에서 user space로 옮김 -> thread block 해제 -> 데이터를 가지고 다음 코드 실행
Socket 통신에서 block I/O
각각 recv_buffer와 send_buffer가 block 된다.
OS 레벨에서 non-block I/O 동작 원리
thread -> read non-blocking system call 실행 -> kernel에서 initiate read I/O 실행 -> kernel에서 -1 (EAGAIN or EWOULDBLOCK 이라는 에러 코드) 반환 -> thread는 이어서 다른 코드 실행 -> 커널에서 read response를 읽을 준비가 됐다는 응답을 보냄 thread에서 read non-blocking system call 실행 -> read response라는 응답을 받은 후라면 data를 kernel space에서 user space로 옮겨 옵니다.
Socket 통신에서 non-block I/O
block I/O와 달리 recv_buffer가 받을 내용이 없으므로 바로 종료(block X)된다. send_buffer가 꽉차서 전송이 더 이상 불가능한 경우 blocking을 해서 전송이 가능할 때까지 기다리는 것이 아닌, 적절한 에러 코드와 함께 전송할 수 없는 상태임을 바로 반환하게 된다.
Non Block IO의 종료를 확인 하는 방법
지속적으로 데이터가 준비될 때까지 확인하는 방식
- 완료된 시간과 완료를 확인한 시간 사이의 갭으로 인해 처리 속도가 느릴 수 있다.
- 완료됐는지 반복적으로 확인하는 것은 CPU 낭비가 발생
I/O multiplexing
- 관심있는 IO 작업들을 동시에 모니터링하고 그 중에 완료된 IO 작업들을 한 번에 알려주는 방식이다.
I/O multiplexing 종류
- select poll (성능 이슈로 사용 X)
- poll (성능 이슈로 사용 X)
- epoll (Linux)
- kqueue (Mac)
- IOCP(I/O completion port) (Window)
Callback/signal
thread가 aio_read non-blcking system call 실행 -> kernel이 initiate thread I/O 실행 -> thread는 다른 작업 수행 ->
kernel이 read response로 수행 완료를 알리면서 data를 user space로 옮기는데, 이 때, callback이나 signal을 통해서 처리된 데이터를 넘긴다.
- 종류
- POSIX AIO
- LINUX AIO
Async and Non Blocking
Asynchronous Programming
은 여러 작업을 동시에 실행하는 프로그래밍 방법론
을 뜻합니다.
Asynchronous Programming을 하는 방법에는
- Multithreading
- Non-block I/O
두 가지 방법이 있습니다.
백엔드 프로그래밍의 추세는 스레드를 적게 쓰면서도 Non-Block I/O를 통해 전체 처리량을 늘리는 방향으로 발전 중입니다.
문맥에 따른 synchronous vs asynchronous 비교
- case 1
- synchronous I/O = block I/O
- asynchronous I/O = non-block I/O
- case 2
- synchronous I/O : 요청자가 I/O 완료까지 챙기는 경우
- asynchronous I/O : 완료를 noti 주거나 callback으로 처리하는 경우
- case 3
- asynchronous I/O : blcok I/O를 다른 thread에서 실행하는 경우