2013. 12. 19. 11:07


blocking 모드 

어떤 시스템 콜을 호출하였을 때 네트워크 시스템이 동작을 완료할 때까지 그 시스템 콜에서 프로세스가 멈춤

소켓 생성시 디폴트 blocking 모드

listen(),connect(), accept(), recv(), send(), read(), write(), recvfrom(), sendto(), close()

block 될 수 있는 소켓 시스템 콜

I/O시 처리가 될 때까지 기다려야 함. 비 동기적인 작업 수행 불가능

일 대 일 통신을 하거나 프로그램이 한가지 작업만 하면 되는 경우는 blocking 모드로 프로그램을 작성할 수 가능


Non-blocking 모드

소켓 관련 시스템 콜에 대하여 네트워크 시스템이 즉시 처리할 수 없는 경우라도 시스템 콜이 바로 리턴되어 응용 프로그램이 block되지 않게 하는 소켓 모드

통신 상대가 여럿이거나 여러 가지 작업을 병행하려면 nonblocking 또는 비동기 모드를 사용하여야 한다.

non-blocking 모드를 사용하는 경우에는 일반적으로 어떤 시스템 콜이 성공적으로 실행될 때까지 계속 루프를 돌면서 확인하는 방법(폴링)을 사용한다.




정리 .....


동기 : 순서 있게 일한다. 


비동기: 신호를 보내고, 받는다. (무순서)


Blocking

- 리턴값에 신뢰성이 있다. 대신에 기다려야 한다.

- 어떤 시스템 콜을 호출 하였을 때 네트워크 시스템이 동작을 완료 할 때까지 시스템 콜에서 프로세스가 멈춤.


Non_Blocking 

- 네트워크가 즉시 처리 할 수 있으면 해당 결과를 리턴  ( 바로 리턴하는 대신 신뢰성을 보장하지 못함)

- 리턴값을 대게 -1, false 를 리턴한다.

- 결과 확인은 위한 반복적인 작업(폴링)으로 CPU 낭비를 초래한다.





<노컷님 정리>


* 더 쉬운 예(프린터를 예로 들어서, 문서 10개를 print시킬때)
1. sync : 문서를 작성하고 print시킨다. 다 프린트 되서 나올때까지 기다려서 확인.
          그 다음 문서를 print시키고, 다 나올때까지 확인.(당연 절라 느림)
          (거기다 사람(application)이 계속 기달리고 있어야 함...시간 아깝죠?^^)
2. async : 문서를 print시키라고 마구 시킨다.(프린터야 죽어나든 말든..)
           글구 사람(application)은 코딩작업을 마무리 하던가, 데브피아에 답변을
           올리던가...일을 하다가 printer가 일이 끝나면, 삐~~(신호음)을 울려주고
           그때서야 프린트가 잘 됐나 한번 봐준다^^
          (사람(application)을 부릴땐 이렇게 시켜야 효율적으로 일하겠죠?^^)
          (실제로 쓰이고 있는 방식입니다.)
3. non-blocking방식 : 프린트 시키고 딴짓하다가 프린트가 나오기 시작하면,
          다 끝날때까지 기다림(sync보단 효율적이고, async보단 더 느리고)
          (recv함수를 쓰는 동안은 기다리니깐요)

동기는 프로그래밍하기가 좋고, 비동기는 좀 더 까다로운 대신 기능이 좋죠^^

덧. async가 네트워크 속도가 빠른 건 아닙니다(확인하고 보내는 시간이 없으니 조금 
더 빠르긴 하지만...프린트를 1000장을 시킬때, 완료될때까지 걸리는 시간은 그렇게 
차이가 안나죠, 문제는 사람(application)이 하루종일 기달리고 있느냐, 하루종일 딴
일하고, 마지막에 확인만 해주느냐의 차이인 것이죠.^^


출저:




아래 읽어보세요.

Non Blocking IO 에 관한 질문..

litdream의 아바타

어제, 후배가 'Non blocking IO 를 왜 쓰나요?' 라고 물어오더군요.
솔직히 한번도 non-blocking IO 를 써본적이 없는 저로써는,
잘 모르겠다만, 내가 알기로는 머 이러이러하다라고 말해준것이
계속 맘에 걸립니다. 잘못 얘기해준것 같아서요.

" 어떤 function call 이 blocking socket 에 대해 이루어질때,
버퍼가 비어있다면 버퍼에 무엇인가 들어올때까지 프로세스는 sleep
상태가 되고, OS 는 다른 프로세스를 선택하게되지만,
non-blocking socket 에 대해 이루어지면, 버퍼가 비어있으면,
펑션은 바로 NULL 을 리턴하게되고, 곧바로 다음 문장을 실행하게
된다. 이것이 가지는 장점은, (여기서 잠시 머뭇하다가.. )
select() 나 poll() 같은 펑션에 소켓을 등록한후, 그 몽땅을 하나의
channel 로 관리하게 되므로, 각각의 소켓에 쓰레드를 할당하는것
과 대조적으로 하나의 쓰레드로 관리할수 있게되므로, 쓰레드에서
잇점이 있다. "

막상 이렇게 정리를 해놓고 보니 넘겨짚은 부분이 많은것 같아서요.
그리고, 설명을 못해준것이, 
1. 이것이 performance 입장에서는 어떻게 더 나은지..
2. 이것이 scalable 한 이유.

이런 문제에 관해서는 전혀 생각을 못했네요.
고견을 부탁드립니다.

kane의 아바타

제가 알고 있는 장점은thread context switching을

제가 알고 있는 장점은
thread context switching을 줄일 수 있다는 겁니다.
프로세스 보다야 낫겠지만 쓰레드도 컨텍스트 스위칭에 오버 헤드가 있기 때문에 이걸 줄일 수 있다면 좋습니다. 특히 소켓 수가 많고, 소켓 통신이 빈번하게 이루어지는 상황이라면 이 오버 헤드도 무시 못할 게 되죠.
대신에 코딩하기 귀찮아진다는 (무시 못할 ㅋㅋ) 단점이 있지만요.

추가로 소켓을 쓰레드에 분배하거나, 쓰레드끼리 데이타를 주고 받을 필요가 발생해서 생기는 오버 헤드도 있을 수 있습니다.

aqwerf의 아바타

select나 poll을 사용하였을 때의 장점은 performance나

select나 poll을 사용하였을 때의 장점은 performance나 scale면에서는 큰 장점은 없는 것 같습니다.

하지만, 
- thread를 여러개 만드는 것보다는 select를 사용하는 것이 메모리 사용면에서 효율 적이고
- 다른 io event와 같이 기다릴 수 있다
는 장점이 있을 것 같습니다.

저 같은 경우에는 두번째의 용도로 많이 씁니다. 예를 들어 소켓 통신 중 중단 시키려는 경우 빨리 깔끔하게 뒷처리를 하도록 하기 위해서는 blocking인 경우 thread를 바로 깨워줘야 하는데 이를 위한 방법이 없어서요. 
제가 주로 사용하는 것이 RTOS인데 unix는 이런 경우에 깨울수 있는 방법이 있나요?

ssehoony의 아바타

throughput 과 response time 간 trade off 관

throughput 과 response time 간 trade off 관계인데요.
일단 이거 단일 프로세스라는 가정에서 이야기를 하면

throughput 은 select 가 좋습니다.
kane 님께서 말씀 하셨듯이 컨텍스트 스위칭, 쓰레드 스케줄링, 크리티컬섹션의 뮤텍스 처리등이 쓰레드를 이용하면 생기는 부하들인데 이런 것들이 없기때문에 전체 성능은 좋아집니다.

하지만 select 는 (쓰레드와 비교해 상대적으로) response time 이 떨어집니다. 클라이언트 입장에서는 다른 클라이언트가 서버에 먼저 뭔가 요구했다면 그 작업이 끝날때까지 기다렸다가 내 차례가 오기때문이죠.

위와 같은 상황은 커널이 프로세스 스케줄링할때 어떤 알고리즘을 사용하느냐 그리고 한 프로세스에 한번에 주는 cpu 시간의 크기에 따라 throughput 과 response time 이 trade off 관계인것 과 같은 것이지요.

또한 쓰레드를 쓰면 각각의 쓰레드 생성 오버헤드도 있고 각 쓰레드의 스택세그먼트 공간을 생각하면 메모리 낭비가 문제지요.

그럼 쓰레드는 뭐가 좋냐? 위에 말씀 드린 것 처럼 response time 이 짧고 (클라이언트 입장에서 보면 서버의 throughput 은 자기완 전혀 상관없고, response time 이 중요하죠), 크리티컬섹션을 제외한다면 코드도 select 보다 간단하고, 멀티 프로세서일때 필요하다면 모든 프로세서를 동시에 병렬로 이용해서 단일 프로세서의 select 보다 더 좋은 throughput 을 낼 수도 있습니다.

litdream의 아바타

Context Switch 의 Overhead 가 있었군요!!이런이런

Context Switch 의 Overhead 가 있었군요!!
이런이런~ 가장 기본적인것을 놓치다니.. 역시 내공이 부족합니다.
답변주신 세분 감사합니다.

삽질의 대마왕...

pynoos의 아바타

NonBlock IO를 쓰는 가장 큰 이유는 소켓의 데이터 처리에 대한

NonBlock IO를 쓰는 가장 큰 이유는 소켓의 데이터 처리에 대한 스케쥴링을 OS나 일반적인 라이브러리에 맡기지 않고, 스스로 구현한 스케쥴링을 사용하겠다는 것입니다.

그리고, OS의 다른 overhead인 process/thread의 스케쥴링 비용(요것이 소켓 100개정도만 넘어가도 상당한 비용이 됩니다.)을 없애겠다는 것입니다.

윗분들이 언급하지 않은 것 하나는 select 또한 소켓수가 100개 이상되면 비용이 작은 것이 아닙니다. select는 각 소켓의 버퍼에 WATER MARK 이상의 값이 있는지에 대해 반응하는 것입니다. 대개 WATER MARK 값은 1로 설정되어 있고, 그 값보다 크게 데이터들이 들어와 있는지를 일일이 비교합니다. 즉 data의 level에 따라 select되는 것이고, 매번 I/O로부터 데이터가 올라왔을 때 바로 반응하는 epoll 을 사용하는 것이 좋습니다.

---
coolengineer.com


Posted by hoonihoon