最近寫程式遇到乙個問題,就是發現
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 是乙個關於生產的。為了體現我們設計人員的高質量服務,我在 需求說明 之外又幫他們設...