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




























