1. 程式人生 > >select和epoll的區別,以及epoll的優勢所在

select和epoll的區別,以及epoll的優勢所在

select的缺點:

  1. 支援的fd數量有限: 單個程序能夠監視的檔案描述符的數量存在最大限制,通常是1024,當然可以更改數量,但由於select採用輪詢的方式掃描檔案描述符,檔案描述符數量越多,效能越差;(在linux核心標頭檔案中,有這樣的定義:#define單個程序能夠監視的檔案描述符的數量存在最大限制,通常是1024,當然可以更改數量,但由於select採用輪詢的方式掃描檔案描述符,檔案描述符數量越多,效能越差;(在linux核心標頭檔案中,有這樣的定義:#define __FD_SETSIZE 1024)

  2. 每次呼叫select, 都會把fd從使用者態拷貝到記憶體態 ; 核心 / 使用者空間記憶體拷貝問題,核心 / 使用者空間記憶體拷貝問題,select需要複製大量的控制代碼資料結構,產生巨大的開銷;

  3. 使用的是輪詢的方式,需要核心遍歷傳進來的所有fd; select返回的是含有整個控制代碼的陣列,應用程式需要遍歷整個陣列才能發現哪些控制代碼發生了事件;select返回的是含有整個控制代碼的陣列,應用程式需要遍歷整個陣列才能發現哪些控制代碼發生了事件;

select只提供了一個函式——select函式。而epoll提供了三個函式,epoll_create, epoll_ctlepoll_wait

  • epoll_create是建立一個epoll控制代碼;
  • epoll_ctl是註冊要監聽的事件型別;
  • epoll_wait則是等待事件的產生。

epoll把原來select呼叫分成了3個部分:

1)呼叫epoll_create()建立一個epoll物件(在epoll檔案系統中為這個控制代碼物件分配資源)

2)呼叫epoll_ctl向epoll物件中新增這100萬個連線的套接字

3)呼叫epoll_wait收集發生的事件的連線

對於第一個缺點,fd數目有限:   epoll沒有這個限制,它所支援的FD上限是最大可以開啟檔案的數目,這個數字一般遠大於2048,舉個例子,在1GB記憶體的機器上大約是10萬左右,具體數目可以cat /proc/sys/fs/file-max檢視,一般來說這個數目和系統記憶體關係很大。    對於第二個缺點,重複把fd從使用者態拷貝到記憶體態: epoll的解決方案在epoll_ctl函式中。每次註冊新的事件到epoll控制代碼中時(在epoll_ctl中指定EPOLL_CTL_ADD),會把所有的fd拷貝進核心,而不是在epoll_wait的時候重複拷貝。epoll保證了每個fd在整個過程中只會拷貝一次。

對於第三個缺點,輪詢方式遍歷所有的fd:   epoll的解決方案不像select那樣每次都把current輪流加入fd對應的裝置等待佇列中,而只在epoll_ctl時把current掛一遍(這一遍必不可少)併為每個fd指定一個回撥函式,當裝置就緒,喚醒等待佇列上的等待者時,就會呼叫這個回撥函式,而這個回撥函式會把就緒的fd加入一個就緒連結串列)。epoll_wait的工作實際上就是在這個就緒連結串列中檢視有沒有就緒的fd(利用schedule_timeout()實現睡一會,判斷一會的效果,和select實現中的第7步是類似的)。