epol學習筆記 l epoll的相關係統調用 epoll_create() epoll_ctl() epoll_wait() l int epoll_create(int size); 創建一個epoll的句柄。 l int epoll_ctl(int epfd, int op, int fd, ...
epol學習筆記
l epoll的相關係統調用
epoll_create()
epoll_ctl()
epoll_wait()
l int epoll_create(int size);
創建一個epoll的句柄。
- 自從linux2.6.8之後,size參數是被忽略的。
- 創建epoll句柄後,它就是會占用一個fd值,在使用完epoll後,必須調用close()關閉。
l int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event);
epoll的事件註冊函數。
1. 第一個參數是epoll_create()的返回值。
2. 第二個參數表示動作,用三個巨集來表示:
EPOLL_CTL_ADD:註冊新的fd到epfd中;
EPOLL_CTL_MOD:修改已經註冊的fd的監聽事件;
EPOLL_CTL_DEL:從epfd中刪除一個fd。
3. 第三個參數是需要監聽的fd。
4. 第四個參數是告訴內核需要監聽什麼事。
struct epoll_event結構如下:
typedef union epoll_data
{//保存觸發事件的某個文件描述符相關的數據
void *ptr;
int fd;
__uint32_t u32;
__uint64_t u64;
} epoll_data_t;
struct epoll_event
{
__uint32_t events;/* Epoll events */
epoll_data_t data;/* User data variable */
};
events可以是以下幾個巨集的集合:
- EPOLLIN:表示對應的文件描述符可以讀(包括對端SOCKET正常關閉);
- EPOLLOUT:表示對應的文件描述符可以寫;
- EPOLLPRI:表示對應的文件描述符有緊急的數據可讀(這裡應該表示有帶外數據到來);
- EPOLLERR:表示對應的文件描述符發生錯誤;
- EPOLLHUP:表示對應的文件描述符被掛斷;
- EPOLLET:將EPOLL設為邊緣觸發(Edge Triggered)模式,這是相對於水平觸發(Level Triggered)來說的。
- EPOLLONESHOT:只監聽一次事件,當監聽完這次事件之後,如果還需要繼續監聽這個socket的話,需要再次把這個socket加入到EPOLL隊列里。
l int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);
收集在epoll監控的事件中已經發生的事件。
- 參數events是分配好的epoll_event結構體數組,epoll將會把發生的事件賦值到events數組中(events不可以是空指針,內核只負責把數據複製到這個events數組中,不會去幫助我們在用戶態中分配記憶體)。
- maxevents告之內核這個events有多大,這個maxevents的值不能大於創建epoll_create()時的size。(自從linux2.6.8之後,size參數是被忽略的。)maxevents值使用cat /proc/sys/fs/file-max命令查詢,與記憶體的大小有關。
- 最後一個timeout是epoll_wait的超時,為0的時候表示馬上返回,為-1的時候表示一直等下去,直到有事件發生,為任意正整數的時候表示等這麼長的時間,如果一直沒有事件,則返回。一般如果網路主迴圈是單獨的線程的話,可以用-1來等,這樣可以保證一些效率,如果是和主邏輯在同一個線程的話,則可以用0來保證主迴圈的效率。
- 如果函數調用成功,返回對應I/O上已準備好的文件描述符數目,如返回0表示已超時。
l Edge Triggered 工作模式
- epoll工作在ET模式的時候,必須使用非阻塞套介面,以避免由於一個文件句柄的阻塞讀/阻塞寫操作把處理多個文件描述符的任務餓死。
- 最好以下麵的方式調用ET模式的epoll介面,在後面會介紹避免可能的缺陷。
@ 基於非阻塞文件句柄
@ 只有當read()或者write()返回EAGAIN時才需要掛起,等待。
但這並不是說每次read()時都需要迴圈讀,直到讀到產生一個EAGAIN才認為此次事件處理完成,當read()返回的讀到的數據長度小於請求的數據長度時,就可以確定此時緩衝中已沒有數據了,也就可以認為此事讀事件已處理完成。