IO多路復用之poll總結

2021-07-05 03:19:10 字數 4495 閱讀 5936

1、基本知識

poll的機制與select類似,與select在本質上沒有多大差別,管理多個描述符也是進行輪詢,根據描述符的狀態進行處理,但是poll沒有最大檔案描述符數量的限制。poll和select同樣存在乙個缺點就是,包含大量檔案描述符的陣列被整體複製於使用者態和核心的位址空間之間,而不論這些檔案描述符是否就緒,它的開銷隨著檔案描述符數量的增加而線性增大。

2、poll函式

函式格式如下所示:

# include 

int poll ( struct pollfd * fds, unsigned

int nfds, int timeout);

pollfd結構體定義如下:

struct pollfd ;

每乙個pollfd結構體指定了乙個被監視的檔案描述符,可以傳遞多個結構體,指示poll()監視多個檔案描述符。每個結構體的events域是監視該檔案描述符的事件掩碼,由使用者來設定這個域。revents域是檔案描述符的操作結果事件掩碼,核心在呼叫返回時設定這個域。events域中請求的任何事件都可能在revents域中返回。合法的事件如下:

pollin         有資料可讀。

pollrdnorm      有普通資料可讀。

pollrdband      有優先資料可讀。

pollpri         有緊迫資料可讀。

pollout       寫資料不會導致阻塞。

pollwrnorm      寫普通資料不會導致阻塞。

pollwrband      寫優先資料不會導致阻塞。

pollmsgsigpoll     訊息可用。

此外,revents域中還可能返回下列事件:

poller   指定的檔案描述符發生錯誤。

pollhup   指定的檔案描述符掛起事件。

pollnval  指定的檔案描述符非法。

這些事件在events域中無意義,因為它們在合適的時候總是會從revents中返回。

使用poll()和select()不一樣,你不需要顯式地請求異常情況報告。

pollin | pollpri等價於select()的讀事件,pollout |pollwrband等價於select()的寫事件。pollin等價於pollrdnorm |pollrdband,而pollout則等價於pollwrnorm。例如,要同時監視乙個檔案描述符是否可讀和可寫,我們可以設定 events為pollin |pollout。在poll返回時,我們可以檢查revents中的標誌,對應於檔案描述符請求的events結構體。如果pollin事件被設定,則檔案描述符可以被讀取而不阻塞。如果pollout被設定,則檔案描述符可以寫入而不導致阻塞。這些標誌並不是互斥的:它們可能被同時設定,表示這個檔案描述符的讀取和寫入操作都會正常返回而不阻塞。

timeout引數指定等待的毫秒數,無論i/o是否準備好,poll都會返回。timeout指定為負數值表示無限超時,使poll()一直掛起直到乙個指定事件發生;timeout為0指示poll呼叫立即返回並列出準備好i/o的檔案描述符,但並不等待其它的事件。這種情況下,poll()就像它的名字那樣,一旦選舉出來,立即返回。

返回值和錯誤**

成功時,poll()返回結構體中revents域不為0的檔案描述符個數;如果在超時前沒有任何事件發生,poll()返回0;失敗時,poll()返回-1,並設定errno為下列值之一:

ebadf   乙個或多個結構體中指定的檔案描述符無效。

efaultfds   指標指向的位址超出程序的位址空間。

eintr     請求的事件之前產生乙個訊號,呼叫可以重新發起。

einvalnfds  引數超出plimit_nofile值。

enomem   可用記憶體不足,無法完成請求。

3、測出程式

編寫乙個echo server程式,功能是客戶端向伺服器傳送資訊,伺服器接收輸出並原樣傳送回給客戶端,客戶端接收到輸出到終端。

伺服器端程式如下:

#include 

#include

#include

#include

#include

#include

#include

#include

#include

#define ipaddress "127.0.0.1"

#define port 8787

#define maxline 1024

#define listenq 5

#define open_max 1000

#define inftim -1

//函式宣告

//建立套接字並進行繫結

static

int socket_bind(const

char* ip,int port);

//io多路復用poll

static

void do_poll(int listenfd);

//處理多個連線

static

void handle_connection(struct pollfd *connfds,int num);

int main(int argc,char *argv)

static

int socket_bind(const

char* ip,int port)

bzero(&servaddr,sizeof(servaddr));

servaddr.sin_family = af_inet;

inet_pton(af_inet,ip,&servaddr.sin_addr);

servaddr.sin_port = htons(port);

if (bind(listenfd,(struct sockaddr*)&servaddr,sizeof(servaddr)) == -1)

return listenfd;

}static

void do_poll(int listenfd)

//測試監聽描述符是否準備好

if (clientfds[0].revents & pollin)

}fprintf(stdout,"accept a new client: %s:%d\n", inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port);

//將新的連線描述符新增到陣列中

for (i = 1;i < open_max;i++)

}if (i == open_max)

//將新的描述符新增到讀描述符集合中

clientfds[i].events = pollin;

//記錄客戶連線套接字的個數

maxi = (i > maxi ? i : maxi);

if (--nready <= 0)

continue;

}//處理客戶連線

handle_connection(clientfds,maxi);

}}static

void handle_connection(struct pollfd *connfds,int num)

// printf("read msg is: ");

write(stdout_fileno,buf,n);

//向客戶端傳送buf

write(connfds[i].fd,buf,n);}}

}

客戶端**如下所示:

#include 

#include

#include

#include

#include

#include

#include

#include

#include

#define maxline 1024

#define ipaddress "127.0.0.1"

#define serv_port 8787

#define max(a,b) (a > b) ? a : b

static

void handle_connection(int sockfd);

int main(int argc,char *argv)

static

void handle_connection(int sockfd)

write(stdout_fileno,recvline,n);

}//測試標準輸入是否準備好

if (pfds[1].revents & pollin)

write(sockfd,sendline,n);}}

}

4、程式測試結果

IO多路復用之poll總結

1 基本知識 poll的機制與select類似,與select在本質上沒有多大差別,管理多個描述符也是進行輪詢,根據描述符的狀態進行處理,但是poll沒有最大檔案描述符數量的限制。poll和select同樣存在乙個缺點就是,包含大量檔案描述符的陣列被整體複製於使用者態和核心的位址空間之間,而不論這些...

I O多路復用之poll

poll的優點 1 poll 不要求開發者計算最大檔案描述符加一的大小。2 poll 在應付大數目的檔案描述符的時候速度更快,相比於select。3 它沒有最大連線數的限制,原因是它是基於鍊錶來儲存的。poll的缺點 1 大量的fd的陣列被整體複製於使用者態和核心位址空間之間,而不管這樣的複製是不是...

IO多路復用之poll

poll和select區別 poll伺服器監視的檔案描述符無上限 poll將輸入 輸出引數進行分離。一 poll函式 函式格式如下所示 include int poll struct pollfd fds,unsigned int nfds,int timeout 不同與select使用三個點陣圖來...