系統提供select函式來實現多路復用輸入/輸出模型,那為什麼提供select函式?首先要知道乙個概念,一次i/o分兩個部分(①等待資料就緒 ②進行i/o),減少等待資料的的比重,增加i/o的比重就可以達到高效伺服器的目的。
select工作原理就是減少等的比重,同時監控多個檔案描述符(或者說檔案控制代碼),一旦其中某乙個進入就緒狀態,就進行i/o操作。監控多個檔案控制代碼可以達到提高就緒狀態出現的概率,就可以使cpu在大多數時間下都處於忙碌狀態,大大提高cpu的效能。達到高效伺服器的目的。
select系統呼叫是用來讓我們的程式監視多個檔案控制代碼的狀態變化的。程式會停在select這⾥裡等待,直到被監視的檔案控制代碼有乙個或多個發⽣生了狀態改變。
(1)select函式引數
下⾯面的巨集提供了處理這三種描述片語的⽅方式:
fd_clr(inr fd,fd_set* set);用來清除描述片語set中相關fd 的位
fd_isset(int fd,fd_set *set);用來測試描述片語set中相關fd 的位是否為真
fd_set(int fd,fd_set*set);用來設定描述片語set中相關fd的位
fd_zero(fd_set *set);用來清除描述片語set的全部位
(2)函式返回值:
執行成功則返回.檔案描述詞狀態已改變的個數
如果返回0代表在描述詞狀態改變前已超過timeout時間,沒有返回;
當有錯誤發生時則返回-1,錯誤原因存於errno,
可監控的⽂檔案描述符個數取決與sizeof(fd_set)的值。我這邊服務 器上sizeof(fd_set)=512,每bit表⽰示⼀乙個⽂檔案描述符,則我伺服器上⽀支援的最⼤大⽂檔案描述符是512*8=4096。
將fd加入select監控集的同時,還要再使用乙個資料結構array儲存放到select監控集中的fd,一是用於再select 返回後,array作為源資料和fd_set進行fd_isset判斷。二是select返回後會把以前加入的但並無事件發生的fd清空,則每次開始 select前都要重新從array取得fd逐一加入(fd_zero最先),掃瞄array的同時取得fd最大值maxfd,用於select的第乙個 引數。
可見select模型必須在select前迴圈array(加fd,取maxfd),select返回後迴圈array(fd_isset判斷是否有時間發生)。
每次進行select都要把檔案描述符集fd由使用者態拷貝到核心態,這樣的開銷會很大。
實現select伺服器,內部要不斷對檔案描述符集fd進行迴圈遍歷,當fd很多時,開銷也很大。
select能監控檔案描述符的數量有限,一般為1024。(sizeof(fd_set) * 8 = 1024(fd_set內部是以位圖表示檔案描述符))
#include
#include
#include
#include
#include
#include
#include
#include
#include
int array_fds[1024];
int startup(char* ip, short port)
int opt = 1;
setsockopt(sock,sol_socket,so_reuseaddr,&opt,sizeof(opt));
struct sockaddr_in local;
local.sin_family = af_inet;
local.sin_port = htons(port);
local.sin_addr.s_addr = inet_addr(ip);
//bind
if(bind(sock,(struct sockaddr*)&local,sizeof(local)) < 0)
//listen
if(listen(sock,10) < 0)
return sock;
}int main(int argc,char* argv)
int listen_sock = startup(argv[1],atoi(argv[2]));
int maxfds = 0;//select第乙個引數
fd_set rfds;
int array_size = sizeof(array_fds)/sizeof(array_fds[0]);
array_fds[0] = listen_sock;
//初始化array_fds
int i = 1;
for(;i < array_size;++i)
while(1)
;//非阻塞式等待,null為阻塞式的等待
fd_zero(&rfds);
maxfds = -1;
for(i = 0; i < array_size;++i)
}switch(select(maxfds+1,&rfds,null,null,/*&timeout*/null ))
else
}if(k == array_size)//表示沒有可用的檔案介面
close(new_fd);}}
else
if(j != 0 && fd_isset(array_fds[j],&rfds))
else
if(s == 0)
else }}
}break;}}
return
0;}
Linux I O多路轉接poll
不同與select使用三個點陣圖來表示三個fdset的方式,poll使用 乙個 pollfd的指標實現。poll函式和select函式的任務相似 等待一組檔案描述符來準備執行i 0。引數 1 第乙個引數 fds struct pollfd 2 第二個引數 nfds nfds用來表示要監視檔案描述符的...
Linux IO多路復用 多路轉接
io多路復用 多路轉接 在沒有io多路復用技術前,程序在同一時間只能監控乙個io狀態 乙個檔案描述符的狀態 例如a和b兩個檔案在操作,定的順序是a前b後,那麼在a阻塞過程中 b在後面也是不能被操作的,這樣會造成資源浪費 響應緩慢。io多路復用 同時監控多個io檔案描述符狀態,如果沒有準備好的描述符 ...
Linux I O多路轉接 poll模型
1.poll模型屬於i o多路轉接模型,是對select模型的一種優化 int poll struct pollfd fds,nfd t nfds,int timeout 2.poll的優點 poll使用陣列儲存檔案描述符,所以能描述的檔案描述個數在理論上沒有上限 poll將輸入輸出型引數進行了分離...