為什麼epoll比select更高效?
本文章將解決一下幾個問題,也是面試常問的問題
1.select和epoll有什麼不同?
2.為什麼epoll比select高效?
3.epoll永遠比select高效嗎?
1.select和epoll有什麼不同?
<1>select可以監聽檔案描述符是有限的,由FD_SETSIZE設定,預設是1024,可以通過修改這個巨集來增加可監聽檔案描述符的個數,但資料同時指出這樣修改將導致不可預期的效果。
epoll可監聽的檔案描述符的個數為程序可開啟的檔案的個數。
<2>select中,當有事件就緒時,核心修改引數以通知使用者,使用者需要遍歷所有的fd判斷是哪個fd就緒,應用程式索引就緒檔案描述符的時間複雜度是O(n)
epoll中註冊了回撥函式,當有就緒事件發生的時候,裝置驅動程式呼叫回撥函式,將就緒的fd新增到rdllist中,呼叫epoll_wait時,將rdllist上就緒的fd傳送給使用者,應用程式索引就緒檔案描述符的時間複雜度是O(1),IO效率與fd的數目無關。
<3>epoll支援ET模式,當核心將該事件通知給使用者後,使用者必須立即處理,這樣就減少了可讀、可寫、異常事件被觸發的次數。
select只能工作在相對較低效的LT模式。
2.為什麼epoll比select高效?
在select中,使用者通過fd_set_bits將感興趣的事件通知核心,核心要將使用者感興趣的事件拷貝到核心空間,併為每個fd分配一個poll_table_page結構體,用來監聽該fd上是否有就緒事件。如果有就緒事件,核心修改使用者傳進來的fd_set_bits告知使用者事件有就緒事件發生
在epoll中,在呼叫epoll_ctl時,已經將使用者感興趣的事件傳給了核心,核心會維持一個核心事件表,記錄使用者感興趣的事件,就緒事件發生時,驅動裝置呼叫回撥函式將就緒的fd掛到rdllist上。使用者呼叫epoll_wait時,將rdllist上就緒的檔案描述符傳送給使用者。此時傳送給使用者的都是就緒的fd。
3.不論哪種情況,epoll永遠比select高效嗎?
不一定!
epoll適用於連線較多,活動數量較少的情況。
(1)epoll為了實現返回就緒的檔案描述符,維護了一個紅黑樹和好多個等待佇列,核心開銷很大。如果此時監聽了很少的檔案描述符,底層的開銷會得不償失;
(2)epoll中註冊了回撥函式,當有時間發生時,伺服器裝置驅動呼叫回撥函式將就緒的fd掛在rdllist上,如果有很多的活動,同一時間需要呼叫的回撥函式數量太多,伺服器壓力太大。
select適用於連線較少的情況。
當select上監聽的fd數量較少,核心通知使用者現在有就緒事件發生,應用程式判斷當前是哪個fd就緒所消耗的時間複雜度就會大大減小。
希望我的解釋對你有幫助,如有錯誤,請指正!