【Linux網絡】五種IO模型與阻塞IO

IO

在Linux網絡環境里,IO(Input/Output)指的是網絡數據在系統與外部網絡(像其他設備、服務器或者客戶端)之間進行傳輸的過程。

它是網絡編程和系統性能優化的核心內容。

  • IO :INPUT和OUTPUT(站在進程角度)
  • 關于IO,read和write都是阻塞式的IO
  • 網絡傳輸數據問題,本質上就是IO問題
  • 如何更好的理解IO問題,就需要更好的理解什么叫做高效的IO?
    • 首先明確,任何通信場景其IO通信場景,效率上一定是會有上限的 。
    • 抽象來說:IO=等+拷貝
    • 在拷貝的角度來說,我們需要充分利用硬件資源以及網絡資源
    • 在“等”的角度來說,我們需要減少IO中“等”的權重

網絡IO的核心流程

網絡IO包含兩個關鍵階段:

  • 數據就緒:數據從網絡傳輸到網卡,再由網卡傳至內核緩沖區。
  • 數據拷貝:數據從內核緩沖區復制到用戶空間的應用程序。

網絡IO模型

Linux支持多種網絡IO模型,它們的主要差異在于如何處理這兩個階段(阻塞、非阻塞、同步、異步)。

常見的網絡IO模型有:

  • 阻塞IO(Blocking IO)
  • 非阻塞IO(Non-blocking IO)
  • IO多路復用(IO Multiplexing)
  • 信號驅動IO(Signal-driven IO)
  • 異步IO(Asynchronous IO)

注意:
前四種IO模型都屬于同步IO,等的方式不同,但還是自己在深度參與IO過程,只要是自己參與了IO過程,就是同步IO

釣魚例子

  • 張三:眼睛盯著魚漂,魚漂動了,釣魚
    • 阻塞IO
  • 李四 :查看魚漂是否動了,如果沒有,就看手機刷抖音,期間不斷查看魚漂是否動了
    • 非阻塞IO(輪巡)
  • 王五 : 帶來一車魚竿插在岸邊,來回檢測哪一個魚竿上的魚漂動了
    • IO多路復用
  • 趙六 :在魚漂上系上一個鈴鐺,開始釣魚后刷抖音,直到鈴鐺響起,開始釣上魚。
    • 信號驅動IO
  • 田七:我雇傭一個人給我釣魚,釣到的魚給我。
    • 異步IO

上述例子中:

  • 魚竿:文件描述符
  • 釣魚佬:進程

1. 阻塞IO(最基礎的模型)

  • 工作方式:應用程序調用系統調用后會被阻塞,一直等到數據就緒并被復制到用戶空間,或者出現錯誤時才會返回。所有的套接字,默認
    都是阻塞方式
  • 特點:編程邏輯簡單,但同一時間只能處理一個連接,容易造成性能瓶頸。
    在這里插入圖片描述

2. 非阻塞IO

  • 工作方式:應用程序調用系統調用后會立即返回。如果數據未就緒,會返回EWOULDBLOCK錯誤。應用程序需要不斷輪詢來檢查數據是否就緒。
  • 特點:非阻塞IO能夠避免線程長時間阻塞,但往往需要程序員循環的方式反復嘗試讀寫文件描述符,這個過程稱為輪詢.這對CPU來說是較大的浪費,一般只有特定場景下才使用.
    在這里插入圖片描述
3. IO多路復用(高性能服務器的核心)
  • 工作方式:借助selectpollepoll等系統調用,一個進程可以同時監視多個文件描述符(FD)。當某個FD的數據就緒時,就會通知應用程序進行處理。
  • 優勢:能夠用單線程處理大量并發連接,顯著減少了系統開銷。
    在這里插入圖片描述

雖然從流程圖上看起來和阻塞IO類似.實際上最核心在于IO多路轉接能夠同時等待多個文件描述符的就緒狀態.

4. 信號驅動IO
  • 工作方式:應用程序先通過sigaction注冊信號處理函數,然后繼續執行其他任務。當數據就緒時,內核會發送SIGIO信號,應用程序在信號處理函數中進行數據讀取操作。
  • 特點:屬于異步通知模式,但數據拷貝階段仍然是同步的。

在這里插入圖片描述

5. 異步IO(真正的異步模型)
  • 工作方式:應用程序通過aio_read等接口發起異步IO請求,然后繼續執行后續操作。內核會自動完成數據的讀取和拷貝工作,完成后通過回調函數或者信號通知應用程序。
  • 特點:整個IO過程都是異步的,極大地提高了系統的并發處理能力。
    在這里插入圖片描述
    小結:
  • 任何IO過程中,都包含兩個步驟.第一是等待,第二是拷貝.
  • 而且在實際的應用場景中,等待消耗的時間往往都遠遠高于拷貝的時間.讓IO更高效,最核心的辦法就是讓等待的時間盡量少

高級IO重要概念

在這里,我們要強調幾個概念

同步通信 vs 異步通信(synchronous communication/ asynchronous communication)

同步和異步是消息通信機制。

  • 所謂同步,就是在發出一個調用時,在沒有得到結果之前,該調用就不返回。但是一旦調用返回,就得到返回值了;換句話說,就是由調用者主動等待這個調用的結果
  • 異步則是相反,調用在發出之后,這個調用就直接返回了,所以沒有返回結果;換句話說,當一個異步過程調用發出后,調用者不會立刻得到結果;而是在調用發出后,被調用者通過狀態、通知來通知調用者,或通過回調函數處理這個調用。

另外,我們回憶在講多進程多線程的時候,也提到同步和互斥。這里的同步通信和進程之間的同步是完全不相干的概念。

  • 進程/線程同步也是進程/線程之間直接的制約關系。
  • 是為完成某種任務而建立的兩個或多個線程,這個線程需要在某些位置上協調他們的工作次序而等待、傳遞信息所產生的制約關系。尤其是在訪問臨界資源的時候。

同學們以后在看到“同步”這個詞,一定要先搞清楚大背景是什么。這個同步,是同步通信異步通信的同步,還是同步與互斥的同步。

阻塞 vs 非阻塞

阻塞和非阻塞關注的是程序在等待調用結果(消息,返回值)時的狀態。

  • 阻塞調用是指調用結果返回之前,當前線程會被掛起。調用線程只有在得到結果之后才會返回。
  • 非阻塞調用指在不能立刻得到結果之前,該調用不會阻塞當前線程。

其他高級IO

非阻塞IO,紀錄鎖,系統V流機制,I/O多路轉接(也叫I/O多路復用),readv和writev函數以及存儲映射IO(mmap),這些統稱為高級IO。

我們此處重點討論的是I/O多路轉接

非阻塞IO

fcntl

一個文件描述符,默認都是阻塞IO。
函數原型如下:

#include <unistd.h>
#include <fcntl.h>
int fcntl(int fd, int cmd, ... /* arg */ );

fcntl的cmd的值不同,后面追加的參數也不相同。
fcntl函數有5種功能:

  • 復制一個現有的描述符(cmd=F_DUPFD)。
  • 獲得/設置文件描述符標記(cmd=F_GETFD或F_SETFD)。
  • 獲得/設置文件狀態標記(cmd=F_GETFL或F_SETFL)。
  • 獲得/設置異步I/O所有權(cmd=F_GETOWN或F_SETOWN)。
  • 獲得/設置記錄鎖(cmd=F_GETLK,F_SETLK或F_SETLKW)。

我們此處只是用第三種功能,獲取/設置文件狀態標記,就可以將一個文件描述符設置為非阻塞。

實現函數SetNoBlock

基于fcntl,我們實現一個SetNoBlock函數,將文件描述符設置為非阻塞。

void SetNoBlock(int fd) {int fl = fcntl(fd, F_GETFL);if (fl < 0) {perror("fcntl");return;}fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}
  • 使用F_GETFL將當前的文件描述符的屬性取出來(這是一個位圖)。
  • 然后再使用F_SETFL將文件描述符設置回去。設置回去的同時,加上一個O_NONBLOCK參數。

輪詢方式讀取標準輸入

#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>void SetNoBlock(int fd) {int fl = fcntl(fd, F_GETFL);if (fl < 0) {perror("fcntl");return;}fcntl(fd, F_SETFL, fl | O_NONBLOCK);
}int main() {SetNoBlock(0);while (1) {char buf[1024] = {0};ssize_t read_size = read(0, buf, sizeof(buf) - 1);if (read_size < 0) {perror("read");sleep(1);continue;}printf("input:%s\n", buf);}return 0;
}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81411.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81411.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81411.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

入門OpenTelemetry——應用自動埋點

埋點 什么是埋點 埋點&#xff0c;本質就是在你的應用程序里&#xff0c;在重要位置插入采集代碼&#xff0c;比如&#xff1a; 收集請求開始和結束的時間收集數據庫查詢時間收集函數調用鏈路信息收集異常信息 這些埋點數據&#xff08;Trace、Metrics、Logs&#xff09;被…

大數據場景下數據導出的架構演進與EasyExcel實戰方案

一、引言&#xff1a;數據導出的演進驅動力 在數字化時代&#xff0c;數據導出功能已成為企業數據服務的基礎能力。隨著數據規模從GB級向TB級甚至PB級發展&#xff0c;傳統導出方案面臨三大核心挑戰&#xff1a; ?數據規模爆炸?&#xff1a;單次導出數據量從萬級到億級的增長…

拓展運算符與數組解構賦值的區別

拓展運算符與數組解構賦值是ES6中用于處理數組的兩種不同的特性&#xff0c;它們有以下區別&#xff1a; 概念與作用 ? 拓展運算符&#xff1a;主要用于將數組展開成一系列獨立的元素&#xff0c;或者將多個數組合并為一個數組&#xff0c;以及在函數調用時將數組作為可變參…

2025年全國青少年信息素養大賽初賽真題(算法創意實踐挑戰賽C++初中組:文末附答案)

2025年全國青少年信息素養大賽初賽真題(算法創意實踐挑戰賽C++初中組:文末附答案) 一、單項選擇題(每題 5 分) C++ 程序流程控制的基本結構不包括以下哪項? A. 分支結構 B. 數據結構 C. 循環結構 D. 順序結構 以下哪段代碼能將數組 int a[4] = {2, 4, 6, 8}; 的所有元素變…

計算機視覺與深度學習 | Python實現EMD-CNN-LSTM時間序列預測(完整源碼、數據、公式)

EMD-CNN-LSTM 1. 環境準備2. 數據生成(示例數據)3. EMD分解4. 數據預處理5. CNN-LSTM模型定義6. 模型訓練7. 預測與重構8. 性能評估核心公式說明1. 經驗模態分解(EMD)2. CNN-LSTM混合模型參數調優建議擴展方向典型輸出示例以下是使用Python實現EMD-CNN-LSTM時間序列預測的完…

React 19中useContext不需要Provider了。

文章目錄 前言一、React 19中useContext移除了Provider&#xff1f;二、使用步驟總結 前言 在 React 19 中&#xff0c;useContext 的使用方式有所更新。開發者現在可以直接使用 作為提供者&#xff0c;而不再需要使用 <Context.Provider>。這一變化簡化了代碼結構&…

單片機-STM32部分:14、SPI

飛書文檔https://x509p6c8to.feishu.cn/wiki/VYYnwOc9Zi6ibFk36lYcPQdRnlf 什么是SPI SPI 是英語Serial Peripheral interface的縮寫&#xff0c;顧名思義就是串行外圍設備接口。是Motorola(摩托羅拉)首先在其MC68HCXX系列處理器上定義的。 SPI&#xff0c;是一種高速的&…

Vue 3 動態 ref 的使用方式(表格)

一、問題描述 先給大家簡單介紹一下問題背景。我正在開發的項目中&#xff0c;有一個表格組件&#xff0c;其中一列是分鏡描述&#xff0c;需要支持視頻上傳功能。用戶可以為每一行的分鏡描述上傳對應的視頻示例。然而&#xff0c;在實現過程中&#xff0c;出現了一個嚴重的問…

構建 TypoView:一個富文本樣式預覽工具的全流程記錄

我正在參加CodeBuddy「首席試玩官」內容創作大賽&#xff0c;本文所使用的 CodeBuddy 免費下載鏈接&#xff1a;騰訊云代碼助手 CodeBuddy - AI 時代的智能編程伙伴 在一次和 CodeBuddy 的日常交流中&#xff0c;我提出了一個構想&#xff1a;能不能幫我從零構建一個富文本樣式…

AI:OpenAI論壇分享—《AI重塑未來:技術、經濟與戰略》

AI&#xff1a;OpenAI論壇分享—《AI重塑未來&#xff1a;技術、經濟與戰略》 導讀&#xff1a;2025年4月24日&#xff0c;OpenAI論壇全面探討了 AI 的發展趨勢、技術范式、地緣政治影響以及對經濟和社會的廣泛影響。強調了 AI 的通用性、可擴展性和高級推理能力&#xff0c;以…

Bash fork 炸彈 —— :(){ :|: };:

&#x1f9e0; 什么是 Fork 炸彈&#xff1f; Fork 炸彈是一種拒絕服務&#xff08;DoS&#xff09;攻擊技術&#xff0c;利用操作系統的 fork() 系統調用不斷創建新進程&#xff0c;直到系統資源&#xff08;如進程表、CPU、內存&#xff09;被耗盡&#xff0c;從而使系統無法…

<前端小白> 前端網頁知識點總結

HTML 標簽 1. 標題標簽 h1到h6 2. 段落標簽 p 3. 換行 br 水平線 hr 4. 加粗 strong 傾斜 em 下劃線 ins 刪除 del 5. 圖像標簽 img src-圖像的位置 alt- 圖片加載失敗顯示的文字 替換文本 title--- 鼠標放到圖片上顯示的文字 提示…

tomcat查看狀態頁及調優信息

準備工作 先準備一臺已經安裝好tomcat的虛擬機&#xff0c;tomcat默認是狀態頁是默認被禁用的 1.添加授權用戶 vim /usr/local/tomcat/conf/tomcat-users.xml22 <role rolename"manager-gui"/>23 <user username"admin" password"tomcat&q…

.NET NativeAOT 指南

目錄 1. 引言 2. 什么是 .NET NativeAOT&#xff1f; 2.1 NativeAOT 的定義 2.2 NativeAOT 與傳統 JIT 的對比 2.3 NativeAOT 的適用場景 3. NativeAOT 的核心優勢 3.1 性能提升 3.2 簡化部署 3.3 更小的應用體積 3.4 知識產權保護 4. NativeAOT 的基本用法 4.1 環境…

產品周圍的幾面墻

不能把排序&#xff0c;當單選題做。 2025年的杭州咖啡館&#xff0c;味道最濃的不是咖啡&#xff0c;是聊各種項目和創業的卷味。 在過去幾年&#xff0c;聊項目的也不少&#xff0c;那時候帶著更加濃烈的自信和松弛感&#xff0c;不過今年略帶幾分忐忑和試探的口吻。 看到網…

例舉3種強制類型轉換和2種隱式

1. 強制類型轉換 強制類型轉換是指程序員顯式地將一個數據類型的值轉換為另一種數據類型。這種轉換通常是通過使用特定的函數或運算符來完成的。 常用的強制類型轉換方法&#xff1a; 使用Number()函數 let value "123"; let num Number(value); // 強制轉換為數字…

UI-TARS本地部署

UI-TARS本地部署 UI-TARS本地部署 UI-TARS 論文&#xff08;arXiv&#xff09; UI-TARS 官方倉庫&#xff1a;包含部署指南、模型下載鏈接及示例代碼。 UI-TARS-Desktop 客戶端&#xff1a;支持本地桌面應用的交互控制。 模型部署框架&#xff1a;vLLM本地部署 1.下載項目…

新電腦軟件配置三 pycharm

快捷鍵放大和縮小字體 按住ctrl鼠標滾輪向上 縮小同理

華為OD機試真題——考勤信息(2025A卷:100分)Java/python/JavaScript/C/C++/GO最佳實現

2025 A卷 100分 題型 本專欄內全部題目均提供Java、python、JavaScript、C、C++、GO六種語言的最佳實現方式; 并且每種語言均涵蓋詳細的問題分析、解題思路、代碼實現、代碼詳解、3個測試用例以及綜合分析; 本文收錄于專欄:《2025華為OD真題目錄+全流程解析+備考攻略+經驗分…

Python語法規則:縮進、代碼塊與空格規范

在眾多編程語言中&#xff0c;Python 以其“簡潔而優雅”的語法風格獨樹一幟。然而&#xff0c;這種“簡潔”并非輕率隨意&#xff0c;而是建立在一套嚴謹的語法哲學之上。縮進、代碼塊與空格規范&#xff0c;不僅是 Python 的語法基礎&#xff0c;更是它傳達代碼意圖、塑造開發…