UNIX的網絡I/O模型:linux
概念:
1)linux內核對一個文件的讀寫操做會調用內核提供的系統命令,返回一個文件描述符(file discriptor,簡稱fd)。
描述符就是一個數字,它指向內核中的一個結構體,這個結構體包含了文件路徑等信息。 eg:對socket的讀寫會返回一個描述符 socketfd
2)一次⽹絡I/O的讀操做會包含下面這兩個階段:1)等待數據準備就緒 2)數據從內核複製到用戶空間(即用戶進程)。緩存
1)阻塞I/O模型:blocking I/O
概念:用戶進程從阻塞的socket中讀取數據時,只有當數據包到達該socket的接收緩存區且數據被複制到進程空間的緩存區中 或 發生錯誤時 才返回,在此期間進程會一直阻塞等待。服務器
說明:默認狀況下,全部的文件操做都是阻塞的。
缺點:客戶端的併發訪問量比較高時,服務端須要建立大量的線程來響應請求,當線程的數量膨脹後,系統的性能會急劇降低甚至宕機。網絡
僞異步I/O模型:
概念:爲了解決阻塞I/O模型中須要爲每個請求都建立一個線程的問題,服務端可使用線程池來實現一個僞異步I/O模型。
僞異步I/O模型可能致使的級聯故障:某臺服務器故障致使響應緩慢 -> 線程讀取故障服務節點的響應 -> 全部線程被故障節點阻塞,後續IO消息都在隊列中 -> 隊列積滿 -> 新的客戶端請求被拒絕,服務器無響應併發
2)非阻塞I/O模型:nonblocking I/O
概念:用戶進程從非阻塞的socket中讀取數據時,若該套接字的接收緩存區中沒有數據,則內核會直接返回一個錯誤。異步
說明:通常當socket設爲非阻塞狀態時,用戶進程會輪詢內核(eg:循環調用recvfrom函數),直到內核有數據返回爲止,所以會致使大量cpu資源被佔用。socket
3)I/O複用模型:I/O multiplexing
概念:將多個待監聽的fd註冊到多路複用器(selector)中,註冊的時候須要指定該fd上待監聽的事件,selector會一直監聽註冊的fd,當fd上有事件發生時,selector會作出相應的處理。函數
說明:
與阻塞I/O模型相比,I/O複用模型是阻塞在select調用(或poll調用、或epoll調用)上,而不是阻塞在真正的I/O操做上。注意:阻塞是針對發起方而言的。
獲取fd的狀態:內核把fd的信息通知給用戶空間。
水平觸發:若就緒的fd未被用戶進程處理,則該fd在下一次查詢時依舊會返回。
邊緣觸發:不管就緒的fd是否被用戶進程處理,該fd在下一次查詢時將再也不返回。性能
優勢:
客戶端發起的鏈接操做是異步的,故單線程能夠同時處理多個客戶端的IO請求。系統不須要爲每一個客戶端請求都建立一個線程,這樣大大下降了系統的開銷,
缺點:操作系統
select調用:
概念:多路複用器(selector)由select函數實現。
監聽機制:
輪詢註冊的fd,並根據fd的狀態作相應的處理:
讀就緒狀態 -> 讀數據 並 刪除該讀就緒事件
寫就緒狀態 -> 寫數據 並 刪除該寫就緒事件
接收(accept)就緒狀態 -> 註冊新的讀就緒事件 並 刪除該接收就緒事件
...
獲取fd的狀態:內核把全部監聽的fd的信息總體複製到用戶空間。
觸發方式:水平觸發。
優勢:與非阻塞式I/O模式相比,select調用不須要客戶端不斷地發出請求。
缺點:
單個進程能夠打開的fd數量有限,默認1024個,若是要修改這個默認值,須要從新編譯內核。
每次select調用都會線性地掃描全部監聽的fd(即:不管fd是否就緒,select都會去檢查它的狀態),當監聽的fd數量比較多時,I/O效率呈線性降低。
poll調用:
概念:多路複用器(selector)由poll函數實現。
監聽機制:同select調用。
觸發方式:水平觸發。
優勢:
單個進程能夠打開的fd數量不受限制。
缺點:
線性地掃描全部監聽的fd,當監聽的fd數量比較多時,I/O效率呈線性降低。
epoll調用:
概念:selector由一系列epoll_函數實現。
監聽機制:
當fd就緒時,fd會當即回調rollback函數。而那些沒有就緒的fd則不會回調rollback函數。
獲取fd的狀態:使用內存映射,不須要把fd的信息從內核複製到用戶空間。
觸發方式:默認是水平觸發,支持邊緣觸發。
優勢:
單個進程能夠打開的fd數量不受限制。(僅受限於操做系統的最大文件句柄數,1g內存的最大文件句柄數爲10w左右)
因爲epoll採用的是回調函數的方式,而不是線性掃描的方式,故I/O效率不會隨着fd數量的增長而線性降低。
使用內存映射,避免了內存複製的開銷,加速了內核與用戶空間的消息傳遞。
缺點:
在鏈接數少而且鏈接都十分活躍的狀況下,epoll的性能可能比select和poll的性能差,畢竟epoll的通知機制須要不少函數回調。
4)信號驅動式I/O模型:SIGIO
開啓套接字信號驅動IO功能,並經過sigaction系統調用,執行一個信號處理函數,當數據報準備好時,內核就爲該進程產生一個SIGIO信號,用戶進程收到這個信號後,就能夠開始進行I/O操做了。
該系統調用會當即返回,在等待數據報到達期間,用戶進程不會被阻塞。
說明:信號驅動式I/O模型使用的場景比較少。
5)異步I/O模型:POSIX定義的異步IO函數
調用異步IO函數,讓內核在整個I/O操做(包括將數據從內核複製到用戶本身的緩衝區)完成後通知用戶進程。
該系統調用會當即返回,在等待I/O操做期間,用戶進程不被阻塞。
說明:同步/異步是針對執行方而言的。