epoll是linux內核爲處理大批量文件描述符而作了改進的poll,是linux下IO複用select/poll的增強版本。
一、epoll的主要接口是:
1、創建
(1)int epoll_create(int maxfds);
maxfds是支持的最大句柄數。該函數會返回一個新的epoll句柄,之後的函數調用都用這個句柄來操作。用完之後,記得用close()關閉這個創建出來的epoll句柄,否則可能導致系統fd被耗盡。
(2)int epoll_reate1(int flag);
上面創建的方法在linux 2.6.8之後,maxfds是被忽略的,所以建議採用epoll_create1(0)這種方法。另外epoll_create1(EPOLLCLOEXEC)表示生成的epoll fd具有“執行後關閉”的特性。
2、事件註冊
int epoll_ctl(int epfd,int op,int fd,struct epoll_event* event);
epoll的事件註冊函數,它不同於select/poll在監聽的時候告訴內核要監聽什麼事件,而是先註冊要監聽的事件類型。
(1)epfd爲(1)返回的epoll句柄
(2)op表示動作,用三個宏來表示:
EPOLL_CTL_ADD:註冊新的fd到epfd中
EPOLL_CTL_MOD:修改已註冊的fd的監聽事件
EPOLL_CTL_DEL:從epfd中刪除一個fd
(3)fd爲要監聽的fd
(4)event爲要監聽的事件,結構如下:
struct epoll_event
{
__uint32_t events;
epoll_data_t data;
};
events可以是一下宏的集合:
EPOLLIN :表示對應的文件描述符可以讀(包括對端SOCKET正常關閉);
EPOLLOUT:表示對應的文件描述符可以寫;
EPOLLPRI:表示對應的文件描述符有緊急的數據可讀(這裏應該表示有帶外數據到來);
EPOLLERR:表示對應的文件描述符發生錯誤;
EPOLLHUP:表示對應的文件描述符被掛斷;
EPOLLET: 將EPOLL設爲邊緣觸發(Edge Triggered)模式,這是相對於水平觸發(Level Triggered)來說的。
EPOLLONESHOT:只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列裏
3、等待事件發生
int epoll_wait(int epfd,struct epoll_event* events,int maxevents,int timeout);
等待事件發生,類似於select()調用。參數events用來從內核得到事件的集合,maxevents告訴內核這個events有多大,maxevents不能大於epoll_create時設置的size,參數timeout是超時時間(毫秒,0立即返回,-1將永久阻塞)。該函數返回需要處理的事件數目,如果返回0表示已超時。
二、epoll的兩種工作模式
epoll默認的工作模式是Level Triggered,通過epoll_ctl可以設置epoll的工作模式爲Edge Triggered。
LT(levet triggered)同時支持block和no-block socket。在該模式下,內核告訴你一個文件描述符是否就緒了,然後你可以對這個就緒的fd進行IO操作。如果你不作任何操作,內核還是會繼續通知你的,所以,這種模式編程出錯的可能性要小一點。傳統的select/poll都是這種模型的代表。
ET(edge triggered)是高速工作方式,只支持non-block socket。在這種模式下,當描述符從未就緒變爲就緒時,內核通過epoll告訴你。如果描述符沒有再次發生IO操作(導致它再次變成未就緒),內核不會發送更多的通知。例如:ET模式下epoll_wait返回,當前緩存中接收到了2KB的數據,調用read讀取1KB的數據。下次循環調用epoll_wai時將不會受到內核通知,將阻塞在這裏,直到發生IO操作(如又收到數據)。當調用read或者write返回EAGAIN時,才需要掛起。但我們一般在處理循環讀時,當read()返回的讀到的數據長度小於請求的數據長度時,就可以確定此時緩衝中已沒有數據了,也就可以認爲此事讀事件已處理完成。
三、epoll相對於select/poll的優勢
1、epoll通過epoll_ctl註冊監聽的事件,而不像select/poll在每次循環調用select/poll函數時,設置監聽事件,把fd集合從用戶態拷貝到內核態),這個開銷在fd很多時會很大。
2、select/poll在監聽事件發生後,需要遍歷所有fd,這個開銷在fd很多時也很大,而epoll_wait返回的就是需要處理的事件。
3、select支持的最大文件描述符個數默認爲1024,不適合處理大批量的文件描述符。而epoll就沒有限制。
4、在併發連接數較大而活動連接數較小時,epoll比poll效率更高;而如果所有連接基本都是活躍的,比如一個高速LAN環境,epoll並不比select/poll有什麼效率。