Non-Blocking I/O

I. 시스템 자원 효율적 사용, Non-Blocking I/O

가. Non-Blocking I/O의 개념

  • 소켓 관련 시스템 콜에 대해 네트워크 응답 지연 시 응용 프로그램 Block 방지 I/O 메커니즘

나. 소켓 프로그래밍에서의 Non-Blocking I/O 사용 배경

  • 대규모 클라이언트-서버 환경에서, 클라이언트별 쓰레드 생성, 클라이언트 별 read 함수 호출 시 Context Switching 비용 다수 발생하므로 자원의 효율적 사용 위해 Non-Blocking I/O 필요
  • 시스템 함수 호출 후 종료 필요 없으며, 버퍼에 데이터 존재 시 Copy, 없으면 넘어가게 되는 방식 → Non-Blocking I/O

 

II. Non-Blocking I/O 메커니즘

가. Non-Blocking I/O 절차도

  • 소켓이 Non-Blocking으로 지정되면 I/O 처리 완료 시까지 대기하지 않고 에러(EWOULD BLOCK) 반환

나. Non-Blocking I/O 절차 설명

#수행 절차설명
system call / EWOULDBLOCK– 소켓에 datagram 존재 여부 확인
– datagram 없으면 에러 신호 리턴
polling (①번 반복)– 네트워크 소켓에 datagram 존재 여부 지속 확인 (Busy Waiting)
네트워크 소켓으로 datagram 수신 시
copy datagram– 네트워크 소켓의 datagram을 어플리케이션 버퍼로 복사
return data– recvfrom은 성공적으로 리턴, 이후 어플리케이션 데이터 처리
  • 리눅스 기반 sleep 없는 polling(loop) 시 CPU 100% 점유 문제 발생하므로 해결 필요

 

III. Non-Blocking I/O 모델 소켓 프로그램 코드

char str[BUF_SIZE] = {0,}; //받을 버퍼
unsigned int strLen = 0; //받고 싶은 데이터의 길이
unsigned int length = 0; //지금까지 받은 데이터의 길이
unsigned int recvLen = 0; //이번에 받은 데이터의 길이

while(TRUE){
 if (recvLen = recv (sock, str+length, strLen, 0) < 0) {
 //recvfrom 호출하여 결과값 받음. 0보다 작으면 받을 수 있는 데이터가 없음
  if (WSAGetLastError() == WSAEWOULDBLOCK){
  //WOULDBLOCK이라면 대기시킨다.
   Sleep( 2000 ); /* Sleep for 2 milliseconds */
  }else{
   printf(“No data Error.\n”);
   break;
  }
 }else {
  length += recvLen;
  if(length >= strLen) break; //다 받았으면 중지
 }
}

 

IV. Non-Blocking I/O의 문제점 및 해결 방안

문제점해결 방안
– datagram 미 존재 시 polling은 자원 낭비
– 일부 시스템에서 CPU 100% 점유문제 발생
– I/O 이벤트 통지 모델
– 데이터 수신 시 통지 수행
– 동기식 및 비동기식 모델

 

콘텐츠 사용 시 출처 표기 부탁 드리고, 궁금한 점이나 의견은 댓글 남겨주세요^^