흔히 Blocking = Synchronous
, Non-Blocking = Asynchronous
라고 착각한다.
📌 키워드:
제어권
Non-Blocking
: 제어권 넘김Blocking
: 제어권 넘기지 않음
위 표를 보면 이해하기 쉽다.
Blocking
시 붕어빵 사장님 앞에서 하염없이 기다린다. ( = 다른 일을 할 수 없다. )
Non-Blocking
시 붕어빵 사장님이 다른 일을 보러 갔다오라고 한다. ( = 내 할 일을 하면 된다. )
즉, 일 시작시 바로 제어권을 리턴해주는지, 할 일을 마친 뒤 리턴해주는지에 따라 나뉜다고 할 수 있다.
📌 키워드:
동시성
Synchronous
: 관심 많음Asynchronous
: 관심 없음
위 표를 보다시피
Synchronous
의 경우 기다리면서 계속 현재 상태를 체크한다.
Asynchronous
의 경우 붕어빵 사장님이 알아서 해준다. (Callback)
즉, 손님이 붕어빵을 신경 쓰는지(A->B), 붕어빵 사장님만 붕어빵(B)을 신경쓰는지에 따라 나뉜다고 생각할 수 있겠다.
Asynchronous
(비동기)는 호출시 Callback을 전달해 작업의 완료 여부를 호출한 함수에게 알린다. (이 덕분에 손님은 사장님이 부를 때까지 다른 일을 처리할 수 있었던 것)
I/O 작업은 Kernel level에서만 수행 가능해 Process
, Thread
는 Kernel
에게 I/O를 요청해야만 한다.
- Process(Thread)가 Kernel에게 I/O를 요청하는 함수 호출
- Kernel이 작업을 완료하면 작업 결과를 반환 받음
✔️ 여러 client가 접속하는 서버를
Blocking
방식으로 구현하는 경우I/O 작업을 진행하는 작업 중지
→ 다른 client가 진행 중인 작업을 중지하면 안되므로 client별로 별도의 Thread 생성
→ 접속자 수 다수 증가
➡️ 많아진 Thread로 컨텍스트 스위칭 횟수가 증가해 비효율적임
Blocking 방식과 다르게 I/O 작업이 진행되는 동안 User Process의 작업이 중단되지 않는다.
- User Process가 recvfrom 함수 호출 (Kernel에게 해당 Socket으로부터 데이터를 받겠다고 요청)
- Kernel은 이 요청에 대해 곧바로 recvBuffer를 채워 보내지 못해,
"EWOULDBLOCK"
을 반환- Blocking 방식과 달리 User Process는 다른 작업 수행
- recvBuffer에 user가 받을 수 있는 데이터가 있는 경우, Buffer로부터 데이터를 복사해 받음
➡️ 이때, recvBuffer는 Kernel이 가진 메모리에 적재되어 있어, 메모리간 복사로 인해 I/O보다 훨씬 빠른 속도로 데이터를 받아옴
- recvfrom 함수는 빠른 속도로 데이터를 복사해 복사한 데이터의 길이와 함께 반환