【計算機網絡】IO模型

概述

  • socket 將網絡中的通信抽象成 I/O 操作, 可以對 socket 像文件一樣的打開, 讀寫和關閉。

  • I/O 模型一般指磁盤 I/O 和網絡 I/O

  • I/O 模型共有五種,分爲兩類

    • 同步
      • 阻塞式 I/O (blocking I/O)
      • 非阻塞式 I/O (non - blocking I/O)
      • I/O多路複用(multiplexing I/O)
      • 信號驅動式 I/O (signal - driven I/O)
    • 異步
      • 異步 I/O (asynchronous I/O)
  • 對 I/O 的一次訪問一般包括兩個階段

    • 等待數據準備好(等待數據到達或等待數據複製到系統內核緩衝區)
    • 將數據從內核緩衝區複製到應用進程緩衝區

同步阻塞 I/O

在JDK1.4之前,Java中主要是用的就是阻塞IO,叫做BIO


發起 IO 請求後進程被阻塞, 直到數據從內核緩衝區複製到應用進程緩衝區爲止。

同步非阻塞 I/O

JDK1.4後提供了 NIO, 即同步非阻塞 I/O


發起 IO 請求後, 系統內部會以非阻塞的形式來執行 I/O , 即如果底層數據沒有準備就緒, 那麼內核返回異常信息, 之後接着繼續不斷的執行系統調用來獲知 I/O 是否完成, 這種方式也稱輪詢(polling)

非阻塞只是指內部在不斷輪詢,不會被阻塞。同步是指在調用了NIO接口後, 還是需要一直同步等待,

I/O 多路複用

調用 select 或者 poll 等待多個socket, 能夠實現對多個 IO 端口的監聽, 其中任意一個socket準備好了, 就能返回可讀, 之後再調用recvform系統調用, 將數據由內核態拷貝到用戶進程, 這個過程是阻塞的。

信號驅動 I/O

應用進程使用sigaction系統調用, 內核立即返回, 應用進程可繼續執行, 內核等到數據到達時嚮應用程序發送SIGIO信號, 應用進程收到信號後調用recvfrom將數據從內核複製到應用進程中

異步 I/O

jdk1.7之後支持AIO, 即異步IO模型。


應用進程執行 aio_read 系統調用後會立即返回, 進程可繼續運行, 不會被阻塞, 內核在所有操作完成後會嚮應用進程發送信號。

五大 I/O 模型比較

  • 同步和異步: 主要區別在第二階段應用進程是否會阻塞, 在調用具體的JDK方法時, 同步不會立即返回, 而異步會直接返回繼續執行。
  • 同步的阻塞和同步的非阻塞: 指第一階段是否會阻塞, 而第二階段都會阻塞.

select poll 和 epoll

select poll 和 epoll都是 I/O 多路複用的具體實現,先出現的是select 之後是 poll 和 epoll。
I/O 多路複用監視多個描述符,當某個描述符準備就緒, 就通知程序進行相應的讀寫操作。

select

int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, struct timeval *timeout);
  • fd_set 由數組實現, 數組大小有限制, 無法監聽大量的描述符.
  • timeout 爲超時參數, 調用 select 會一直等待到有描述符事件或者時間超時

select 每次輪詢 fd 文件描述符檢查就緒時間

缺點

  • 每次調用都需要將fd拷貝到內核, 開銷大
  • 每次都需要遍歷fd
  • select 支持的文件描述符太小, 默認是1024.

poll

int poll(struct pollfd *fds, unsigned int nfds, int timeout);

poll 和 select 的功能基本相同, 只是描述fd集合的方式不同, poll使用pollfd結構, 從而解決了單獨線程能夠打開文件描述符的數量有限制的問題.

epoll

int epoll_create(int size);
int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event)int epoll_wait(int epfd, struct epoll_event * events, int maxevents, int timeout);

epoll 不需要通過輪詢來獲得世界完成的描述符,已註冊的描述符在內核中會被維護在一棵紅黑樹上,通過回調函數內核會將 I/O 準備好的描述符加入到一個鏈表中管理, epoll 不斷輪詢就緒鏈表, 避免了將描述符從進程緩衝區向內核緩存區的重複拷貝.

  • epoll的默認工作模式爲LT邊緣觸發: 已通知的事件如果未被處理則下次依然被通知
  • ET模式水平觸發: 已通知的事件必須被處理並且不再通知此事件

應用場景

  • select

select 的 timeout 精度爲1ns, 而 poll 和 epoll 爲 1ms, 因此 select 適合實時性高的場景

select 的可移植性更好, 幾乎被所有主流平臺支持.

  • poll

如果有大量描述符, 且對實時性要求不高的場景, 應該使用 poll 而不是 select

  • epoll

僅適用於 linux

有大量的描述符需要同時輪詢, 且連接最好是長連接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章