認識epoll

linux下的epoll(7)函數,其有着良好的就緒事件通知機制。Epoll 是被linux2.6開始引進的,可是不被其餘的類UNIX系統支持,它提供了一種相似select或poll函數的機制:
a. Select(2)只可以同時管理FD_SETSIZE(默認爲1024)數目的文件描述符,而且必須遍歷全部的描述符來檢查就緒的描述符。
b. poll(2)沒有固定的描述符上限這一限制,可是每次必須遍歷全部的描述符來檢查就緒的描述符,這個過程的時間複雜度爲O(n)。
epoll沒有select這樣對文件描述符上限的限制,也不會像select/poll那樣進行線性的遍歷。所以epoll處理大併發鏈接有着更高的性能。html

咱們從select那裏僅僅知道了,有I/O事件發生了,但卻並不知道是那幾個流(可能有一個,多個,甚至所有),咱們只能無差異輪詢全部流,找出能讀出數據,或者寫入數據的流,對他們進行操做。
可是使用select,咱們有O(n)的無差異輪詢複雜度,同時處理的流越多,每一次無差異輪詢時間就越長。
epoll能夠理解爲event poll,不一樣於忙輪詢和無差異輪詢,epoll只會把哪一個流發生了怎樣的I/O事件通知咱們(時間複雜度下降到了O(1))。此時咱們對這些流的操做都是有意義的。linux


Epoll相關操做函數介紹:
1. epoll_create(2) or epoll_create1(2)(有着不一樣的參數值)用來建立epoll實例。
/usr/include/sys/epoll.h
extern int epoll_create (int __size) ;
RETURN:>0, 成功;-1, 出錯
函數描述:
(1) epoll_create返回的是一個文件描述符,也就是說epoll是以特殊文件的方式體現給用戶
(2) __size提示操做系統,用戶可能要使用多少個文件描述符,該參數已經廢棄,填寫一個大於0的正整數
程序員

2. epoll_ctl(2)用來增長或移除被epoll所監聽的文件描述符。數組

int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);

RETURN:0,成功;-1,出錯併發

函數描述:
(1) epfd爲epoll_create建立的epoll描述符
(2) epoll_ctl函數對epoll進行op類型的操做,op選項爲
EPOLL_CTL_ADD,對fd描述符註冊event事件
EPOLL_CTL_MOD,對fd描述符的event事件進行修改
EPOLL_CTL_DEL,刪除已註冊的event事件socket

3. epoll_wait(2)用來等待發生在監聽描述符上的事件。它會一直阻塞直到事件發生。
#include函數

int epoll_wait(int epfd, struct epoll_event *events,
int maxevents, int timeout);

RETURN:>0,發生事件個數;=0,時間到;-1,出錯性能

函數描述:
epoll_wait與select函數相似,同步地等待事件發生
(1) epfd,標識epoll的文件描述符
(2) events,指向傳入操做系統的一個epoll_event數組
(3) maxevents,表示傳入數組的大小,必須大於0
當有事件發生,Linux會填寫events結構,返回給應用程序。因爲epoll_wait同步等待,有可能被信號中斷,返回EINTR錯誤.
這裏有一個比較重要的問題:從epoll_wait返回的events中,該如何知道是哪一個描述符上的事件:在註冊epoll事件的時候,必定要填寫epoll_data,不然咱們將分不清觸發的是哪一個描述符上的事件。
Epoll的兩種模式:
1. 水平觸發(LT):使用此種模式,當數據可讀的時候,epoll_wait()將會一直返回就緒事件。若是你沒有處理徹底部數據,而且再次在該 epoll實例上調用epoll_wait()才監聽描述符的時候,它將會再次返回就緒事件,由於有數據可讀。LT(level triggered)是缺省的工做方式,而且同時支持block和no-block socket.。
2. 邊緣觸發(ET):使用此種模式,只能獲取一次就緒通知,若是沒有處理徹底部數據,而且再次調用epoll_wait()的時候,它將會阻塞,由於就緒事件已經釋放出來了。ET只支持非阻塞socket。
ET的效能更高,可是對程序員的要求也更高。在ET模式下,咱們必須一次乾淨而完全地處理完全部事件。
傳遞給epoll_ctl(2)的Epoll事件結構體以下所示:ui

typedef union epoll_data
{
void*ptr;
intfd;
__uint32_t u32;
__uint64_t u64;
}epoll_data_t;

struct epoll_event
{
__uint32_t events;/* Epoll events */
epoll_data_t data;/* User data variable */
};

對於每個監聽的描述符,可以關聯一個整形數據或指向用戶數據的指針。spa

epoll的事件類型:
– EPOLLIN,讀事件
– EPOLLOUT,寫事件
– EPOLLPRI,帶外數據,與select的異常事件集合對應
– EPOLLRDHUP,2.6.17 版本內核中增長了 EPOLLRDHUP 事件,表明對端斷開鏈接(參見EPOLL事件之EPOLLRDHUP)
– EPOLLERR,錯誤事件
– EPOLLET,設置事件爲邊沿觸發
– EPOLLONESHOT,只觸發一次,事件自動被刪除
一個文件描述符在一個epoll實例上只能註冊一次,一個描述符在同一個epoll實例上註冊屢次,會產生EEXIST的錯誤。
一樣,刪除epoll的事件,只需描述符就夠了
epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);

引用:

epoll實例

epoll 或者 kqueue 的原理是什麼?

相關文章
相關標籤/搜索