首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

網絡編程核心觀念釐清:同步、異步、阻塞、非阻塞的區別與聯繫

     編輯:關於C語言

在網絡編程的 I/O 模型討論中,「同步/異步」與「阻塞/非阻塞」是最容易混淆的四個概念。許多開發者甚至資深工程師,也難以清晰闡述它們的邊界與關聯。本文參考經典著作《UNIX 網絡編程 卷一》第六章,結合內核視角,為你徹底拆解這五種 I/O 模型的本質差異。

五種 UNIX I/O 模型總覽

書中定義了以下五種可用的 I/O 模型:

  • 阻塞式 I/O:默認模型,進程在數據準備和複製階段均阻塞。
  • 非阻塞式 I/O:進程通過輪詢方式檢查數據是否就緒,不就緒即返回錯誤。
  • I/O 多路復用:利用 select/poll/epoll 同時監控多個文件描述符,阻塞在系統調用上而非具體 I/O 操作。
  • 信號驅動式 I/O:通過 SIGIO 信號通知進程數據就緒,工程實踐中較少使用。
  • 異步 I/O:告知內核啟動操作,內核完成數據複製後再通知進程(POSIX aio 系列)。

核心流程:兩個關鍵階段

一次輸入操作包含兩個階段:

  1. 等待數據就緒:網絡數據到達網卡,經驅動程序複製到內核緩衝區。
  2. 數據從內核複製到用戶空間:將內核緩衝區數據拷貝至應用程序緩衝區。

各模型圖解與關鍵差異

1. 阻塞式 I/O

應用調用 recvfrom 後,進程在兩個階段均被掛起睡眠,直到數據複製完成才返回。

阻塞 I/O 模型示意圖

紅色標記區域即為進程阻塞等待的過程。

2. 非阻塞式 I/O

核心語句:「當所請求的 I/O 操作非得把本進程投入睡眠才能完成時,不要把進程投入睡眠,而是返回一個錯誤。」

進程反覆調用 recvfrom,若數據未就緒立即返回 EWOULDBLOCK,需應用層自行輪詢。

非阻塞 I/O 模型示意圖

3. I/O 多路復用

雖然 select/epoll 本身是阻塞的,但它阻塞在「監控多個描述符」這一系統調用上,而非具體的 recvfrom。一旦有描述符就緒,再發起真正的讀取。

I/O 多路復用模型示意圖

4. 信號驅動式 I/O

進程預先註冊信號處理函數,數據就緒時內核發送 SIGIO,進程在信號處理函數中調用 recvfrom。此處略過詳細圖解。

信號驅動 I/O 模型示意圖

5. 異步 I/O

調用 aio_read 後立即返回,內核自動完成「等待數據」與「複製數據」兩個階段,完成後通知進程(回調或信號)。這是唯一在兩個階段均不阻塞進程的模型。

異步 I/O 模型示意圖

同步 vs 異步、阻塞 vs 非阻塞:本質定義

POSIX 給出權威定義:

  • 同步 I/O:導致請求進程阻塞,直到 I/O 操作完成(包含數據複製階段)。
  • 異步 I/O:不導致請求進程阻塞。

前四種模型(阻塞、非阻塞、多路復用、信號驅動)本質上都是同步 I/O,它們的區別僅在於「第一階段(等待數據就緒)如何處理」。而異步 I/O 則將兩個階段完全交由內核代勞。

白話總結

概念對核心關注點一句話定義
阻塞 / 非阻塞進程/線程在訪問數據時,數據是否就緒、是否需要等待調用者主動發起請求後,是否立即返回或被掛起睡眠。
同步 / 異步訪問數據的方式與責任歸屬同步需主動讀寫數據,讀寫過程中仍會阻塞;異步只需接收「操作完成」通知,數據讀寫由內核完成。

理解這兩組概念的正交關係,是掌握高性能網絡編程的基石。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved