首先,應用程序發起 io 系統呼叫後,應用程序被阻塞,轉到核心空間處理。
之後,核心開始等待資料,等待到資料之後,再將核心中的資料拷貝到使用者記憶體中,整個 io 處理完畢後返回程序。
最後應用的程序解除阻塞狀態,執行業務邏輯。
系統核心處理 io 操作分為兩個階段——等待資料和拷貝資料。而在這兩個階段中,應用程序中 io 操作的執行緒會一直都處於阻塞狀態字面上理解
通過字面上的理解,多路就是指多個通道,也就是多個網路連線的 io,而復用就是指多個通道復用在乙個復用器上。
真實含義
多個網路連線的 io 可以註冊到乙個復用器(select)上,當使用者程序呼叫了 select,那麼整個程序會被阻塞。同時,核心會「監視」所有 select 負責的 socket,當任何乙個 socket 中的資料準備好了,select 就會返回。這個時候使用者程序再呼叫 read 操作,將資料從核心中拷貝到使用者程序。
優勢使用者可以在乙個執行緒內同時處理多個 socket 的 io 請求。使用者可以註冊多個 socket,然後不斷地呼叫 select 讀取被啟用的 socket,即可達到在同乙個執行緒內同時處理多個 io 請求的目的。在系統核心的支援上,現在大多數系統核心都會支援阻塞 io、非阻塞 io 和 io 多路復用,但像訊號驅動 io、非同步 io,只有高版本的 linux 系統核心才會支援。
在程式語言上,在高效能的網路程式設計框架的編寫上,大多數都是基於 reactor 模式,其中最為典型的便是 j**a 的 netty 框架,而 reactor 模式是基於 io 多路復用的。當然,在非高併發場景下,同步阻塞 io 是最為常見的阻塞io
阻塞 io 每處理乙個 socket 的 io 請求都會阻塞程序(執行緒),但使用難度較低。在併發量較低、業務邏輯只需要同步進行 io 操作的場景下,阻塞 io 已經滿足了需求,並且不需要發起 select 呼叫,開銷上還要比 io 多路復用低。
io多路復用
適用於高併發的場景,可以用較少的程序(執行緒)處理較多的 socket 的 io 請求,但使用難度比較高。當然高階的程式語言支援得還是比較好的rpc呼叫在大多數情況下是乙個高併發的場景,考慮到系統核心的支援、程式語言的支援以及 io 模型本身的特點,在 rpc 框架的實現中,在網路通訊的處理上,我們會選擇 io 多路復用的方式。
開發語言的網路通訊框架的選型上,我們最優的選擇是基於 reactor 模式實現的框架,
在 linux 環境下,也要開啟 epoll 來提公升系統效能(windows 環境下是無法開啟 epoll 的,因為系統核心不支援)。阻塞io時,系統核心處理io操作分為等待資料和拷貝資料兩個階段
等待資料,就是系統核心在等待網絡卡接收到資料後,把資料寫到核心中;
拷貝資料,就是系統核心在獲取到資料後,將資料拷貝到使用者程序的空間中
應用程序的每一次寫操作,都會把資料寫到使用者空間的緩衝區中,再由 cpu 將資料拷貝到系統核心的緩衝區中,之後再由 dma 將這份資料拷貝到網絡卡中,最後由網絡卡傳送出去。可以看到,一次寫運算元據要拷貝兩次才能通過網絡卡傳送出去,而使用者程序的讀操作則是將整個流程反過來,資料同樣會拷貝兩次才能讓應用程式讀取到資料。
應用程序的一次完整的讀寫操作,都需要在使用者空間與核心空間中來回拷貝,並且每一次拷貝,都需要 cpu 進行一次上下文切換(由使用者程序切換到系統核心,或由系統核心切換到使用者程序),浪費cpu和效能所謂的零拷貝,就是取消使用者空間與核心空間之間的資料拷貝操作,應用程序每一次的讀寫操作,都可以通過一種方式,讓應用程序向使用者空間寫入或者讀取資料,就如同直接向核心空間寫入或者讀取資料一樣,再通過 dma 將核心中的資料拷貝到網絡卡,或將網絡卡中的資料 copy 到核心。
1、mmap+write 方式
核心原理就是通過虛擬記憶體來解決2、sendfile方
效能優化 優化RPC網路通訊
上一講中,我提到了微服務框架,其中 springcloud 和 dubbo 的使用最為廣泛,行業內也一直存在著對兩者的比較,很多技術人會為這兩個框架哪個更好而爭辯。我記得我們部門在搭建微服務框架時,也在技術選型上糾結良久,還曾一度有過激烈的討論。當前 springcloud 炙手可熱,具備完整的微服...
網路通訊框架使用 topiot
pom.xml com.top topiot 1.0.0 com.alibaba fastjson 1.1.34 log4j log4j 1.2.17 org.apache.mina mina core 2.0.7 springmvc.xml 10375 false true 說明 1 id 服務唯...
C 網路通訊
c 網路通訊 一 伺服器端程式 10.17 1.建立伺服器端socket 1 使用socket類 建立伺服器socket物件 socket objs new socket 引數 使用ipendpoint類設定伺服器ip位址和埠號 或使用dns類 ipaddress serip ipaddress.p...