linux多路IO複用中的select和epoll,多路io複用epoll

來源:互聯網
上載者:User

linux多路IO複用中的select和epoll,多路io複用epoll

select,epoll都是IO多工機制。I/O多工就通過一種機制,可以監視多個描述符,一旦某個描述符就緒(一般是讀就緒或者寫就緒),能夠通知程式進行相應的讀寫操作。但select,poll,epoll本質上都是同步I/O,因為他們都需要在讀寫事件就緒後自己負責進行讀寫,也就是說這個讀寫過程是阻塞的,而非同步I/O則無需自己負責進行讀寫,非同步I/O的實現會負責把資料從核心拷貝到使用者空間。

select調用的過程:

(1)從使用者空間拷貝fd_set到核心空間

(2)註冊回呼函數__pollwait

(3)遍曆所有fd,調用其對應的poll方法(對於socket,這個poll方法是sock_poll,sock_poll根據情況會調用到tcp_poll,udp_poll或者datagram_poll)

(4)以tcp_poll為例,其核心實現就是__pollwait,也就是上面註冊的回呼函數。

(5)__pollwait的主要工作就是把current(當前進程)掛到裝置的等待隊列中,不同的裝置有不同的等待隊列,對於tcp_poll來說,其等待隊列是sk->sk_sleep(注意把進程掛到等待隊列中並不代表進程已經睡眠了)。在裝置收到一條訊息(網路裝置)或填寫完檔案資料(磁碟裝置)後,會喚醒裝置等待隊列上睡眠的進程,這時current便被喚醒了。

(6)poll方法返回時會返回一個描述讀寫操作是否就緒的mask掩碼,根據這個mask掩碼給fd_set賦值。

(7)如果遍曆完所有的fd,還沒有返回一個可讀寫的mask掩碼,則會調用schedule_timeout是調用select的進程(也就是current)進入睡眠。當裝置驅動發生自身資源可讀寫後,會喚醒其等待隊列上睡眠的進程。如果超過一定的逾時時間(schedule_timeout指定),還是沒人喚醒,則調用select的進程會重新被喚醒獲得CPU,進而重新遍曆fd,判斷有沒有就緒的fd。

(8)把fd_set從核心空間拷貝到使用者空間。

select的幾大缺點:

(1)每次調用select,都需要把fd集合從使用者態拷貝到核心態,這個開銷在fd很多時會很大

(2)同時每次調用select都需要在核心遍曆傳遞進來的所有fd,這個開銷在fd很多時也很大

(3)select支援的檔案描述符數量太小了,預設是1024

(4)select需要對每個fd進行輪詢,即使該fd尚未就緒

 那麼epoll有何區別呢?我們先看一下epoll和select和poll的調用介面上的不同,select和poll都只提供了一個函數——select或者poll函數。而epoll提供了三個函數,epoll_create,epoll_ctl和epoll_wait,epoll_create是建立一個epoll控制代碼;epoll_ctl是註冊要監聽的事件類型;epoll_wait則是等待事件的產生。

  對於第一個缺點,epoll的解決方案在epoll_ctl函數中。每次註冊新的事件到epoll控制代碼中時(在epoll_ctl中指定EPOLL_CTL_ADD),會把所有的fd拷貝進核心,而不是在epoll_wait的時候重複拷貝。epoll保證了每個fd在整個過程中只會拷貝一次。

  對於第二個缺點,epoll的解決方案不像select或poll一樣每次都把current輪流加入fd對應的裝置等待隊列中,而只在epoll_ctl時把current掛一遍(這一遍必不可少)並為每個fd指定一個回呼函數,當裝置就緒,喚醒等待隊列上的等待者時,就會調用這個回呼函數,而這個回呼函數會把就緒的fd加入一個就緒鏈表)。epoll_wait的工作實際上就是在這個就緒鏈表中查看有沒有就緒的fd(利用schedule_timeout()實現睡一會,判斷一會的效果,和select實現中的第7步是類似的)。

  對於第三個缺點,epoll沒有這個限制,它所支援的FD上限是最大可以開啟檔案的數目,這個數字一般遠大於2048,舉個例子,在1GB記憶體的機器上大約是10萬左右,具體數目可以cat /proc/sys/fs/file-max察看,一般來說這個數目和系統記憶體關係很大。

總結:

(1)select,poll實現需要自己不斷輪詢所有fd集合,直到裝置就緒,期間可能要睡眠和喚醒多次交替。而epoll其實也需要調用epoll_wait不斷輪詢就緒鏈表,期間也可能多次睡眠和喚醒交替,但是它是裝置就緒時,調用回呼函數,把就緒fd放入就緒鏈表中,並喚醒在epoll_wait中進入睡眠的進程。雖然都要睡眠和交替,但是select和poll在“醒著”的時候要遍曆整個fd集合,而epoll在“醒著”的時候只要判斷一下就緒鏈表是否為空白就行了,這節省了大量的CPU時間。這就是回調機制帶來的效能提升。

(2)select,poll每次調用都要把fd集合從使用者態往核心態拷貝一次,並且要把current往裝置等待隊列中掛一次,而epoll只要一次拷貝,而且把current往等待隊列上掛也只掛一次(在epoll_wait的開始,注意這裡的等待隊列並不是裝置等待隊列,只是一個epoll內部定義的等待隊列)。這也能節省不少的開銷。

著作權聲明:本文為博主原創文章,未經博主允許不得轉載。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.