C++网络编程快速入门(四):EPOLL模型使用
目錄
- 基本使用方法
- step1:創(chuàng)建epollfd
- step2:將fd綁定到epollfd
- step3:調用epoll_wait檢測事件
- epoll_wait與poll、select區(qū)別所在
- 水平觸發(fā)與邊緣觸發(fā)
基本使用方法
step1:創(chuàng)建epollfd
- 創(chuàng)建一個epollfd,若epoll_create調用成功,則返回一個非負值的epollfd,否則返回-1
step2:將fd綁定到epollfd
有了epollfd之后,我們有三種需求:
1、將需要檢測事件的其他fd綁定到這個epollfd上
2、修改一個已經綁定到epollfd的fd的事件類型
3、在不需要的時候將fd從epollfd上解綁
都需要依托函數(shù)epoll_ctl完成:
__epfd:即epollfd
__op:操作類型,有三種EPOLL_CTL_ADD、EPOLL_CTL_MOD、EPOLL_CTL_DEL。分別對應著在epollfd上添加、修改、移除fd,當為EPOLL_CTL_DEL時,__event參數(shù)忽略,置NULL
__fd:需要備操作的fd
__event:一個epoll_event結構體的地址
具體結構如下:
返回值:
調用成功,返回0;
調用失敗,返回-1,通過errno錯誤碼可以獲取具體的錯誤原因。
step3:調用epoll_wait檢測事件
/* Wait for events on an epoll instance "epfd". Returns the number oftriggered events returned in "events" buffer. Or -1 in case oferror with the "errno" variable set to the specific error code. The"events" parameter is a buffer that will contain triggeredevents. The "maxevents" is the maximum number of events to bereturned ( usually size of "events" ). The "timeout" parameterspecifies the maximum wait time in milliseconds (-1 == infinite).This function is a cancellation point and therefore not marked with__THROW. */ extern int epoll_wait (int __epfd, struct epoll_event *__events,int __maxevents, int __timeout);__events:一個epoll_event結構數(shù)組的首地址,是一個輸出參數(shù),在函數(shù)調用成功后,在events中存放的是與就緒事件相關的epoll_event結構體數(shù)組。
__maxevents:數(shù)組元素個數(shù)
__timeout:超時時間,單位為ms
返回值:調用成功返回有事件的fd數(shù)量,若返回0,表示超時。若返回-1,表示調用失敗。
使用示例如下:
epoll_wait與poll、select區(qū)別所在
在第二講中演示了select的基本使用方式:C++網(wǎng)絡編程快速入門(二):Linux下使用select演示簡單服務端程序
select和epoll底層機制一樣,所以這里只看select。
可以發(fā)現(xiàn)調用完select之后,需要在原來的clientfds數(shù)組中遍歷,然后加條件判斷是否是有事件的。
而epoll_wait調用完之后是直接返回一個篩選過后的有事件的events數(shù)組。
所以:
在fd數(shù)量比較多但是某段時間內的就緒事件fd數(shù)量較少時,epoll_wait函數(shù)更加高效。
也就是epoll模型更適合用在socket連接數(shù)量較大而活躍的連接較少的情景下
水平觸發(fā)與邊緣觸發(fā)
epoll具有兩種模式:邊緣觸發(fā)模式(Edge Trigger,ET)和水平觸發(fā)模式(Level Trigger,LT)。
區(qū)別在于:
1、LT:一個事件只要有,就會一直觸發(fā)
2、ET:一個事件從無到有,才會觸發(fā)
以socket讀事件為例:
水平模式下,只要socket上有未讀完的數(shù)據(jù),就會一直產生EPOLLIN事件。
邊緣模式下,socket上每新來一次數(shù)據(jù)就會觸發(fā)一次,如果上一次觸發(fā)后未將socket上的數(shù)據(jù)讀完,也不會再觸發(fā),除非再新來一次數(shù)據(jù)。
以socket寫事件為例:
水平模式下,只要socket上TCP窗口一直不飽和,就會一直觸發(fā)EPOLLOUT事件。
邊緣模式下,只有TCP窗口由不飽和變成飽和 或者 再一次變成不飽和,才會觸發(fā)EPOLLOUT事件。
這對于編程的啟示是:
1、對于非阻塞socket,如果epoll使用邊緣模式檢測事件可讀,那么一旦觸發(fā),一定要一次性把socket上數(shù)據(jù)收取干凈,即循環(huán)調用recv函數(shù)直到recv出錯
2、如果是水平模式,可以根據(jù)業(yè)務一次性收取固定字節(jié)數(shù)
下面總結一下兩者在編碼上需要注意的地方:
1、LT模式下,讀事件觸發(fā)后可以按需收取想要的字節(jié)數(shù),不用把本次數(shù)據(jù)收取干凈;
ET模式下,讀事件必須把數(shù)據(jù)收取干凈,因為我們不一定再有機會收取數(shù)據(jù)了。
2、LT模式下,不需要寫事件時一定要及時移除,避免不必要地觸發(fā)且浪費CPU資源。
ET模式下,寫事件觸發(fā)后,如果還需要下一次的寫事件觸發(fā)來驅動任務(例如發(fā)送上次剩余的數(shù)據(jù)),則我們需要繼續(xù)注冊一次檢測可寫事件
3、LT會導致多次觸發(fā),ET優(yōu)點是觸發(fā)次數(shù)少
總結
以上是生活随笔為你收集整理的C++网络编程快速入门(四):EPOLL模型使用的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 全网通手机多少钱啊?
- 下一篇: C++智能指针使用指南 part2:智能