1. 數據結構
//表示一個要監聽的事件
//其中events表示監聽的標誌位 EPOLLIN EPOLLOUT
//表示被觸發後的data
struct epoll_event{
uint32_t events;
epoll_data_t data;
}
//其中只有ptr數據結構比較重要
typedef union epoll_data{
void *ptr;
int fd;
}
在nginx的實現,
struct epoll_event e;//定義需要監聽的事件
e.events = 傳進來的值 ;//用來表示監控輸入還是輸出
e.data.ptr = connection;//當有事件觸發時,獲取得到data.ptr從而得到連接
2. epoll create/close
int epoll_create(int size)// size預估事件多少
// 返回epoll的fd
epoll_close(efd);
3. 添加事件
int epoll_ctr(int efd, int op, int fd , struct epoll_event *event)
//efd 由epoll_create創建的fd
//op 分爲3種操作,EPOLL_CTL_ADD EPOLL_CTL_MOD EPOLL_CTL_DEL
//event 添加需要監控的事件, 數據結構如上。
4. 監聽事件
int epoll_wait(int efd, struct epoll_event *event, int maxeevents, int timeout)
//efd 由epoll_create創建的fd
//timeout 爲一次監聽的間隔
//當有事件觸發 返回int 表示事件個數,event裏存儲的是觸發的事件
5. LT && ET
LT 當緩衝區還有數據時會一直觸發,支持阻塞和非阻塞兩種
ET 只觸發有數據那一次,只支持非阻塞
如果爲非阻塞則需要
// 設置events 爲ET
ep_event.events |= EPOLLET
// 獲取得到原來的fd, 加上O_NONBLOCK
int old_flags = fcntl(fd, F_GETFL);
fcntl(fd, F_SETFL, old_flags | O_NONBLOCK);
在nginx的中用到了這樣的一個原理
不管在32bit 和 64bit機器上,指針的最後一位都是0, 在事件觸發之後, 先通過 e.data.ptr得到conn的指針,指針的最後一位有個instance,指針的read 或者 write中有個instance,兩個instance 來對比,一致表示是有效連接