慢系統呼叫 和EINTR錯誤

2021-09-19 14:49:20 字數 1457 閱讀 9434

本文引用了《訊號中斷 與 慢系統呼叫》中的內容,感謝許老師的精彩分享。

所謂慢系統呼叫(slow system call):指的是那些可能永遠阻塞的系統呼叫,永遠阻塞的意思是指呼叫有可能永遠無法返回,多數網路支援函式都屬於這一類,比如socket程式設計中的 accept 函式:如果沒有客戶連線到伺服器上,accept就不會返回。

eintr錯誤:如果程序正在 乙個慢系統呼叫中阻塞,當**到某個訊號而且相應 訊號處理函式返回時,這個慢系統呼叫會被中斷,呼叫返回錯誤(返回-1),會設定errno為eintr(interrupted system call)。理解這個有2點,首先是正在慢系統呼叫阻塞中,其次是有訊號來,並且訊號處理函式返回了,這個時候才會返回中斷錯誤。這個機制其實是很有道理的,畢竟不可能發生意外事件的時候,慢系統呼叫還在那傻傻的等著。

如何處理被中斷的系統呼叫

乙個穩健的程式是需要考慮所有的異常,並且有相應的處理機制的,不怕強迫症,就怕粗心。處理被中斷的系統呼叫一般有3種方式:

(1)人為重啟被中斷的系統呼叫。

(2)安裝訊號時,設定sa_restart屬性(該方法對有的系統呼叫是無效的)

(3)忽略此訊號,讓系統不產生訊號中斷。

我們常用的一般是第一種方式:人為重啟,畢竟我們也不希望有eintr,程式就掛掉。

人為重啟被中斷的系統呼叫

當碰到eintr錯誤的時候,有一些可以重啟的系統呼叫要進行重啟,而對於有一些系統呼叫是不能夠重啟的。例如:accept、read、write、select、和open之類的函式來說,失敗只是臨時性的,我們是可以進行重啟的。不過對於套接字程式設計中的connect函式我們是不能重啟的,若connect函式返回乙個eintr錯誤的時候,我們不能再次呼叫它,否則將立即返回乙個錯誤。當connect失敗則該套接字不可再用,必須關閉close(sd),我們不能對這樣的套接字再次呼叫connect函式。必須重新呼叫socket()函式獲得新的套接字。

我們以 read 函式為例分析:

**1:

ssize_t read(int fd, void *ptr, size_t nbytes)

return n;

}

unix網路程式設計中的案例如下:

ssize_t						/* read "n" bytes from a descriptor. */

readn(int fd, void *vptr, size_t n)

else if (nread == 0)

break; /* eof */

nleft -= nread;

ptr += nread;

} return(n - nleft); /* return >= 0 */

}

慢系統呼叫

對於那些可能永遠阻塞的函式,我們可以稱之為慢系統呼叫,多數網路支援的函式都屬於這一類,如上列的這些函式,比如沒有客戶連線到伺服器,那麼伺服器對與accept的返回沒 應用在這的乙個規則是,當一程序阻塞於乙個慢系統呼叫,可能捕獲到乙個訊號,等待訊號處理程式返回時,系統呼叫可能返回乙個 eintr錯誤。...

系統呼叫 錯誤處理函式

1 perror perror函式是用來列印錯誤提示資訊的,原型是 include void perror const char s 它先列印s指向的字串,然後輸出當前errno值所對應的錯誤提示資訊,例如當前errno若為12,呼叫perror abc 會輸出 abc cannot allocat...

系統呼叫read()的返回錯誤場景

ssize t read int fd,void buf,size t count 從檔案描述符fd中讀取count個位元組的資料放入buf的緩衝區中。返回值 成功返回讀取到的位元組數 count為0,read 返回0 eintr 在讀取到資料以前呼叫被訊號所中斷.eagain 使用 o nonbl...