深入理解I/O模型:阻塞/非阻塞與同步/異步的概念辨析及實現差異
0.引言
隨著互聯網應用和高性能計算的發展,對于性能要求日益提升,而I/O作為影響性能的關鍵瓶頸之一,深入理解I/O模型對于提高應用的的性能非常重要,然而,阻塞/非阻塞與同步/異步作為I/O模型的核心概念,常常被混淆,本文將深入探討這些概念的本質以及其實現上的差異。
1. I/O操作流程
要理解不同的I/O模型需要先明確I/O操作的基本流程。一般來說,一次完整的I/O操作包含兩個關鍵的階段,這兩個階段的不同產生了不同的I/O模型。
1)數據準備階段:數據準備階段對于讀取來說是將外部設備數據(如磁盤、網絡等)加載到內核緩沖區(等待數據到來);對于寫入來說是等待內核緩沖區有足夠的空間接收用戶的數據(等待空間騰出來)。
2)數據拷貝階段:數據拷貝階段對于讀取操作來說就是將數據從內核緩沖區拷貝到用戶空間緩沖區;對于寫入來說就是將用戶空間緩沖區拷貝到內核緩沖區。
圖片
2.阻塞/非阻塞、同步/異步
2.1 阻塞/非阻塞
阻塞/非阻塞關注等待的狀態,是一直等待不能做其他事情還是可以立即返回通過輪詢/事件方式獲取結果。我們以網絡接收數據為例,如果socket沒有設置為非阻塞的,那么調用recv函數時就會一直等待直到數據到達或者連接關閉,而如果設置socket為非阻塞就可以動態輪詢去獲取狀態,但是由于輪詢有可能導致CPU資源浪費,所以一般配合多路復用技術一起使用。
總結一下,阻塞/非阻塞對于I/O來講就是其影響線程的等待狀態(是否可以做別的事情,線程是否還是運行狀態),而且這主要體現在數據準備階段。
圖片
2.2 同步/異步
同步和異步關注的是結果的通知方式,同步的需要自己等待結果返回,而異步的是有結果了通知你。我們還是以網絡接收數據為例,直接調用recv函數,不論是阻塞I/O還是非阻塞I/O,其都是程序自己獲取狀態后進行同步的數據拷貝(從內核->用戶空間);那與其對應的就是異步I/O,異步I/O中應用程序只需要向內核發起I/O請求,內核完成數據的讀寫操作后會通過事先約定的方式,如信號或回調函數來通知應用程序,比如使用aio_read。
總結一下,同步/異步對于I/O來講就是關注結果的通知方式以及是否需要程序自行進行數據的拷貝。
圖片
2.3 概念辨析(阻塞≠同步,非阻塞≠異步)
在我們的理解中,很容易將阻塞和同步以及非阻塞和異步聯系起來,但其對于I/O操作來說,阻塞和非阻塞僅僅只是描述數據準備階段的等待狀態,而同步異步則是涵蓋了整個I/O操作的通知機制。也就是說,在處理I/O時,無論是阻塞還是非阻塞都是同步I/O,只有使用特殊的API的才是異步的I/O。
對比維度 | 阻塞 / 非阻塞 | 同步 / 異步 |
關注焦點 | 數據準備階段的進程狀態 | 整個 I/O 操作的結果通知方式 |
進程參與度 | 僅影響數據準備階段是否阻塞 | 決定進程是否需要主動等待或輪詢結果 |
典型特征 | 阻塞時進程暫停,非阻塞時進程可執行其他任務 | 同步需主動監控,異步由內核主動通知 |
3.I/O模型
根據上面對于阻塞/非阻塞以及同步/異步的概念說明,接下來來看一下常見的I/O模型,此處主要做概念的說明。
3.1 阻塞I/O模型
1)實現流程:進程發起I/O請求->內核檢查數據是否準備好->沒準備好則阻塞等待->數據準備好后內核拷貝數據到用戶空間,線程被喚醒,繼續執行。
3.2 非阻塞I/O模型
1)實現流程:進程發起 I/O 請求→內核檢查數據是否準備好→若未準備好,內核返回 “未就緒”,進程不阻塞,繼續執行其他任務→進程定期輪詢發起 I/O 請求→數據準備完成后,內核將數據拷貝到用戶空間,返回結果→進程處理數據。
2)特點:無需長時間阻塞,但會造成一些CPU資源浪費。
3.3 I/O復用模型
多路I/O共用一個同步阻塞接口,任意I/O可操作時都能激活I/O操作,這是對阻塞I/O的改進,讓阻塞發生在多路復用的接口(如select,epoll),而不是發生在單個I/O上。
1)實現流程:進程創建監控對象(如 epoll 實例)→將需要監控的 I/O 描述符添加到監控對象中→進程阻塞等待監控對象通知→當任一 I/O 描述符數據準備好后,監控對象喚醒進程→進程對就緒的 I/O 描述符進行數據拷貝和處理。
2)特點:資源消耗減少,但數據拷貝階段仍可能阻塞。
3.4 信號驅動I/O模型
1)實現流程:進程發起 I/O 請求時,注冊信號處理函數→內核返回,進程不阻塞,繼續執行→數據準備完成后,內核發送信號通知進程→進程調用信號處理函數,完成數據拷貝和處理。
2)特點:避免輪詢開銷,但帶來了信號機制的復雜性。
3.5 異步I/O模型
1)實現流程:進程發起異步 I/O 請求,指定回調函數→內核負責完成數據準備和數據拷貝→操作完成后,內核通過回調函數通知進程→進程處理結果。
2)特點:全程無阻塞和輪詢,CPU利用率高,編程稍復雜。
3.6 I/O模型總結
上面介紹的五種I/O模型,我們從I/O的兩階段來看(數據準備階段和數據拷貝階段),前面四種都有阻塞且有依賴程序主動獲取狀態,只有最后的異步I/O模型完全沒有阻塞,由內核通知。
圖片
4.總結
本文通過介紹阻塞/非阻塞、同步/異步概念以及五種基本的I/O模型,接下來將繼續I/O基礎的介紹,也就是文件I/O和流的概念。




























