1. 程式人生 > >select模型的原理、優點、缺點

select模型的原理、優點、缺點

I/O多路複用(又被稱為“事件驅動”),首先要理解的是,作業系統為你提供了一個功能,當你的某個socket可讀或者可寫的時候,它可以給你一 個通知。這樣當配合非阻塞的socket使用時,只有當系統通知我哪個描述符可讀了,我才去執行read操作,可以保證每次read都能讀到有效資料而不 做純返回-1和EAGAIN的無用功。寫操作類似。作業系統的這個功能通過select/poll/epoll之類的系統呼叫來實現,這些函式都可以同時 監視多個描述符的讀寫就緒狀況,這樣,**多個描述符的I/O操作都能在一個執行緒內併發交替地順序完成,這就叫I/O多路複用,這裡的“複用”指的是複用 同一個執行緒。

I/O複用之select

1、介紹: 
select系統呼叫的目的是:在一段指定時間內,監聽使用者感興趣的檔案描述符上的可讀、可寫和異常事件。poll和select應該被歸類為這樣的系統 呼叫,它們可以阻塞地同時探測一組支援非阻塞的IO裝置,直至某一個裝置觸發了事件或者超過了指定的等待時間——也就是說它們的職責不是做IO,而是幫助 呼叫者尋找當前就緒的裝置。 
下面是select的原理圖:

   

2 、select系統呼叫API如下:

 
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
 

fd_set結構體是檔案描述符集,該結構體實際上是一個整型陣列,陣列中的每個元素的每一位標記一個檔案描述符。fd_set能容納的檔案描述符 數量由FD_SETSIZE指定,一般情況下,FD_SETSIZE等  於1024,這就限制了select能同時處理的檔案描述符的總量。

3、下面介紹一下各個引數的含義: 
    1)nfds引數指定被監聽的檔案描述符的總數。通常被設定為select監聽的所有檔案描述符中最大值加1; 
    2)readfds、writefds、exceptfds分別指向可讀、可寫和異常等事件對應的檔案描述符集合。這三個引數都是傳入傳出型引數,指的是 在呼叫select之前,使用者把關心的可讀、可寫、或異常的檔案描述   符 通過FD_SET(下面介紹)函式分別新增進readfds、writefds、 exceptfds檔案描述符集,select將對這些檔案描述符集中的檔案描述符進行監聽,如果有就緒檔案描述符,select會重置readfds、writefds、exceptfds檔案描述符集來通知應用程式哪些檔案描述符就緒。這個特性將導致select函式返回後,再次呼叫select之前,必須重置我們關心的檔案描述符

,也就是三個檔案描述符集已經不是我們之前傳入 的了。 
   3)timeout引數用來指定select函式的超時時間(下面講select返回值時還會談及)。

 
struct timeval
{
    long tv_sec;        //秒數
    long tv_usec;       //微秒數
};
 

4、下面幾個函式(巨集實現)用來操縱檔案描述符集:

 
void FD_SET(int fd, fd_set *set);   //在set中設定檔案描述符fd
void FD_CLR(int fd, fd_set *set);   //清除set中的fd位
int  FD_ISSET(int fd, fd_set *set); //判斷set中是否設定了檔案描述符fd
void FD_ZERO(fd_set *set);          //清空set中的所有位(在使用檔案描述符集前,應該先清空一下)
    //(注意FD_CLR和FD_ZERO的區別,一個是清除某一位,一個是清除所有位)
 

5、select的返回情況: 
1)如果指定timeout為NULL,select會永遠等待下去,直到有一個檔案描述符就緒,select返回; 
2)如果timeout的指定時間為0,select根本不等待,立即返回; 
3)如果指定一段固定時間,則在這一段時間內,如果有指定的檔案描述符就緒,select函式返回,如果超過指定時間,select同樣返回。 
4)返回值情況: 
a)超時時間內,如果檔案描述符就緒,select返回就緒的檔案描述符總數(包括可讀、可寫和異常),如果沒有檔案描述符就緒,select返回0; 
b)select呼叫失敗時,返回 -1並設定errno,如果收到訊號,select返回 -1並設定errno為EINTR。

6、檔案描述符的就緒條件: 
在網路程式設計中, 
1)下列情況下socket可讀: 
a) socket核心接收緩衝區的位元組數大於或等於其低水位標記SO_RCVLOWAT; 
b) socket通訊的對方關閉連線,此時該socket可讀,但是一旦讀該socket,會立即返回0(可以用這個方法判斷client端是否斷開連線); 
c) 監聽socket上有新的連線請求; 
d) socket上有未處理的錯誤。 
2)下列情況下socket可寫: 
a) socket核心傳送緩衝區的可用位元組數大於或等於其低水位標記SO_SNDLOWAT; 
b) socket的讀端關閉,此時該socket可寫,一旦對該socket進行操作,該程序會收到SIGPIPE訊號; 
c) socket使用connect連線成功之後; 
d) socket上有未處理的錯誤。

select優點:

   select模型是Windows sockets中最常見的IO模型。它利用select函式實現IO 管理。通過對select函式的呼叫,應用程式可以判斷套接字是否存在資料、能否向該套接字寫入據。

    如:在呼叫recv函式之前,先呼叫select函式,如果系統沒有可讀資料那麼select函式就會阻塞在這裡。當系統存在可讀或可寫資料時,select函式返回,就可以呼叫recv函式接   收資料了。

   可以看出使用select模型,需要兩次呼叫函式。第一次呼叫select函式第二次socket API。使用該模式的好處是:可以等待多個套接字。

select缺點:
(1)每次調⽤用select,都需要把fd集合從⽤使用者態拷貝到核心態,這個開銷在fd很多時會很⼤大
(2)同時每次調⽤用select都需要在核心遍歷傳遞進來的所有fd,這個開銷在fd很多時也很⼤大
(3)select⽀支援的⽂檔案描述符數量太⼩