我找到了一個服務器select()
,我想從某些客戶端收到。可重入函數read()
但我發現服務器會被gdb的read()
阻塞。
所以我想通過增加一個SIGALRM
來解決它,但是當發生超時時,它仍然被阻塞在read()
。
發生這種情況的原因是系統調用會自動重新啓動,因此在SIGALRM信號處理程序返回時不會中斷read()
。
這個解釋是否正確?
我找到了一個服務器select()
,我想從某些客戶端收到。可重入函數read()
但我發現服務器會被gdb的read()
阻塞。
所以我想通過增加一個SIGALRM
來解決它,但是當發生超時時,它仍然被阻塞在read()
。
發生這種情況的原因是系統調用會自動重新啓動,因此在SIGALRM信號處理程序返回時不會中斷read()
。
這個解釋是否正確?
通常解決此問題是使用SOCK_NONBLOCK
到socket(2)
或O_NONBLOCK
到fcntl(2)
的F_SETFL
命令。一旦套接字被標記爲非阻塞,當你嘗試讀取套接字時它就不會阻塞,並且你不需要跨越阻塞或非阻塞之間的鴻溝。你確定select(2)
設置了filedescriptor嗎?該select(2)
手冊頁確實描述一個原因爲什麼你看到你所看到的,但似乎有可能並不:
在Linux下,
select()
可能會報告套接字文件描述符 「讀就緒」,同時仍然隨後讀取 塊。例如,這可能發生在數據到達 但檢查錯誤校驗和並被丟棄時發生。 在其他情況下,其中文件描述符 虛假地報告爲就緒。因此,在不應阻塞的插座上使用O_NONBLOCK
可能會更安全。
如果你真的只是想阻止自動重啓,看看SA_RESTART
在sigaction(2)
防止重新啓動系統調用重新啓動。
謝謝,我會嘗試套接字(2)。 – lxgeek 2011-04-09 12:16:28
我用select()方法:select(FD_SETSIZE,server-> fd_readset,0,0,timeout),我用FD_SETSIZE,這個可以工作嗎?或者這會造成一些錯誤?謝謝 – lxgeek 2011-04-09 12:16:56
@lxgeek - 不要在那裏使用FD_SETSIZE。它給你的fd_set的大小通常是1024.選擇的第一個參數需要最高的文件描述符+1。自己跟蹤。使用FD_SETSIZE強制搜索一千個你可能永遠不會使用的FD。它會工作,但效率不高。你也想通過「超時」。 – Duck 2011-04-09 13:19:33