先說個故事html
鬼子進村程序員
處理大量的鏈接的讀寫,select 是夠低效的。由於 kernel 每次都要對 select 傳入的一組 socket 號作輪詢,這叫鬼子進村策略。一遍遍的詢問「鬼子進村了嗎?」,「鬼子進村了嗎?」... 大量的 cpu 時間都耗了進去。(更過度的是在 windows 上,還有個萬惡的 64 限制。)使用 kqueue 這些,變成了派一些我的去站崗,鬼子來了就能夠拿到通知,效率天然高了許多。web
緩存I/O又稱爲標準I/O,大多數文件系統的默認I/O操做都是緩存I/O。在Linux的緩存I/O機制中,操做系統會將I/O的數據緩存在文件系統的頁緩存中,即數據會先被拷貝到操做系統內核的緩衝區中,而後纔會從操做系統內核的緩衝區拷貝到應用程序的地址空間。編程
阻塞式I/O模型:默認狀況下,全部套接字都是阻塞的。recvfrom等待數據準備好,從內核向進程複製數據。windows
非阻塞式I/O: 進程把一個套接字設置成非阻塞是在通知內核,當所請求的I/O操做非得把本進程投入睡眠才能完成時,不要把進程投入睡眠,而是返回一個錯誤,recvfrom老是當即返回。數組
I/O多路複用:雖然I/O多路複用的函數也是阻塞的,可是其與以上兩種仍是有不一樣的,I/O多路複用是阻塞在select,epoll這樣的系統調用之上,而沒有阻塞在真正的I/O系統調用如recvfrom之上。其本質是經過一種機制(系統內核緩衝I/O數據),讓單個進程能夠監視多個文件描述符,一旦某個描述符就緒(通常是讀就緒或寫就緒),可以通知程序進行相應的讀寫操做。select、poll 和 epoll 都是 Linux API 提供的 IO 複用方式。緩存
信號驅動式I/O:用的不多,就不作講解了。服務器
異步I/O:這類函數的工做機制是告知內核啓動某個操做,並讓內核在整個操做(包括將數據從內核拷貝到用戶空間)完成後通知咱們。網絡
recvfrom函數(經socket接收數據)。數據結構
再看POSIX對這兩個術語的定義:
同步I/O操做:致使請求進程阻塞,直到I/O操做完成;
異步I/O操做:不致使請求進程阻塞。
select()的機制中提供一種fd_set
的數據結構,其實是一個long類型的數組,每個數組元素都能與一打開的文件句柄(不論是Socket句柄,仍是其餘文件或命名管道或設備句柄)創建聯繫,創建聯繫的工做由程序員完成,當調用select()時,由內核根據IO狀態修改fd_set的內容,由此來通知執行了select()的進程哪一Socket或文件可讀。
從流程上來看,使用select函數進行IO請求和同步阻塞模型沒有太大的區別,甚至還多了添加監視socket,以及調用select函數的額外操做,效率更差。可是,使用select之後最大的優點是用戶能夠在一個線程內同時處理多個socket的IO請求。用戶能夠註冊多個socket,而後不斷地調用select讀取被激活的socket,便可達到在同一個線程內同時處理多個IO請求的目的。而在同步阻塞模型中,必須經過多線程的方式才能達到這個目的。
epoll除了提供select/poll那種IO事件的水平觸發(Level Triggered)外,還提供了邊緣觸發(Edge Triggered),這就使得用戶空間程序有可能緩存IO狀態,減小epoll_wait/epoll_pwait的調用,提升應用程序效率。
LT和ET本來應該是用於脈衝信號的,可能用它來解釋更加形象。Level和Edge指的就是觸發點,Level爲只要處於水平,那麼就一直觸發,而Edge則爲上升沿和降低沿的時候觸發。好比:0->1 就是Edge,1->1 就是Level。
ET模式很大程度上減小了epoll事件的觸發次數,所以效率比LT模式下高。
一張圖總結一下select,poll,epoll的區別:
select | poll | epoll | |
---|---|---|---|
操做方式 | 遍歷 | 遍歷 | 回調 |
底層實現 | 數組 | 鏈表 | 哈希表 |
IO效率 | 每次調用都進行線性遍歷,時間複雜度爲O(n) | 每次調用都進行線性遍歷,時間複雜度爲O(n) | 事件通知方式,每當fd就緒,系統註冊的回調函數就會被調用,將就緒fd放到readyList裏面,時間複雜度O(1) |
最大鏈接數 | 1024(x86)或2048(x64) | 無上限 | 無上限 |
fd拷貝 | 每次調用select,都須要把fd集合從用戶態拷貝到內核態 | 每次調用poll,都須要把fd集合從用戶態拷貝到內核態 | 調用epoll_ctl時拷貝進內核並保存,以後每次epoll_wait不拷貝 |
既然select,poll,epoll都是I/O多路複用的具體的實現,之因此如今同時存在,其實他們也是不一樣歷史時期的產物
參考:
https://blog.csdn.net/dapengbusi/article/details/50690690