I/O 작업은 Kernel level에서만 수행할 수 있다. 따라서, Process, Thread는 커널에게 I/O를 요청해야 한다.
I/O Blocking 형태의 작업은
(1) Process(Thread)가 Kernel에게 I/O를 요청하는 함수를 호출
(2) Kernel이 작업을 완료하면 작업 결과를 반환 받음.
특징
여러 Client 가 접속하는 서버를 Blocking 방식으로 구현하는 경우
-> I/O 작업을 진행하는 작업을 중지 -> 다른 Client가 진행중인 작업을 중지하면 안되므로, client 별로 별도의 Thread를 생성해야 함 -> 접속자 수가 매우 많아짐
이로 인해, 많아진 Threads 로 컨텍스트 스위칭 횟수가 증가함,,, 비효율적인 동작 방식
I/O 작업이 진행되는 동안 User Process의 작업을 중단하지 않음.
진행 순서
User Process가 recvfrom 함수 호출 (커널에게 해당 Socket으로부터 data를 받고 싶다고 요청함)
Kernel은 이 요청에 대해서, 곧바로 recvBuffer를 채워서 보내지 못하므로, "EWOULDBLOCK"을 return함.
Blocking 방식과 달리, User Process는 다른 작업을 진행할 수 있음.
recvBuffer에 user가 받을 수 있는 데이터가 있는 경우, Buffer로부터 데이터를 복사하여 받아옴.
이때, recvBuffer는 Kernel이 가지고 있는 메모리에 적재되어 있으므로, Memory간 복사로 인해, I/O보다 훨씬 빠른 속도로 data를 받아올 수 있음.
recvfrom 함수는 빠른 속도로 data를 복사한 후, 복사한 data의 길이와 함께 반환함.
EWOULDBLOCK: non-blocking 소켓에서 I/O 작업이 즉시 이루어질 수 없을 때 발생하는 오류. 예를 들어, non-blocking 소켓에서 데이터를 읽으려 했지만 데이터가 아직 준비되지 않았다면, EWOULDBLOCK 오류가 발생.
1. 텍스트 에디터 사용:
대부분의 텍스트 에디터는 사용자가 파일을 저장하거나 열려고 할 때 blocking I/O를 사용합니다. 예를 들어, 사용자가 "파일 저장"을 클릭하면, 에디터는 해당 파일을 저장하는 동안 다른 작업을 수행하지 않습니다. 파일 저장이 완료될 때까지 기다린 후에만 사용자에게 다른 작업을 수행하도록 허용합니다.
2. 웹 서버:
간단한 웹 서버에서 클라이언트의 요청을 기다릴 때, 서버는 blocking 모드로 요청을 기다립니다. 요청이 도착할 때까지 서버는 다른 작업을 수행하지 않습니다.
3. 파일 I/O
파일 시스템에서 데이터를 읽거나 쓸 때, 해당 I/O 작업이 완료될 때까지 프로그램은 대기. 예를 들
어, 프로그램이 디스크에 있는 큰 파일을 읽어올 때, 그 파일을 모두 읽어오는 동안 프로그램은 다른 작업을 수행하지 않는다.
하지만, 모던 운영체제와 프로그래밍 언어에서는 논블락킹 파일 I/O나 비동기 파일 I/O를 제공하는 경우도 있음. 이 방식을 사용하면 프로그램이 파일 작업을 대기하는 동안 다른 작업을 계속 수행할 수 있다.
온라인 채팅 프로그램:
여러 사용자와 동시에 메시지를 주고받는 채팅 프로그램에서는 non-blocking I/O를 사용함. 서버는 어느 사용자로부터 메시지가 올지 모르기 때문에, 모든 연결에 대해 non-blocking 모드로 데이터를 체크한다. 메시지가 도착하면 해당 메시지를 처리하고, 아무 메시지도 없다면 다른 연결을 체크하며 계속 진행.
게임 서버:
실시간 멀티플레이어 게임에서 게임 서버는 여러 플레이어로부터 동시에 데이터를 받아야 한다. 서버는 non-blocking I/O를 사용하여 여러 플레이어의 입력을 동시에 체크하고, 해당 입력에 따라 게임 상태를 업데이트.
이렇게 blocking I/O는 특정 작업의 완료를 기다리는 동안 다른 작업을 중단시키는 반면, non-blocking I/O는 여러 I/O 작업을 동시에 처리하거나, I/O 작업이 진행되는 동안 다른 작업도 계속 수행할 수 있도록 함.