由於poll()和select()的侷限,2.6核心以上引用了event poll機制(就是說的epoll),雖然比前2個實現複雜得多,epoll解決了它們共有的基本效能問題,並增加了新的特性。
poll()和select()每次呼叫的時候,都需要所有被監聽的檔案的描述符。核心必須遍歷所有被監視的檔案描述符。當這個表變得很大時,每次呼叫,都會成為效能降低。
epoll把監聽註冊從實際監聽中分離出來,從而解決這個問題:乙個系統呼叫初始化乙個epoll上下文,另乙個從上下文中加入或刪除需要監視的檔案描述符,第三個執行真正的事件等待(event wait)。
先來看看常用模型的缺點(如果不擺出來其他模型的缺點,怎麼能對比出 epoll 的優點呢):
① ppc/tpc 模型
這兩種模型思想類似,就是讓每乙個到來的連線一邊自己做事去,別再來煩我。只是 ppc 是為它開了乙個程序,而 tpc 開了乙個執行緒。可是別煩我是有代價的,它要時間和空間啊,連線多了之後,那麼多的程序 / 執行緒切換,這開銷就上來了;因此這類模型能接受的最大連線數都不會高,一般在幾百個左右。
② select 模型
1. 最大併發數限制,因為乙個程序所開啟的 fd (檔案描述符)是有限制的,由 fd_setsize 設定,預設值是 1024/2048 ,因此 select 模型的最大併發數就被相應限制了。自己改改這個 fd_setsize ?想法雖好,可是先看看下面吧 …
2. 效率問題, select 每次呼叫都會線性掃瞄全部的 fd 集合,這樣效率就會呈現線性下降,把 fd_setsize 改大的後果就是,大家都慢慢來,什麼?都超時了。
3. 核心 / 使用者空間 記憶體拷貝問題,如何讓核心把 fd 訊息通知給使用者空間呢?在這個問題上 select 採取了記憶體拷貝方法。
總結為:1.連線數受限2.查詢配對速度慢3.資料由核心拷貝到使用者態
③ poll 模型
基本上效率和 select 是相同的, select 缺點的 2 和 3 它都沒有改掉。
三). epoll 的提公升
把其他模型逐個批判了一下,再來看看 epoll 的改進之處吧,其實把 select 的缺點反過來那就是 epoll 的優點了。
①. epoll 沒有最大併發連線的限制,上限是最大可以開啟檔案的數目,這個數字一般遠大於 2048,一般來說這個數目和系統記憶體關係很大,具體數目可以 cat /proc/sys/fs/file-max 察看。
②. 效率提公升, epoll 最大的優點就在於它只管你「活躍」的連線,而跟連線總數無關,因此在實際的網路環境中, epoll 的效率就會遠遠高於 select 和 poll 。
③. 記憶體拷貝, epoll 在這點上使用了「共享記憶體」,這個記憶體拷貝也省略了。
使用 epoll
既然 epoll 相比 select 這麼好,那麼用起來如何呢?會不會很繁瑣啊 … 先看看下面的三個函式吧,就知道 epoll 的易用了。
1int epoll_create(int size);
1int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event );
控制某個 epoll 檔案描述符上的事件:註冊、修改、刪除。其中引數 epfd 是 epoll_create() 建立 epoll 專用的檔案描述符。相對於 select 模型中的 fd_set 和 fd_clr 巨集。
1int epoll_wait(int epfd,struct epoll_event * events,int maxevents,int timeout);
等待 i/o 事件的發生;引數說明:
epfd: 由epoll_create()生成的 epoll 專用的檔案描述符;
epoll_event: 用於回傳代處理事件的陣列;
maxevents: 每次能處理的事件數;
timeout: 等待 i/o 事件發生的超時值;
返回發生事件數。
相對於 select 模型中的 select 函式。
epoll的lt和et的區別
lt:水平觸發,效率會低於et觸發,尤其在大併發,大流量的情況下。但是lt對**編寫要求比較低,不容易出現問題。lt模式服務編寫上的表現是:只要有資料沒有被獲取,核心就不斷通知你,因此不用擔心事件丟失的情況。
et:邊緣觸發,效率非常高,在併發,大流量的情況下,會比lt少很多epoll的系統呼叫,因此效率高。但是對程式設計要求高,需要細緻的處理每個請求,否則容易發生丟失事件的情況。
下面舉乙個列子來說明lt和et的區別(都是非阻塞模式,阻塞就不說了,效率太低):
採用lt模式下, 如果accept呼叫有返回就可以馬上建立當前這個連線了,再epoll_wait等待下次通知,和select一樣。
但是對於et而言,如果accpet呼叫有返回,除了建立當前這個連線外,不能馬上就epoll_wait還需要繼續迴圈accpet,直到返回-1,且errno==eagain
epoll是linux2.6核心以後支援的一種高效能的io多路服用技術。伺服器框架如下:
1 socket( af_inet,sock_stream,0)2 fcntl(listen_fd, f_setfl,flags|o_nonblock);
3 bind( listen_fd, (structsockaddr *)&my_addr,sizeof(struct
sockaddr_in))
4 listen( listen_fd,1
)5 epoll_ctl(epfd,epoll_ctl_add,listen_fd,&ev);
6 ev_s = epoll_wait(epfd,events,20,500);7
for(i=0; i)
13else
if(events[i].events&epollin)
16 }
出處:
epoll 實現I O復用
epoll是linux特有的i o復用函式,它能顯著提高程式在大量併發連線中只有少量活躍的情況下的系統cpu利用率 並且epoll使用一組函式來完成任務,而不是單個函式,它無須遍歷整個被偵聽的描述符集,只要遍歷那些核心i o時間非同步喚醒而加入ready佇列的描述符集合即可。但epoll需要使用乙個...
IO復用模型 epoll
參見 1.epoll模型簡介 epoll是linux多路服用io介面select poll的加強版,e對應的英文單詞就是enhancement,中文翻譯為增強,加強,提高,充實的意思。所以epoll模型會顯著提高程式在大量併發連線中只有少量活躍的情況下的系統cpu利用率。epoll把使用者關心的檔案...
IO復用 epoll系列系統呼叫
1 核心事件表 epoll是linux特有的i o復用函式。epoll把使用者關心的檔案描述上的事件放在核心裡的乙個事件表中,並用乙個額外的檔案描述符來標識該核心事件表。這個額外檔案描述符使用函式epoll create函式來建立。includeint epoll create int size s...