原文:i/o多路復用和socket
由於io操作涉及到系統呼叫,涉及到使用者空間和核心空間的切換,所以理解系統的io模型,對於需要進入到系統呼叫層面進行程式設計來說是很重要的。
從程式編寫的角度來看,i/o就是呼叫乙個或多個系統函式,完成對輸入輸出裝置的操作。輸入輸出設定可以是顯示器、字元終端命令列、網路介面卡、磁碟等。作業系統在這些裝置與使用者程式之間完成乙個銜接,稱為驅動程式,驅動程式向下驅動硬體,向上提供抽象的函式呼叫入口。
一般來說i/o操作是需要時間的,因為這涉及到系統、硬體等計算器模組的互相配合,所以必然不像普通的函式呼叫那樣能夠按照既定的方式立即返回。從使用者**的角度,i/o操作的系統呼叫分為「阻塞」和「非阻塞」兩種。
那麼我們以網路io為例,看一下對於乙個伺服器,「阻塞」和「非阻塞」兩種模式,該如何設計。由於伺服器要同時服務多個客戶端,所以需要同時操作多個socket。
可以看到,如果使用阻塞的io方式,因為每個socket都會阻塞,為了同時服務多個客戶端,需要多個執行緒同時掛起;而如果採用非阻塞的呼叫方式,則需要在乙個執行緒中不斷輪訓每個客戶端是否有資料到來。
顯然純粹阻塞式的呼叫不可取,非阻塞式的呼叫看起來不錯,但是仍不夠好,因為輪詢實際也是通過某種系統呼叫完成的,相當於在使用者空間進行的,效率不高,如果能夠在核心空間進行這種類似輪詢,然後讓核心通知使用者空間哪個io就緒了,就更好了。於是引出接下來的概念:io多路復用
io多路復用是一種系統呼叫,核心能夠同時對多個io描述符進行就緒檢查。當所有被監聽的io都沒有就緒時,呼叫將阻塞;當至少有乙個io描述符就緒時,呼叫將返回,使用者**可通過檢查究竟是哪個io就緒來進一步處理業務。顯然,io多路復用是解決系統裡面存在n個io描述符的問題的,這裡必須明確io復用和io阻塞與否並不是乙個概念,io復用只檢測io是否就緒(讀就緒或者寫就緒等),具體的資料的輸入輸出還是需要依靠具體的io操作完成(阻塞操作或非阻塞操作)。最典型的io多路復用技術有select
、poll
、epoll
等。select
具有最大數量描述符限制,而epoll
則沒有,並且在機制上,epoll
也更為高效。select
的優勢僅僅是跨平台支援性,所有平台和較低版本的核心都支援select
模式,epoll
則不是。
在io相關的程式設計中,io復用起到的作用相當於乙個閥門,讓後續io操作更為精準高效。
綜上討論,我們在進行實際的socket程式設計的時候,無論是客戶端還是服務端,大致有幾種模式可以選擇:
阻塞式。純採用阻塞式,這種方式很少見,基本只會出現在demo中。多個描述符需要用多個程序或者執行緒來一一對應處理。
非阻塞式。純非阻塞式,對io的就緒與否需要在使用者空間通過輪詢來實現。
io多路復用+阻塞式。僅使用乙個執行緒就可以實現對多個描述符的狀態管理,但由於io輸入輸出呼叫本身是阻塞的,可能出現某個io輸入輸出過慢,影響其他描述符的效率,從而體現出整體效能不高。此種方式程式設計難度比較低。
io多路復用+非阻塞式。在多路復用的基礎上,io採用非阻塞式,可以大大降低單個描述符的io速度對其他io的影響,不過此種方式程式設計難度較高,主要表現在需要考慮一些慢速讀寫時的邊界情況,比如讀黏包、寫緩衝不夠等。
下面以select為例,整理 在select下,socket的阻塞和非阻塞的一些問題。這些細節在編寫基於socket的網路程式時,尤其是底層資料收發時,是十分重要的。
socket讀就緒:
socket寫就緒:
補充:非阻的呼叫recv
、send
、accept
,分別地,如果收緩衝中無資料、傳送緩衝不夠空間發、沒有外來連線,將立即返回,此時全域性errno
將得到ewouldblock
或eagian
,表示「本應阻塞的呼叫,由於採用了非阻塞模式,而返回」。非阻的呼叫connect
將立即返回,此時全域性errno
將得到einprogress
,表示連線正在進行。
I O復用及程式設計模型
原文 i o多路復用和socket 由於io操作涉及到系統呼叫,涉及到使用者空間和核心空間的切換,所以理解系統的io模型,對於需要進入到系統呼叫層面進行程式設計來說是很重要的。從程式編寫的角度來看,i o就是呼叫乙個或多個系統函式,完成對輸入輸出裝置的操作。輸入輸出設定可以是顯示器 字元終端命令列 ...
I O復用和I O模型
由 unix網路程式設計卷1 總結而來。同時監視多個i o條件,在其中任意乙個就緒時通知程序,這樣的能力稱為i o復用。由select和poll函式支援,較新的還有posix中的pselect函式。linux中還有epoll i o復用應用場合 1 客戶同時處理多個描述符時,必須使用i o復用。2 ...
併發程式設計 網路IO模型 IO多路復用
網路io模型 一 網路io 輸入 recv recvfrom accept 阻塞io 輸出 send sendto sendall connect 會等待一段時間,但是卻是非阻塞io,因為是乙個主動的過程 二 網路io模型 跟socket有關 blocking io 阻塞io 平時用的 tcp ud...