linux下的epoll較之傳統的select函數比較其優點
突破了單進程打開SOCKET描述符最大數目的限制,select單進程打開FD的數據是有限制的,由FD_SETSIZE設置,默認值是2048,而這在那此需要支持上萬連接數目的網絡服務器來說是不能忍受的,雖然這個限制可以通過修改宏重編譯內核,但這會給效率帶來急劇下降,而epoll卻沒有這個限制,理論上打開FD的數目跟系統內在有關;
另外效率不會隨連接數的增加而線性下降,它只會對活躍的IO事件進行操作,而select每次調用返回的是線性掃描的全集,不過在一個高速的網絡環境里epoll的性能并不比select高多少,因為大部分的socket基本都是活躍的
epoll使用
epoll函數非常簡單,epoll_create,epoll_ctl,epoll_wait 3個函數,可用man查看具體函數說明,先使用epoll_create創建一個epoll的句柄,再通過epoll_ctl注冊事件,然后epoll_wait檢測事件的發生。
epoll二種工作模式的區別
Edge Triggered (ET)、Level Triggered (LT);ET(edge-triggered)是高速工作方式,只支持no-block socket。當IO事件發生時內核通知你后不會再發送更多的通知,一直到你執行的操作導致那個文件描述符事件的改變,如果你不對其進程IO操作,內核不會再通知你。Level Triggered (LT)是缺省的工作方式,并且同時支持block和no-block socket.內核告訴你一個文件描述符是否就緒了,然后你可以對這個就緒的fd進行IO操作。如果你不作任何操作,內核還是會繼續通知你的,你可以使用EPOLLONESHOT標志來告訴內核只通知一次,需注意的是操作完后使用帶有 EPOLL_CTL_MOD標志epoll_ctl修改處理文件描述符
ET模式使用在epoll_ctl加入事件時使用EPOLLET標志來設置。ET模式在IO處理時需注意使用非阻塞模式,網上有很多這樣的例子
ACE及libevent都使用LT模式。而ACE的ACE_Dev_Poll_Reactor反應器不支持線程池,雖然其代碼里也類似TP_Reactor通過鎖來互斥epoll_wait 操作,但在多線程應用中會出現問題。本人參照TP_Reactort自寫了一個L/F線程池支持的epoll反應器,在一個項目中已經在使用。