select和poll函式講解

2021-07-11 09:42:45 字數 3648 閱讀 8349

五種io處理模型

阻塞性io模型 

在這種模型下,若呼叫的io函式沒有完成相關的功能,則會使程序掛起,直到相關資料到達才會返回,如常見的管道裝置,終端裝置,網路裝置進行讀寫時經常出現這種情況;

非阻塞型io模型

在這種模型下,當請求的io操作不能完成時,則不讓程序睡眠,而且立即返回,非阻塞io使使用者可以呼叫不會阻塞的iowa操作,如open(),write(),read()。如果該操作不能完成,則會立即返回出錯(如打不開檔案)或者返回0(如在緩衝區沒有資料可以讀取或者沒有空間可以寫入資料)

io多路轉接模型

在這種模型下,如果請求的iowa操作阻塞,且他不是真正的阻塞io,而是讓其中的乙個函式等待,在此期間,io不能進行其他操作。如select()和poll()函式

訊號驅動io模型

在這種模型下,程序要定義乙個訊號處理程式,系統可以自動捕獲特定訊號的到來,從而啟動iowa。這是由核心通知使用者何時可以啟動乙個iowa操作決定的。他是非阻塞的,當有就緒的資料時,核心就向該程序傳送sigio訊號,無論我們如何處理sigio訊號,這種模型的好處就是當等待資料到達時,可以不阻塞,主程式繼續執行,只有收到sigio訊號才去處理資料即可。

非同步io模型

在這種模型下,程序先讓核心啟動io操作,並在整個操作完成後通知該程序,這種模型與訊號驅動模型的主要區別在於:訊號驅動io是核心通知我們何時可以啟動乙個io操作,而非同步io模型是由核心通知程序io操作何時完成的。現在,並不是所有的系統都支援這種模型。

可以看到,select()和poll()的io多路轉接模型是處理io復用的乙個高效方法,他可以具體設定程式中每乙個所關心的檔案描述符的條件。希望等待的時間等,select()和poll()函式返回時,核心會通知使用者已準備好的檔案描述符的數量、已準備好的條件(或者事件等)通過使用select()和poll()函式的返回結果(可能是某個檔案描述符的註冊事件或是超時,或是呼叫出錯),就可以呼叫相應的io處理函式了。

阻塞方式block,就是程序或是執行緒執行到這些函式時必須等待某個事件的發生,如果事件沒有發生,程序或執行緒就被阻塞,函式不能立即返回。使用select就可以完成非阻塞non-block,就是程序或執行緒執行此函式時不必非要等待事件的發生,一旦執行肯定返回,以返回值的不同來反映函式的執**況,如果事件發生則與阻塞方式相同,若事件沒有發生則返回乙個**來告知事件未發生,而程序或執行緒繼續執行,所以效率較高。select能夠監視我們需要監視的檔案描述符的變化情況。

(一)首先說明兩個結構體:

1:struct fd_set乙個存放檔案描述符(file descriptor),即檔案控制代碼的聚合,實際上是一long型別的陣列,

每乙個陣列元素都能與一開啟的檔案控制代碼(不管是socket控制代碼,還是其他檔案或命名管道或裝置控制代碼)建立聯絡,建立聯絡的工作由程式設計師完成;

fd_zero(fd_set *fdset):清空fdset與所有檔案控制代碼的聯絡。

fd_set(intfd, fd_set *fdset):建立檔案控制代碼fd與fdset的聯絡。

fd_clr(intfd, fd_set *fdset):清除檔案控制代碼fd與fdset的聯絡。

fd_isset(intfd, fdset *fdset):檢查fdset聯絡的檔案控制代碼fd是否可讀寫,>0表示可讀寫。

2:struct timeval用來代表時間值,有兩個成員,乙個是秒數tv_sec,另乙個是毫秒數tv_usec。

(二)select()函式原型:

1:int select(int nfds, fd_set *rdfds, fd_set *wtfds, fd_set *exfds, struct timeval *timeout)

2:ndfs:select中監視的檔案控制代碼數,一般設為要監視的檔案中的最大檔案號加一。

3:rdfds:select()監視的可讀檔案控制代碼集合,當rdfds映象的檔案控制代碼狀態變成可讀時系統告訴select函式返回。

這個集合中有乙個檔案可讀,select就會返回乙個大於0的值,表示有檔案可讀,

如果沒有可讀的檔案,則根據timeout引數再判斷是否超時,

若超出timeout的時間,select返回0,若發生錯誤返回負值,

可以傳入null值,表示不關心任何檔案的讀變化;

4:wtfds: select()監視的可寫檔案控制代碼集合,當wtfds映象的檔案控制代碼狀態變成可寫時系統告訴select函式返回。

如果這個集合中有乙個檔案可寫,select就會返回乙個大於0的值,表示有檔案可寫,

如果沒有可寫的檔案,則根據timeout引數再判斷是否超時,

若超出timeout的時間,select返回0,若發生錯誤返回負值,

可以傳入null值,表示不關心任何檔案的寫變化。

5:exfds:select()監視的異常檔案控制代碼集合,當exfds映象的檔案控制代碼上有特殊情況發生時系統會告訴select函式返回。

6:timeout:select()的超時結束時間。

這個引數它使select處於三種狀態,

第一,若將null以形參傳入,即不傳入時間結構,就是將select置於阻塞狀態,

一定等到監視檔案描述符集合中某個檔案描述符發生變化為止;

第二,若將時間值設為0秒0毫秒,就變成乙個純粹的非阻塞函式,不管檔案描述符是否有變化,

都立刻返回繼續執行,檔案無變化返回0,有變化返回乙個正值;

第三,timeout的值大於0,這就是等待的超時時間,即select在timeout時間內阻塞,

超時時間之內有事件到來就返回了,否則在超時後不管怎樣一定返回,返回值同上述。

7:返回值:負值:select錯誤

0:等待超時,沒有可讀寫或錯誤的檔案

正值:某些檔案可讀可寫或出錯

(三)下面是乙個有三個套接字控制代碼的例子

intsa, sb, sc;

sa = socket(...);

connect(sa,...);

sb = socket(...);

connect(sb,...);

sc = socket(...);

connect(sc,...);

fd_set(sa, &rdfds);/* 分別把3個控制代碼加入讀監視集合裡去 */

fd_set(sb, &rdfds);

fd_set(sc, &rdfds);

intmaxfd = 0;

if(sa > maxfd) maxfd = sa;/* 獲取3個控制代碼的最大值 */

if(sb > maxfd) maxfd = sb;

if(sc > maxfd) maxfd = sc;

structtimeval tv;

tv.tv_sec   = ... ;

tv.tv_usec = ...;

ret = select(maxfd + 1, &rdfds, null, null, &tv); /* 注意是最大值加1 */

if(ret < 0)

else if(ret == 0)

else

......

}

I O模型以及select和poll函式

unix下可用的5中i o模型 1.阻塞式i o模型 2.非阻塞式i o模型 3.i o復用 select poll epoll 目前linux下幾乎都使用epoll。4.訊號驅動式i o sigio 5.非同步i o posix的aio 系列函式 預設情況下,所有套接字都是阻塞的,write,re...

I O復用 select和poll函式 一

我們看到上面的tcp客戶同時處理兩個輸入 標準輸入和tcp套接字。我們遇到的問題就是在客戶阻塞於 標準輸入上的 fgets呼叫期間,伺服器程序會被殺死。伺服器tcp雖然正確地給客戶tcp傳送乙個fin,但是既然客戶程序阻塞於從標準輸入讀入的過程,它將看不到這個rof,知道從套接字讀時為止 可能已經過...

select和poll的用法

select 函式的作用 系統呼叫select和poll的後端實現,用這兩個系統呼叫來查詢裝置是否可讀寫,或是否處於某種狀態。如果poll為空,則驅動裝置會被認為即可讀又可寫,返回值是乙個狀態掩碼 如何使用select 函式?select 函式的介面主要是建立在一種叫 fd set 型別的基礎上。它...