多路復用select與poll
時間:2017-01-04作者:華清遠見
在UNIX/linux中有4中IO模型,分別為: 這幾種IO模(mo)型(xing)(xing)(xing),阻(zu)塞(sai)IO是(shi)長用(yong)到(dao)的(de)(de)(de),并且操(cao)作相對簡單,但是(shi)缺點(dian)在(zai)于效(xiao)率低下,尤其是(shi)在(zai),同(tong)時(shi)操(cao)作多個IO的(de)(de)(de)時(shi)候(hou),不能隨時(shi)的(de)(de)(de)處理各個IO操(cao)作。而(er)非(fei)阻(zu)塞(sai)IO可以解決這個問(wen)題(ti),但是(shi)同(tong)樣也存(cun)在(zai)的(de)(de)(de)問(wen)題(ti),因為(wei)使用(yong)非(fei)阻(zu)塞(sai)IO模(mo)型(xing)(xing)(xing)的(de)(de)(de)時(shi)候(hou),就需要對每個IO操(cao)作進行輪訓(xun)操(cao)作,而(er)實際上輪空的(de)(de)(de)幾率是(shi)很(hen)大的(de)(de)(de),多以非(fei)阻(zu)塞(sai)IO模(mo)型(xing)(xing)(xing)是(shi)在(zai)那(nei)種輪空幾率相對較小(xiao)的(de)(de)(de)的(de)(de)(de)時(shi)候(hou)才會使用(yong)。因為(wei)輪訓(xun)是(shi)會占用(yong)相當多的(de)(de)(de)cpu時(shi)間片的(de)(de)(de)。基于這種考慮多路復用(yong)模(mo)型(xing)(xing)(xing)變產生了。 多路復(fu)用(yong)模型(xing)是(shi)對多個(ge)(ge)IO操(cao)作進(jin)行檢(jian)測,返回可操(cao)作集(ji)合,這樣(yang)就(jiu)(jiu)可以對其進(jin)行操(cao)作了。這樣(yang)就(jiu)(jiu)避(bi)免了阻(zu)塞IO不(bu)能隨時(shi)處(chu)理各個(ge)(ge)IO和(he)非阻(zu)塞占(zhan)用(yong)系(xi)統資源(yuan)的確定。下(xia)面就(jiu)(jiu)多路復(fu)用(yong)中兩(liang)個(ge)(ge)常用(yong)的系(xi)統調用(yong)select和(he)poll進(jin)行簡(jian)單的說明。 1、 select select函數(shu)的原(yuan)型為:
#include <sys/select.h>
select的使用需要維護三類文件描述符集合,分別是: 在使用(yong)select的時候需要注意,在調用(yong)select后(hou)者幾個集(ji)(ji)合(he)就會(hui)變化,變為是操作的集(ji)(ji)合(he),即可讀寫或發生(sheng)異常,所以(yi)在調用(yong)select之前需要保存以(yi)前的集(ji)(ji)合(he)。 系統(tong)為我們提供了下面四(si)個宏來操作這些(xie)文件(jian)描(miao)述符集(ji)合:
void FD_SET(int fd, fd_set *set); 其中FD_SET用來將(jiang)一個文(wen)件描(miao)述符加入到文(wen)件描(miao)述符集(ji)合里,FD_CLR是(shi)(shi)刪除,FD_ISSET是(shi)(shi)判斷(duan)文(wen)件描(miao)述符是(shi)(shi)否在(zai)這個集(ji)合里,而FD_ZERO是(shi)(shi)將(jiang)這個集(ji)合清零。 下面我們以一個(ge)簡(jian)單的例子來(lai)說明(ming)select的使(shi)用。
#include <stdio.h> #define N 64
int main(int argc, char *argv[]) struct sockaddr_in servaddr;
if((servsock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
memset(&servaddr, 0, sizeof(servaddr));
if(bind(servsock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
listen(servsock, 5);
for(;;)
for(i = 0; i <= maxfd; i++)
return 0; 上面這(zhe)段(duan)程序在select會(hui)阻塞,這(zhe)個時(shi)候我們可以(yi)定義一個時(shi)間結構體(ti)變量,如(ru)下:
struct timeval timeout; 這(zhe)個(ge)變量可(ke)以提供一個(ge)微秒級的時間,我(wo)們(men)可(ke)以使用(yong)這(zhe)個(ge)作為超時處(chu)理。使用(yong)方(fang)式就是把(ba)這(zhe)個(ge)變量作為select系(xi)統調用(yong)的后一個(ge)參數。 2、 poll poll的原型為:
#include <poll.h> poll的(de)使用(yong)不(bu)需(xu)(xu)要分別維護幾個(ge)(ge)表,只需(xu)(xu)要維護一個(ge)(ge)結(jie)構體(ti)數(shu)組,這個(ge)(ge)結(jie)構體(ti)為:
struct pollfd { 這個結構體(ti)幾個成(cheng)員(yuan)分(fen)別是我們要監測的(de)文件描述(shu)符,和我們請求的(de)事(shi)件及后返回的(de)事(shi)件。 poll事件(jian)的類型為:
POLLIN There is data to read. 上面這(zhe)些事(shi)件下面三種在events中(zhong)沒有用的,只能(neng)在revents中(zhong)才能(neng)出現。我們可以調用poll并且查看每個文件描述符的返回狀態進(jin)行相應(ying)的操作。 下面以一個簡(jian)單的實力說明poll的使用:
#include <stdio.h>
#define OPEN_MAX openmax
int main(int argc, char **argv) int openmax = getdtablesize();
int listensock, connsock;
for(i = 0; i < OPEN_MAX; i++)
if((listensock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
memset(&servaddr, 0, sizeof(servaddr));
if(bind(listensock, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) listen(listensock, 5);
fds[0].fd = 0;
發表評論
|