2011-04-09 83 views
3

我找到了一個服務器select(),我想從某些客戶端收到。可重入函數read()

但我發現服務器會被gdb的read()阻塞。

所以我想通過增加一個SIGALRM來解決它,但是當發生超時時,它仍然被阻塞在read()

發生這種情況的原因是系統調用會自動重新啓動,因此在SIGALRM信號處理程序返回時不會中斷read()

這個解釋是否正確?

回答

2

通常解決此問題是使用SOCK_NONBLOCKsocket(2)O_NONBLOCKfcntl(2)F_SETFL命令。一旦套接字被標記爲非阻塞,當你嘗試讀取套接字時它就不會阻塞,並且你不需要跨越阻塞或非阻塞之間的鴻溝。你確定select(2)設置了filedescriptor嗎?該select(2)手冊頁確實描述一個原因爲什麼你看到你所看到的,但似乎有可能並不:

在Linux下,select()可能會報告套接字文件描述符 「讀就緒」,同時仍然隨後讀取 塊。例如,這可能發生在數據到達 但檢查錯誤校驗和並被丟棄時發生。 在其他情況下,其中文件描述符 虛假地報告爲就緒。因此,在不應阻塞的插座上使用 O_NONBLOCK可能會更安全。

如果你真的只是想阻止自動重啓,看看SA_RESTARTsigaction(2)防止重新啓動系統調用重新啓動。

+0

謝謝,我會嘗試套接字(2)。 – lxgeek 2011-04-09 12:16:28

+0

我用select()方法:select(FD_SETSIZE,server-> fd_readset,0,0,timeout),我用FD_SETSIZE,這個可以工作嗎?或者這會造成一些錯誤?謝謝 – lxgeek 2011-04-09 12:16:56

+1

@lxgeek - 不要在那裏使用FD_SETSIZE。它給你的fd_set的大小通常是1024.選擇的第一個參數需要最高的文件描述符+1。自己跟蹤。使用FD_SETSIZE強制搜索一千個你可能永遠不會使用的FD。它會工作,但效率不高。你也想通過「超時」。 – Duck 2011-04-09 13:19:33