Epoll

一個服務端同時能夠接受多個客戶端的鏈接,每一個鏈接都是一個SocketChannel(Channel中的一種),這些Channel共同鏈接到Selector上(服務端僅須要一個選擇器),channel會註冊感興趣的事件到Selector中,當調用Select方法返回後,會遍歷全部的套接字描述符(服務端進程爲每個socket鏈接建立一個描述符),一旦某個描述符就緒,就通知應用程序進行相應的讀寫操做。Selector下面會接一個Buffer緩衝區,全部的數據都會先到達內核的緩衝區中,而後再read(匯聚/發散)到用戶態應用程序的內存緩衝區中。數組

 

在select中,描述符存放在一個數組中,當調用select()方法的時候,進程會阻塞,直到數組中有某些描述符處於就緒狀態,此時select()方法返回,而後遍歷該數組,處理這些描述符。select的缺點就是進程能夠監視的描述符只有1024個,若是鏈接數再多的話就不行了。併發

poll的實現和select很是類似,只是描述fd集合的方式不一樣。select和poll都須要在返回後,經過遍歷文件描述符來獲取已經就緒的socket。事實上,同時鏈接的大量客戶端在一時刻可能只有不多的處於就緒狀態,所以隨着監視的描述符數量的增加,其效率也會線性降低。異步

 

epoll提供了三個函數,epoll_create,epoll_ctl和epoll_wait,epoll_create是建立一個epoll句柄,epoll_ctl是註冊要監聽的事件類型;epoll_wait則是等待事件的產生。epoll的優勢是不受描述符數量的限制,可以支持很是高的併發請求。epoll方式在每一個描述符上定義了一個回調函數,只有當就緒的描述符纔會執行回調函數,加入就緒隊列中等待應用程序去處理,而不須要每次都遍歷fd容器。若是沒有大量的idle -connection或者dead-connection,epoll的效率並不會比select/poll高不少,可是當遇到大量的idle-connection,就會發現epoll的效率大大高於select/poll。socket

epoll高效的原理是利用了就緒隊列和紅黑樹:將註冊的事件插入到紅黑樹中,這樣每次操做系統找就緒的事件就比較快,找到後就鏈到就緒隊列的鏈表中,這樣每次epoll_wait 就只處理就緒隊列的事件,比起poll和 select每次所有遍歷一遍高效的多。函數

 

select,poll,epoll都是IO多路複用的機制,該機制能夠監視多個描述符,一旦某個描述符就緒,可以通知程序進行相應的讀寫操做。select,poll,epoll本質上都是同步I/O,由於他們都須要在讀寫事件就緒後本身負責進行讀寫,也就是說這個讀寫過程是阻塞的,而異步I/O則無需本身負責進行讀寫,異步I/O的實現會負責把數據從內核拷貝到用戶空間。操作系統

 

傳統IO中,IO線程和event_process(事件處理)線程是在一塊兒的,也就是來多少socket鏈接,就要開多少線程去讀寫IO並處理該請求。若是有不少的長鏈接,可是大多socket鏈接處於idle-connection或者dead-connection狀態,那麼這些線程都須要持續保留,浪費系統資源。線程

IO多路複用,將IO線程和事件處理線程區分開,事件處理線程放在一個線程池中,而IO線程只有一個,即Selector線程.只有就緒的描述符纔會被線程池(事件處理線程)處理掉,其餘鏈接上可是未就緒的描述符,不用專門去開線程維護。blog

相關文章
相關標籤/搜索