2009-01-27 42 views
5

我在Linux/ARM平臺上使用select()來查看udp套接字是否已收到數據包。如果在超時之前返回(檢測到數據包),我想知道選擇呼叫還剩多少時間。Select()調用中剩餘的時間

東西沿着線:

int wait_fd(int fd, int msec) 
{ 
    struct timeval tv; 
    fd_set rws; 

    tv.tv_sec = msec/1000ul; 
    tv.tv_usec = (msec % 1000ul) * 1000ul; 

    FD_ZERO(& rws); 
    FD_SET(fd, & rws); 

    (void)select(fd + 1, & rws, NULL, NULL, & tv); 

    if (FD_ISSET(fd, &rws)) { /* There is data */ 
     msec = (tv.tv_sec * 1000) + (tv.tv_usec/1000); 
     return(msec?msec:1); 
    } else { /* There is no data */ 
     return(0); 
    } 
} 
+0

我不確定你的問題是什麼。你的代碼解決了這個問題。剩餘時間寫入超時參數。 Quoth select(2):「在Linux上,select()修改超時以反映不睡眠的時間量;大多數其他實現不這樣做(POSIX.1-2001允許這兩種行爲之一)。」 – phihag 2009-01-27 22:34:44

+0

@phihag:「許可任一行爲「......在選擇調用不可移植後精確查看超時值 – 2009-01-28 07:48:10

回答

3

最安全的做法是忽略的select()模棱兩可的定義和時間它自己。

只需要選擇前後的時間並從您想要的時間間隔中減去該時間。

1

如果正確地記得的select()函數將超時和一個I/O參數,並且當選擇返回時殘留在超時變量被返回。

否則,您將不得不在調用之前記錄當前時間,並在獲得兩者之間的差異後再次記錄。

+0

select()的文檔說如果函數成功返回(不超時),則可能更改超時值'可能'。 我想知道是否有一個簡單的習語或替代庫調用來做到這一點。 – Jamie 2009-01-27 23:39:31

+0

由於您正在爲特定平臺編寫應用程序,爲何不嘗試在該平臺上調用之後嘗試更改超時值。 – 2009-01-28 00:21:53

1

從 「人選擇」 對OSX:

Timeout is not changed by select(), and may be reused on subsequent calls, however it 
is good style to re-ini-tialize it before each invocation of select(). 

你需要調用select之前調用gettimeofday的,然後退出gettimeofday的。

[編輯]看來,Linux是略有不同:

(ii) The select function may update the timeout parameter to indicate 
      how much time was left. The pselect function does not change 
      this parameter. 

    On Linux, the function select modifies timeout to reflect the amount of 
    time not slept; most other implementations do not do this. This causes 
    problems both when Linux code which reads timeout is ported to other 
    operating systems, and when code is ported to Linux that reuses a 
    struct timeval for multiple selects in a loop without reinitializing 
    it. Consider timeout to be undefined after select returns. 
0

的Linux選擇()更新超時參數,以反映已經過去的時間。

請注意,這不適用於其他系統(因此上面引用的OS X手冊中的警告),但可以在Linux上使用。

吉拉德

-3

不要使用select,請嘗試使用fd大於1024的代碼,並查看您將獲得的內容。