從select的乙個死迴圈談epoll的ET模式

2021-06-22 07:34:41 字數 3198 閱讀 1176

最近寫程式遇到乙個問題,就是發現

select

監聽標準輸出的時候遇到了死迴圈,具體程式如下程式一。程式的意圖是每當使用者在控制台有任何輸入,就輸出

」hello world!」。

程式一:

#include 

#include 

#include 

#include 

int 

main(int argc, char *argv)

} return 0; }

執行結果:

結果會迴圈輸出「

hello world!

」,這是為什麼呢?也就是當我們輸入任意字元後,

select每次都判斷標準輸入的描述符就緒。造成這種情況的原因要從

select

的機制說起。如下圖所示:

沒乙個檔案描述符(

fd)與乙個緩衝關聯,

select對

fd的監聽其實就是監聽

fd的緩衝,

當緩衝中有資料要讀的時候,select

就認為該

fd可讀就緒,當緩衝中有資料待寫的時候,

select

就認為該

fd可寫就緒。

下面我們在分析一下我們的程式一,當輸入任意字元,比如:「abc

」,則「

abc」被放在標準輸入的緩衝當中,此時緩衝中有資料(

abc)待讀,所以

select

返回stdin_fileno

就緒,程式輸出「hello world

!」。緊接著進入下一次迴圈,

select

重新將stdin_fileno

加入監聽的描述符集,由於剛剛的「abc

」並沒有被讀出,所以仍在緩衝中,此時

stdin_fileno

的緩衝中仍有資料等待讀,所以select

又返回stdin_fileno

可讀就緒,又一次輸出「hello world

!」。

之後迴圈情況類似,由於緩衝的的「待讀」資料始終還在,所以每次select

都直接返回

stdin_fileno

就緒,每次都輸出「hello world

!」,這就是造成程式死迴圈的原因。那麼讓偶們如何解決呢?

方法一:將緩衝區中的「待讀」資料讀出,程式修改如下所示:

修改後程式正常執行(任意輸入後,輸出「hello world

!」)。我們在做如下實驗——輸入多個字元,制度出部分字元。修改程式做如下修改:

char buf[2];

//將buf

長度改為

2,每次從緩衝區讀入兩個字元

程式執行結果如下:

分析:

(1) 

輸入乙個字元』s

』,s被放入緩衝區,同時放入緩衝區中的還有換行符』\n

』,緩衝區中有待讀資料,

select

返回讀就緒,

read將』

s\n』

讀出,緩衝區清空,select

再次阻塞。

(2) 

輸入兩個」dd

」,緩衝區中的資料變為

」dd\n

」,select

返回讀就緒,

read

讀出兩個字元——」ss

」,輸出hello world

!此時緩衝區中還有』\n

』,所以下一次select

依然返回讀就緒,之後

read將』

\n』讀出,輸出hello world

!,緩衝區清空,

select

阻塞。

(3) 

之後輸入三個字元,四個字元的情況類似,不在分析。

到此,我們將程式一基本分析清楚,但我們的討論遠沒有結束。因為,這個程式的現象令我想起了另乙個知識點——epoll的lt

和et模式。

關於et和lt

模式的介紹,之前的博文已經寫得很詳細了,這裡不再重複。這裡想說的是,以上程式一的現象正式

lt模式的乙個典型例項,也是

lt模式的乙個缺陷。

我們知道select

和poll

都是採用

lt模式,並且只有這一種模式。

所以,使用select

或者poll

要想解決程式一的問題只能採用方法一。下面我們採用

epoll的et

模式解決,也就是方法二。**如下。

程式二:

#include 

#include 

#include 

using namespace std;

int main(void)

} }

執行結果:

可以發現,使用et

模式,程式正常執行,雖然輸入緩衝區的資料並沒有被讀出,但是只要沒有新的資料進入,

epoll

就不再被通知(只被通知一次),當再次輸入資料,又有新的資料進入緩衝時才會觸發

epoll

,再次返回讀就緒,輸出

」hello world!」。

我們再看看使用lt

模式的情況,將程式二以下修改:

ev.events=epollin;

//預設使用

lt模式

執行結果:

可以發現和select

的結果一樣。

從select的乙個死迴圈談epoll的ET模式

最近寫程式遇到乙個問題,就是發現 select 監聽標準輸出的時候遇到了死迴圈,具體程式如下程式一。程式的意圖是每當使用者在控制台有任何輸入,就輸出 hello world!程式一 include include include include int main int argc,char argv...

從select的乙個死迴圈談epoll的ET模式

最近寫程式遇到乙個問題,就是發現 select 監聽標準輸出的時候遇到了死迴圈,具體程式如下程式一。程式的意圖是每當使用者在控制台有任何輸入,就輸出 hello world!程式一 include include include include int main int argc,char argv...

從乙個圈套For迴圈來談

從乙個圈套 for迴圈來談軟體設計 武漢華中師範大學信管係謝剛 摘要 就自己的一次實際經歷來談談軟體設計過程中應該注意的一些細節 關鍵字 軟體設計需求分析 前段時間,跟外面公司設計乙個mis系統 使用工具是pb8.0 是乙個關於生產的。為了體現我們設計人員的高質量服務,我在 需求說明 之外又幫他們設...