我們用術語慢系統調用(slow system call)描述accept函數,該術語也適用於那些可能永遠阻塞的系統調用。永遠阻塞的系統調用有可能永遠無法返回,多數網絡支持函數都屬於這一類。舉例來說,如果沒有客戶連接到服務器上,那麼服務器的accept調用就沒有返回的保證。類似的,如果客戶端從未發送過數據,那麼read調用將永不返回。其他慢系統調用的例子是對管道和終端設備的讀和寫。一個值得注意的例外是磁盤IO,它們一般都會返回到調用者(假設沒有災難性的硬件事故)。
適用於慢系統調用的基本規則是:當阻塞於某個慢系統調用的一個進程捕獲某個信號且相應處理函數返回時,該系統調用可能返回一個EINTR錯誤。所以,我們必須對慢系統調用返回的EINTR有所準備。
爲了處理被中斷的accept,可以改成如下形式:
- for (;;)
- {
- if((connfd=accept(listenfd,NULL, NULL)) < 0)
- {
- if (errno == EINTR)
- continue;
- else
- printf("accept error");
- }
- }
這段代碼所做的事情就是自己重啓被中斷的系統調用。對於accept,以及諸如read、write、select和open之類的函數,這是適合的。不過有一個函數我們不能重啓:connect。如果該函數返回EINTR,我們就不能再次調用它,否則將立即返回一個錯誤。當connect被一個捕獲信號中斷而且不自動重啓時,我們必須調用select來等待連接完成。