初識Linux · 五種IO模型和非阻塞IO

目錄

前言:

五種IO模型

什么是IO

IO模型

非阻塞IO


前言:

前文我們已經將網絡的基本原理介紹完了,都是通過圍繞TCP/IP四層協議,將應用層,傳輸層,網絡層,數據鏈路層全部介紹完畢,至于部分小主題,比如ARP欺騙,HTTP協議的原理,cookie以及session等內容,我們放在后面介紹。

本文以及之后的內容,主要通過是介紹IO相關的問題,通過IO模型的介紹,從而引出多路復用的具體內容,通過介紹select,poll,epoll,最后再單獨介紹一下Reactor,網絡的基本原理我們就介紹完了。

那么廢話不多說,我們直接進入五種IO模型。


五種IO模型

什么是IO

對于IO這個話題,我們從語言階段,一直到了現在都經常談論,因為IO問題不管在哪個階段都是非常重要的,從C語言階段的printf scanf,到文件操作的read和write涉及到了IO,即便是Linux,我們從一開始的文件系統,引出了文件描述符,到后面的網絡也是一直使用文件描述符的概念,足以看出IO在編程中的重要性了。

那么問題來了,一開始我們只是粗略的將IO認定為是輸入輸出,今天我們進一步探討,當我們第一次使用scanf的時候,我們發現只要我們不輸入,系統就會阻塞住,系統在干什么呢?

系統在等我們輸入,所以IO有一個非常重要的過程是:等待。當我們輸入數據之后,系統也收到了數據也就不再等待,就執行了下一步操作了。這個過程還有讀取的操作,或者是寫入的操作,但是不管怎么說,都是從發送緩沖區/接收緩沖區拷貝數據到應用層的緩沖區。

所以實際上的IO = 等待 + 拷貝

而我們從一開始的學習到現在,使用到的基本上都是阻塞IO,自然也就存在非阻塞的IO,我們放在IO模型里面介紹。那么我們在MySQL中介紹索引的時候,我們提及到了IO次數如果多了,就一定會降低效率,所以我們就要使用高效的IO,那么高效的IO實際上減少了等待操作在IO中的比例

IO模型

對于IO模型我們拿釣魚舉例子,假設有五個人,分別在魚塘中釣魚,張三拿個魚竿就坐在那里一直等待,當別人問他什么事,他也不理睬,這是第一種IO模型;李四拿個魚竿放在那里,就不管了,轉身去做自己的事兒了,然后定期來查看魚竿的情況,這是第二種IO模型;王五拿個魚竿,釣魚的時候放個鈴鐺,當魚上鉤了,就放在自己手里的事兒,然后釣魚,這是第三種IO模型;趙六就很有說法了,拿了一卡車的魚竿過來了,同時使用很多的魚竿,然后一個一個的檢查魚竿情況,這是第四種IO模型;田七的釣魚操作是派遣一個人,讓這個人像張三一樣,完成釣魚的等待和釣操作,自己就轉身去干其他事兒了,也就是田七只負責吃的操作,這是第五種IO模型。

那么上述都是一個口語化的介紹,實際上的名稱叫做:
第一種,阻塞IO,比如我們常見的read recvfrom scanf都是阻塞IO的代表,如果系統的數據還沒有準備好,強行非阻塞的話就會返回錯誤碼11,一會兒我們可以實驗。

第二種,非阻塞IO,非阻塞IO顧名思義,IO的同時干自己的事兒,那么這意味著需要反反復復的嘗試讀寫文件描述符,這個過程稱為輪詢,但是因為會反反復復的操作文件操作符,所以會對CPU資源造成較大的浪費,一般根據特定情況使用:

第三種,信號驅動IO,同王五一樣,鈴鐺就像信號,內核將數據處理好之后,就使用信號SIGIO通知應用程序,這種IO模型實際上也是非阻塞IO模型:

第四種,IO多路轉接,它實際上是阻塞IO的plus版本,也就是說張三一個人進行阻塞IO的時候,趙六已經創建了100個張三的分身了,所以實際上的流程圖也就是IO的流程圖,那么多路轉接也是我們后面的主題,介紹select poll epoll就是從這里引出的:

第五種,異步IO,異步IO實際上就是先讓內核吧數據報準備好,再進行拷貝的,最后OS給應用程序發信號通知準備好了,這個過程田七只是作為發起IO,但是等的過程交給了內核,然后他再來負責拷貝,那么被稱為異步IO就是因為發出 I/O 請求的線程不會阻塞等待,后續的 I/O 完成由內核負責異步處理,應用程序通過信號、回調或輪詢某種狀態(如 aio_error())來獲取 I/O 是否完成,所以它是異步的。

那么以上五種IO中,第四種IO多路復用的效率是最高的,因為大大減少了等待了時間,這也是之后我們為什么圍繞它展開的理由。


非阻塞IO

對于阻塞IO來說,是我們最常見,也是最經常使用的IO模型,但是如果我們今天想嘗試一下非阻塞IO怎么辦呢?我們可以使用函數fcntl

第一個參數是對應的文件描述符,第二個參數是執行的控制命令,第三個參數取決于第三個參數,可以忽略。

一般常用的cmd有F_SETFL,F_GETFL,GET用來獲取狀態標志,SET用來獲取標志,比如我們想要將一個文件描述符設置為非阻塞的就可以這樣操作:

void SetNoBlock()
{int n = ::fcntl(0, F_GETFL);if(n < 0)std::cout << "Error" << std::endl;else   fcntl(0, F_SETFL, n | O_NONBLOCK);
}int main() 
{SetNoBlock();while(true){char buffer[1024];ssize_t n = ::read(0, buffer, sizeof(buffer));if(n > 0){std::string str = buffer;std::cout << str << std::endl;}else if(n == 0){std::cout << "read done!" << std::endl;break;}else{// errno == 11 EWOULDBLOCK EAGAINif(errno == EWOULDBLOCK){continue;}std::cout << "GG" << std::endl;sleep(1);}}return 0;
}

我們會發現如果我們強行讓read這種阻塞IO變成非阻塞IO,就會導致返回的值是負數,所以這個時候就有這種情況:發生錯誤是因為read本身出錯還是因為非阻塞下沒有數據可讀導致read不會阻塞直接返回-1?所以我們可使用EWOULDBLOCK比較一下,當然了,它的本質是11,也是EAGAIN:

那么IO模型先到這里,算是一個開胃小菜~


感謝閱讀!

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

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

相關文章

Node.js 24發布:性能與安全雙提升

在科技的迅速發展中&#xff0c;Node.js作為一個備受青睞的開源跨平臺Java運行環境&#xff0c;近日迎來了其24.0版本的正式發布。此次更新不僅承諾提升性能和安全性&#xff0c;還為開發者提供了更為順暢的開發體驗&#xff0c;值得我們深入探討。 Node.js 24.0的最大亮點之一…

SLAM文獻之-SuperOdometry: Lightweight LiDAR-inertial Odometry and Mapping

《Super Odometry: IMU-centric LiDAR-Visual-Inertial Estimator for Challenging Environments》是一篇旨在增強 SLAM 系統在惡劣環境下魯棒性的工作&#xff0c;尤其關注塵霧、煙霧等遮擋條件下的魯棒估計。下面從算法原理、公式推導、創新點和應用場景四個方面進行詳細解析…

指令燒錄ORIN NANO操作系統

1 概述 模組為ORIN NANO 4GB版本 Ubuntu系統為18.04虛擬機 說明&#xff1a;刷機過程會有重新連接USB的操作&#xff0c;燒寫過程需要注意虛擬機提示&#xff0c;官方不建議使用虛擬機&#xff0c;建議直接使用ubuntu操作系統的機器。 2 下載燒錄所需文件 進入到下載網址&am…

游戲引擎學習第287天:加入brain邏輯

Blackboard&#xff1a;動態控制類似蛇的多節實體 我們目前正在處理一個關于實體系統如何以組合方式進行管理的問題。具體來說&#xff0c;是在游戲中實現多個實體可以共同或獨立行動的機制。例如&#xff0c;我們的主角擁有兩個實體組成部分&#xff0c;一個是身體&#xff0…

QML定時器Timer和線程任務WorkerScript

定時器 Timer 屬性 interval: 事件間隔毫秒repeat: 多次執行&#xff0c;默認只執行一次running: 定時器啟動triggeredOnStart: 定時器啟動時立刻觸發一次事件 信號 triggered(): 定時時間到&#xff0c;觸發此信號 方法 restart(): 重啟定時器start(): 啟動定時器stop(): 停止…

Linux中的域名解析服務器

一、DNS&#xff08;域名系統&#xff09;詳解 1. 核心功能與特點 特性說明核心作用將域名&#xff08;如 www.example.com&#xff09;轉換為 IP 地址&#xff08;如 192.168.1.1&#xff09;&#xff0c;實現人類可讀地址與機器可讀地址的映射。端口與協議- 默認端口&#…

Springboot2

1、搭建環境 2、配置文件 application.properties application.yml 3、springboot接收請求 springspringmvc 接收請求 響應數據 4、springboot集成jdbc spring-boot-starter-jdbc.jar JdbcTemplate(update|query) 5、springboot自動裝配原理&#xff08;重點&#x…

【課堂筆記】核方法和Mercer定理

文章目錄 Kernal引入定義Mercer定理描述有限情形證明一般情形證明 Kernal 引入 在實際數據中常常遇到不可線性分割的情況&#xff0c;此時通常需要將其映射到高維空間中&#xff0c;使其變得線性可分。例如二維數據&#xff1a; 通過映射 ? ( x 1 , x 2 ) ( x 1 2 , 2 x 1…

談談未來iOS越獄或巨魔是否會消失

2024年10月的預測&#xff0c;先說結論&#xff1a; 巨魔iOS17.1消失概率為99%。 因為巨魔強依賴的漏洞就是一個簽名漏洞&#xff0c;攻擊面有限又經過2輪修復&#xff0c;第3次出現漏洞的概率極低。而越獄的話由于系統組件和服務較多&#xff0c;所以出現漏洞概率高攻擊面多&…

根據當前日期計算并選取上一個月和上一個季度的日期范圍,用于日期控件的快捷選取功能

1.選擇月份范圍 代碼如下&#xff1a; <el-date-picker v-model"value" type"monthrange" align"right" unlink-panels range-separator"至"start-placeholder"開始月份" end-placeholder"結束月份" :picker-…

用戶棧的高效解析邏輯

一、背景 在之前的博客 內核邏輯里抓取用戶棧的幾種方法-CSDN博客 里&#xff0c;介紹了使用內核邏輯進行用戶棧的函數地址的抓取邏輯&#xff0c;但是并沒有涉及如何解析出函數符號的邏輯。 就如perf工具一樣&#xff0c;它也是分為兩個步驟&#xff0c;一個步驟是內核態抓取…

vue3 el-table 行號

在 Vue 3 中&#xff0c;使用 Element Plus 的 <el-table> 組件來創建表格時&#xff0c;如果你想添加行號&#xff08;即每一行的編號&#xff09;&#xff0c;可以通過自定義列來實現。下面是如何實現的步驟&#xff1a; 1. 安裝 Element Plus 首先&#xff0c;確保你…

Linux:進程信號---信號的保存與處理

文章目錄 1. 信號的保存1.1 信號的狀態管理 2. 信號的處理2.1 用戶態與內核態2.2 信號處理和捕捉的內核原理2.3 sigaction函數 3. 可重入函數4. Volatile5. SIGCHLD信號 序&#xff1a;在上一章中&#xff0c;我們對信號的概念及其識別的底層原理有了一定認識&#xff0c;也知道…

UML 圖的細分類別及其應用

統一建模語言&#xff08;UML&#xff0c;Unified Modeling Language&#xff09;是一種用于軟件系統建模的標準化語言&#xff0c;廣泛應用于軟件工程領域。UML 圖分為多種類別&#xff0c;每種圖都有其特定的用途和特點。本文將詳細介紹 UML 圖的細分類別&#xff0c;包括 類…

「極簡」扣子(coze)教程 | 小程序UI設計進階!控件可見性設置

大師兄在上一期的內容中對用戶的UI做了一些簡單的介紹。這期大師兄繼續介紹UI設計上的進階小技巧&#xff0c;幫我們獲得更好的使用體驗。 扣子&#xff08;coze&#xff09;編程 「極簡」扣子(coze)教程 | 3分鐘學會小程序UI設計&#xff01;從零開始創建頁面和瓷片按鈕 「極…

2025年滲透測試面試題總結-快手[實習]安全工程師(題目+回答)

網絡安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 快手[實習]安全工程師 一面問題分析與詳細回答 1. 自我介紹 4. 項目問題與解決 7. 防止SQL注入&…

WordPress Madara插件存在文件包含漏洞(CVE-2025-4524)

免責聲明 本文檔所述漏洞詳情及復現方法僅限用于合法授權的安全研究和學術教育用途。任何個人或組織不得利用本文內容從事未經許可的滲透測試、網絡攻擊或其他違法行為。使用者應確保其行為符合相關法律法規,并取得目標系統的明確授權。 對于因不當使用本文信息而造成的任何直…

互聯網大廠Java面試場景:從Spring Boot到分布式緩存技術的探討

互聯網大廠Java面試場景&#xff1a;從Spring Boot到分布式緩存技術的探討 場景描述 互聯網大廠某次Java開發崗面試&#xff0c;主考官是一位嚴肅的技術專家&#xff0c;而應聘者則是搞笑的程序員“碼農明哥”。面試圍繞音視頻場景的技術解決方案展開&#xff0c;探討從Sprin…

leetcode hot100刷題日記——8.合并區間

class Solution { public:vector<vector<int>> merge(vector<vector<int>>& intervals) {if(intervals.empty()){//復習empty函數啊&#xff0c;日記1有的return {};}// 按照區間的起始位置進行排序sort(intervals.begin(), intervals.end());vect…

Unity中GPU Instancing使用整理

GPU Instancing是一種繪制調用優化方法,可在單個繪制調用中渲染具有相同材質Mesh的多個副本(實例),可用于繪制在場景中多次出現的幾何體(例如,樹木或灌木叢),在同一繪制調用中渲染相同的網格,每個實例可以具有不同的屬性(如 Color 或 Scale),渲染多個實例的繪制調用…