epoll模型會顯著提高程序在大量併發連接中只有少量活躍的情況下的系統CPU利用率。epoll是通過內核與用戶空間mmap同一塊內存實現的。
epoll可以理解為event poll,epoll之會把哪個流發生了怎樣的I/O事件通知我們。此時我們對這些流的操作都是有意義的。
LT和ET模式
LT(LevelTriggered,電平觸發):LT模式是epoll默認的工作模式,在LT模式下,epoll相當於一個效率較高的poll,採用LT模式的文件描述符,當epoll_wait檢測到其上有事件發生並將此事件通知應用程序後,應用程序可以不立即處理此事件,當下一次調用epoll_wait是,epoll_wait還會將此事件通告應用程序。
ET(EdgeTriggered,邊沿觸發):當調用epoll_ctl,向參數event註冊EPOLLET事件時,epoll將以ET模式來操作該文件描述符,ET模式是epoll的高效工作模式.對於採用ET模式的文件描述符,當epoll_wait檢測到其上有事件發生並將此通知應用程序後,應用程序必須立即處理該事件,因為後續的epoll_wait調用將不在嚮應用程序通知這一事件。ET模式降低了同意epoll事件被觸發的次數,效率比LT模式高。
在討論epoll的實現細節之前,先把epoll的相關操作列出:
epoll_create函數會為要監聽的fd分配內存。
epoll_ctl函數將要監聽的fd拷貝到內核空間,從而避免每次等待事件都要進行內存拷貝。同時,註冊一個回調函數到 fd的設備等待隊列中,這樣,當設備就緒的時候,驅動程序可以直接調用回調函數進行處理,從而避免了對所有監聽fd的輪循。
epoll_wait函數會檢查是否已經有fd就緒了,如果有則直接返回,如果沒有,則進入休眠狀態,直到被上述的回調函數喚醒或者超時時間到達。
epoll_create 創建一個epoll對象,一般epollfd = epoll_create()
epoll_ctl (epoll_add/epoll_del的合體),往epoll對象中增加/刪除某一個流的某一個事件
epoll_ctl(epollfd, EPOLL_CTL_ADD, socket, EPOLLIN);//註冊緩衝區非空事件,即有數據流入
epoll_ctl(epollfd, EPOLL_CTL_DEL, socket, EPOLLOUT);//註冊緩衝區非滿事件,即流可以被寫入
epoll_wait(epollfd,...)等待直到註冊的事件發生
注意:當對一個非阻塞流的讀寫發生緩衝區滿或緩衝區空,write/read會返回-1,設置errno=EAGAIN。epoll只關心緩衝區非滿和緩衝區非空事件。
一個epoll模式的代碼大概的樣子是:
while true {
active_stream[] = epoll_wait(epollfd)
for i in active_stream[] {
read or write till
}
}
更多內容請關注每日編程,每天進步一點。
閱讀更多 每日編程 的文章