5種網絡通信設計模型(也稱IO模型)


1、基本概念

同步:同步函數一般指調用函數后,等到函數功能實現再返回,期間一直霸占的CPU,等待期間同一個線程無法執行其他函數

異步:異步函數指調用函數后,不管函數功能是否實現,立馬返回;通過回調函數等告知函數功能完成

阻塞:調用某些函數阻塞是因為函數功能沒有實現,主動放棄CPU,讓其他線程的得以執行;當功能實現后,函數返回

非阻塞:調用某些函數不會進入阻塞,無論實現與否,都會返回結果

 

2、5種 IO 模型

阻塞模型

應用程序調用一個IO函數,導致應用程序阻塞,等待數據准備好。 如果數據沒有准備好,一直等待

特點:

  當希望能夠立即發送和接收數據,且處理的套接字數量比較少的情況下,使用阻塞模式來開發網絡程序比較合適。

  阻塞模式套接字的不足表現為,在大量建立好的套接字線程之間進行通信時比較困難。當使用“生產者-消費者”模型開發網絡程序時,為每個套接字都分別分配一個讀線程、一個處理數據線程和一個用於同步的事件,那么這樣無疑加大系統的開銷。其最大的缺點是當希望同時處理大量套接字時,將無從下手,其擴展性很差

 

非阻塞模型

程序框架如下:

while true {
    for i in stream[]
    {
        if i has data
        read until unavailable
    }
}

 

特點:

  不像阻塞模型需要為每個socket創建一個線程,非阻塞只需要一個線程,但是會一直占用CPU

 

復用模型

      I/O復用模型會用到select、poll、epoll函數,這幾個函數也會使進程阻塞(根據實參規定最長進入阻塞時間,是否進入阻塞),但是和阻塞I/O所不同的的,這些函數可以同時阻塞多個I/O操作。而且可以同時對多個讀操作、多個寫操作的I/O函數進行檢測,直到有數據可讀或可寫時,才真正調用I/O操作函數。

epoll跟select都能提供多路I/O復用的解決方案。在現在的Linux內核里有都能夠支持,其中epoll是Linux所特有,而select則應該是POSIX所規定,一般操作系統均有實現

 

select:

程序框架如下:

while true {
    select(streams[])
    for i in streams[] {
        if i has data
            read until unavailable
    }
}

 

select本質上是通過設置或者檢查存放fd標志位的數據結構來進行下一步處理。這樣所帶來的缺點是:

1、 單個進程可監視的fd數量被限制,即能監聽端口的大小有限。

      一般來說這個數目和系統內存關系很大,具體數目可以cat /proc/sys/fs/file-max察看。32位機默認是1024個。64位機默認是2048.

2、 對socket進行掃描時是線性掃描,即采用輪詢的方法,效率較低:

       因為select()只會告訴我們有套接字可讀或可寫,沒有指明是哪個套接字的哪個事件發生,所以需要遍歷每個套接字,時間復雜度是O(n)。如果能給套接字注冊某個回調函數,當他們活躍時,自動完成相關操作,那就避免了輪詢,這正是epoll與kqueue做的。

3、需要維護一個用來存放大量fd的數據結構,這樣會使得用戶空間和內核空間在傳遞該結構時復制開銷大

poll:(有待重新組織語言)

poll本質上和select沒有區別,它將用戶傳入的數組拷貝到內核空間,然后查詢每個fd對應的設備狀態,如果設備就緒則在設備等待隊列中加入一項並繼續遍歷,如果遍歷完所有fd后沒有發現就緒設備,則掛起當前進程,直到設備就緒或者主動超時,被喚醒后它又要再次遍歷fd。這個過程經歷了多次無謂的遍歷。

它沒有最大連接數的限制,原因是它是基於鏈表來存儲的,但是同樣有一個缺點:

1、大量的fd的數組被整體復制於用戶態和內核地址空間之間,而不管這樣的復制是不是有意義。

2、poll還有一個特點是“水平觸發”,如果報告了fd后,沒有被處理,那么下次poll時會再次報告該fd。

epoll:

程序框架如下;

while true {
    active_stream[] = epoll_wait(epollfd)
    for i in active_stream[] {
        read or write till unavailable
    }
}

 

epoll支持水平觸發和邊緣觸發,最大的特點在於邊緣觸發,它只告訴進程哪些fd剛剛變為就需態,並且只會通知一次。還有一個特點是,epoll使用“事件”的就緒通知方式,通過epoll_ctl注冊fd,一旦該fd就緒,內核就會采用類似callback的回調機制來激活該fd,epoll_wait便可以收到通知

epoll的優點:

1、相比於select,沒有最大並發連接的限制,能打開的FD的上限遠大於1024(1G的內存上能監聽約10萬個端口);
2、效率提升,不是無差別輪詢的方式,不會隨着FD數目的增加效率下降。只有活躍可用的FD才會調用callback函數,時間復雜度為O(k),k為產生I/O事件的流的個數
      即Epoll最大的優點就在於它只管你“活躍”的連接,而跟連接總數無關,因此在實際的網絡環境中,Epoll的效率就會遠遠高於select和poll。
3、 內存拷貝,利用mmap()文件映射內存加速與內核空間的消息傳遞;即epoll使用mmap減少復制開銷。

select、poll、epoll 區別總結:

 

1、一個進程所能打開的最大連接數

select

單個進程所能打開的最大連接數由FD_SETSIZE宏定義,其大小是32個整數的大小(在32位的機器上,大小就是32*32,同理64位機器上FD_SETSIZE為32*64),當然我們可以對進行修改,然后重新編譯內核,但是性能可能會受到影響,這需要進一步的測試。

poll

poll本質上和select沒有區別,但是它沒有最大連接數的限制,原因是它是基於鏈表來存儲的

epoll

雖然連接數有上限,但是很大,1G內存的機器上可以打開10萬左右的連接,2G內存的機器可以打開20萬左右的連接

2、FD劇增后帶來的IO效率問題

select

因為每次調用時都會對連接進行線性遍歷,所以隨着FD的增加會造成遍歷速度慢的“線性下降性能問題”。

poll

同上

epoll

因為epoll內核中實現是根據每個fd上的callback函數來實現的,只有活躍的socket才會主動調用callback,所以在活躍socket較少的情況下,使用epoll沒有前面兩者的線性下降的性能問題,但是所有socket都很活躍的情況下,可能會有性能問題。

3、 消息傳遞方式

select

內核需要將消息傳遞到用戶空間,都需要內核拷貝動作

poll

同上

epoll

epoll通過內核和用戶空間共享一塊內存來實現的。

總結:

綜上,在選擇select,poll,epoll時要根據具體的使用場合以及這三種方式的自身特點。

1、表面上看epoll的性能最好,但是在連接數少並且連接都十分活躍的情況下,select和poll的性能可能比epoll好,畢竟epoll的通知機制需要很多函數回調

2、select低效是因為每次它都需要輪詢。但低效也是相對的,視情況而定,也可通過良好的設計改善

3、epoll 能顯著提高程序在大量並發連接中只有少量活躍的情況下的系統CPU利用率

 

信號驅動模型

    首先我們允許套接口進行信號驅動I/O,並安裝一個信號處理函數,進程繼續運行並不阻塞。當數據准備好時,進程會收到一個SIGIO信號,可以在信號處理函數中調用I/O操作函數處理數據。

 

異步模型

  簡介:數據拷貝的時候進程無需阻塞。

     當一個異步過程調用發出后,調用者不能立刻得到結果。實際處理這個調用的部件在完成后,通過狀態、通知和回調來通知調用者的輸入輸出操作

 

比較

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM