2014-12-01 1 views
0

UDP 멀티 캐스트 피드를 수신하고 들어오는 데이터를 처리하는 클라이언트 응용 프로그램이 있습니다. 휴대용이며 Windows와 Linux에서 모두 실행됩니다. 주요 처리 루프는, 데이터를 기다리는 select()를 사용하여 일반적으로는 하나 또는 두 개의 UDP 비 블로킹 소켓의 :select()가 특히 멀티 스레드에서 시간 초과를 고려하지 않는 이유

while(!stopRequested) 
{ 
    fdset io; 
    FD_ZERO(&io); 
    FD_SET(sock, &io); 

    timeval waitInterval = { 0 }; 
    waitInterval.tv_usec = 10000; // 10 milliseconds 

    int r = select(sock + 1, &io, NULL, NULL, &waitInterval); 
    if(r == 0) // Process timeout 
    else // Data or error processing 
} 

코드는 꽤 잘 작동을하지만 데이터를 사용할 수 없을 때 제한 시간 정확도 문제가 있습니다. 우리는 실제로 보장 대기의 초 몇시에 select() 내부에 소요되는 시간을 측정 (데이터가 전송되지 않았다) 및 분포는 다음과 같이이다 :

에 오류가 없었다
<1 usec  : 170 time(s) 
<2000 usec : 1 time(s) 
<10000 usec : 11973 time(s) 
<12000 usec : 6558 time(s) 
<15000 usec : 64 time(s) 
<20000 usec : 47 time(s) 

, select() 항상 그래서 0을 반환 우리가 볼 수 있듯이, select()이 거의 즉각적으로 반환되었을 때 시간 초과를 기다리지 않고 몇 가지 경우 (170 번)가 있습니다.

그래서 시간 초과가 여러 경우에 존중되지 않는 이유는 무엇입니까? Windows (Win7 x64) 및 Linux (CentOS/RHEL6.0 x64)에서도 비슷한 결과가 나타납니다.

또한 멀티 스레딩을 사용할 때 상황이 훨씬 더 악화되었습니다. 2 개 스레드가 상기 코드를 실행 (모두 동일한 소켓 select() 호출하지만 fd_setwaitInterval 로컬 객체)되면 select() 내부 횟수 분포 (각 쓰레드)이 같다 : select() 같다

<1 usec  : 13800827 time(s) 
<10 usec : 1639 time(s) 
<100 usec : 8660 time(s) 
<1000 usec : 16 time(s) 
<12000 usec : 768 time(s) 
<15000 usec : 39 time(s) 

timeout을 존중하지 않지만 동시 호출에서 즉시 0을 반환합니다.

혼란스러운 행동에 대한 설명이 있습니까? fd_settimeout 매개 변수를 다시 초기화하지 않는 일반적인 함정을 확인하고 이것이 사실이 아닙니다.

+2

시간 초과가 걸린 시간을 측정하는 데 사용한 내용은 무엇입니까? 이것을 보여줄 수있는 간단한 예제 프로그램을 게시 할 수 있습니까? – Art

+1

어떻게 측정합니까? –

+2

시스템 HZ는 무엇입니까? 'grep 'CONFIG_HZ ='/ boot/config - $ (uname -r)'? 이렇게하면 1/HZ 초의 타임 아웃 해상도를 선택할 수 있습니다. –

답변

0

실제로 select()에는 아무런 문제가 없으며 올바르게 시간 초과됩니다. 측정이 잘못되었습니다. select() 자체를 호출하지 않고 실제로는 fd_set을 검사하고을 생략 한 랩핑 기능을 측정했습니다. 항상 < 10000 usec은 select() 전화와 관련이 없습니다.

아마도이 질문은 관련성이없는 것으로 삭제되어야합니다.

관련 문제