【Linux】47.高級IO(1)

文章目錄

  • 1. 高級IO
    • 1.1 五種IO模型
    • 1.2 高級IO重要概念
      • 1.2.1 同步通信 vs 異步通信
      • 1.2.2 阻塞 vs 非阻塞
    • 1.3非阻塞IO
      • 1.3.1 fcntl
      • 1.3.2 實現函數SetNoBlock
      • 1.3.3 輪詢方式讀取標準輸入
      • 1.3.4 I/O多路轉接之select
        • 1.3.4.1 初識select:
        • 1.3.4.2 select函數原型
        • 1.3.4.3 理解select執行過程


1. 高級IO

1.1 五種IO模型

[釣魚例子]

  • 阻塞IO: 在內核將數據準備好之前, 系統調用會一直等待. 所有的套接字, 默認都是阻塞方式.

阻塞IO是最常見的IO模型.

b1ec28c33d73553f0f533dfb2f7f6578

  • 非阻塞IO: 如果內核還未將數據準備好, 系統調用仍然會直接返回, 并且返回EWOULDBLOCK錯誤碼.

非阻塞IO往往需要程序員循環的方式反復嘗試讀寫文件描述符, 這個過程稱為輪詢. 這對CPU來說是較大的浪費, 一般只有特定場景下才使用

0a1f3215a2333d995b59518f6f625052

  • 信號驅動IO: 內核將數據準備好的時候, 使用SIGIO信號通知應用程序進行IO操作.

f74701d18ed4883f485655b0de6f8748

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

c8a62d36ae2870d11aeba3fd70877224

  • 異步IO: 由內核在數據拷貝完成時, 通知應用程序(而信號驅動是告訴應用程序何時可以開始拷貝數據).

ddb9a78c361fe790231ca2e57908b990

小結:

任何IO過程中, 都包含兩個步驟. 第一是等待, 第二是拷貝. 而且在實際的應用場景中, 等待消耗的時間往往都遠遠高于拷貝的時間. 讓IO更高效, 最核心的辦法就是讓等待的時間盡量少


1.2 高級IO重要概念

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

1.2.1 同步通信 vs 異步通信

同步和異步關注的是消息通信機制.

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

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

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

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


1.2.2 阻塞 vs 非阻塞

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

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

1.3非阻塞IO

1.3.1 fcntl

一個文件描述符, 默認都是阻塞IO

函數原型如下.

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

傳入的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).

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


1.3.2 實現函數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參數.

1.3.3 輪詢方式讀取標準輸入

#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);                       // 將標準輸入(文件描述符0)設置為非阻塞模式while (1) {                          // 無限循環char buf[1024] = {0};            // 定義并初始化緩沖區ssize_t read_size = read(0, buf, sizeof(buf) - 1);  // 嘗試從標準輸入讀取數據if (read_size < 0) {             // 如果讀取失敗(在非阻塞模式下,沒有數據可讀會返回-1)perror("read");              // 打印錯誤信息sleep(1);                    // 休眠1秒continue;                    // 繼續下一次循環}printf("input:%s\n", buf);       // 打印讀取到的輸入內容}return 0;                            // 程序結束(實際上這行代碼不會執行,因為有無限循環)
}

這段程序演示了非阻塞I/O的工作方式:

  1. 首先將標準輸入(文件描述符0)設置為非阻塞模式
  2. 在無限循環中,程序嘗試從標準輸入讀取數據
  3. 由于是非阻塞模式,當沒有輸入數據時,read()不會阻塞等待,而是立即返回-1,同時設置errno為EAGAIN或EWOULDBLOCK
  4. 程序捕獲這個錯誤,打印錯誤信息,然后休眠1秒后再次嘗試讀取
  5. 當有數據輸入時,read()會成功讀取數據并返回讀取的字節數,然后程序打印輸入的內容

這種模式允許程序在沒有輸入時繼續執行其他任務(在本例中只是休眠),而不是被阻塞在輸入操作上,適用于需要同時處理多個I/O事件的場景。


1.3.4 I/O多路轉接之select

1.3.4.1 初識select:

系統提供select函數來實現多路復用輸入/輸出模型.

  • select系統調用是用來讓我們的程序監視多個文件描述符的狀態變化的;
  • 程序會停在select這里等待,直到被監視的文件描述符有一個或多個發生了狀態改變;

1.3.4.2 select函數原型

select的函數原型如下: #include <sys/select.h>

int select(int nfds, fd_set *readfds, fd_set *writefds,fd_set *exceptfds, struct timeval *timeout);

參數解釋:

  • 參數nfds是需要監視的最大的文件描述符值+1;
  • rdset,wrset,exset分別對應于需要檢測的可讀文件描述符的集合,可寫文件描述符的集 合及異常文件描述符的集合;
  • 參數timeout為結構timeval,用來設置select()的等待時間

參數timeout取值:

  • NULL:則表示select()沒有timeout,select將一直被阻塞,直到某個文件描述符上發生了事件;

  • 0:僅檢測描述符集合的狀態,然后立即返回,并不等待外部事件的發生。

  • 特定的時間值:如果在指定的時間段里沒有事件發生,select將超時返回。

關于fd_set結構

其實這個結構就是一個整數數組, 更嚴格的說, 是一個 “位圖”. 使用位圖中對應的位來表示要監視的文件描述符.

提供了一組操作fd_set的接口, 來比較方便的操作位圖

void FD_CLR(int fd, fd_set *set); // 用來清除描述詞組set中相關fd 的位
int FD_ISSET(int fd, fd_set *set); // 用來測試描述詞組set中相關fd 的位是否為真
void FD_SET(int fd, fd_set *set); // 用來設置描述詞組set中相關fd的位
void FD_ZERO(fd_set *set); // 用來清除描述詞組set的全部位

關于timeval結構

timeval結構用于描述一段時間長度,如果在這個時間內,需要監視的描述符沒有事件發生則函數返回,返回值為0。

1241a998a52b51f0b1b28870b85fa847

函數返回值:

  • 執行成功則返回文件描述詞狀態已改變的個數
  • 如果返回0代表在描述詞狀態改變前已超過timeout時間,沒有返回
  • 當有錯誤發生時則返回-1,錯誤原因存于errno,此時參數readfds,writefds, exceptfds和timeout的值變成不可預測。

錯誤值可能為:

  • EBADF 文件描述詞為無效的或該文件已關閉
  • EINTR 此調用被信號所中斷
  • EINVAL 參數n 為負值。
  • ENOMEM 核心內存不足

1.3.4.3 理解select執行過程

理解select模型的關鍵在于理解fd_set,為說明方便,取fd_set長度為1字節,fd_set中的每一bit可以對應一個文件描述符fd。則1字節長的fd_set最大可以對應8個fd.

(1)執行fd_set set; FD_ZERO(&set);則set用位表示是0000,0000。

(2)若fd=5,執行FD_SET(fd,&set);后set變為0001,0000(第5位置為1) *

(3)若再加入fd=2,fd=1,則set變為0001,0011

(4)執行select(6,&set,0,0,0)阻塞等待

(5)若fd=1,fd=2上都發生可讀事件,則select返回,此時set變為0000,0011。

注意:沒有事件發生的fd=5被清空。

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

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

相關文章

【Vulkan 入門系列】創建幀緩沖、命令池、命令緩存,和獲取圖片(六)

這一節主要介紹創建幀緩沖&#xff08;Framebuffer&#xff09;&#xff0c;創建命令池&#xff0c;創建命令緩存&#xff0c;和從文件加載 PNG 圖像數據&#xff0c;解碼為 RGBA 格式&#xff0c;并將像素數據暫存到 Vulkan 的 暫存緩沖區中。 一、創建幀緩沖 createFramebu…

ubuntu的普通用戶相關配置

1.切換到普通用戶下&#xff0c;不出現&#xff0c;用戶名主機ip, 環境變量被破壞&#xff0c; 參考&#xff1a;一文教你快速修改ubuntu終端顯示的主機名和用戶名_ubuntu終端名稱-CSDN博客 2.如果登陸進去無法使用ls,cd&#xff0c;vi等命令 2.1 環境變量 如果 PATH 被清空…

騰訊云×數語科技:Datablau DDM (AI智能版)上架云應用!

在數據爆炸式增長的時代&#xff0c;傳統的數據建模方式已難以滿足企業對敏捷性、智能化、自動化的需求。數語科技聯合騰訊云推出的 Datablau DDM 數據建模平臺&#xff08;AI智能版&#xff09;&#xff0c;基于AI語義建模技術&#xff0c;深度融合騰訊混元大模型能力&#xf…

Spark-streaming(一)

Spark-Streaming概述 Spark Streaming 用于流式數據的處理。 和 Spark 基于 RDD 的概念很相似&#xff0c;Spark Streaming 使用離散化流(discretized stream)作為抽象表示&#xff0c;叫作 DStream。 DStream 是隨時間推移而收到的數據的序列。 Spark-Streaming的特點&…

CS144 Lab 6 實戰記錄:構建 IP 路由器

1 實驗背景與目標 在 CS144 的 Lab 6 中&#xff0c;我們需要在之前實現的 NetworkInterface&#xff08;Lab 5&#xff09;基礎上構建一個完整的 IP 路由器。路由器的主要任務是根據路由表將接收到的 IP 數據報轉發到正確的網絡接口&#xff0c;并發送給正確的下一跳&#xf…

【網絡安全】社會工程學策略

1. 社會工程學簡介 社會工程攻擊是威脅行為者常用的攻擊方式。這是因為&#xff0c;誘騙人們提供訪問權限、信息或金錢通常比利用軟件或網絡漏洞更容易。 您可能還記得&#xff0c;社會工程學是一種利用人為錯誤來獲取私人信息、訪問權限或貴重物品的操縱技術。它是一個涵蓋性…

【含文檔+PPT+源碼】基于SpringBoot的開放實驗管理平臺設計與實現

項目介紹 本課程演示的是一款基于SpringBoot的開放實驗管理平臺設計與實現&#xff0c;主要針對計算機相關專業的正在做畢設的學生與需要項目實戰練習的 Java 學習者。 1.包含&#xff1a;項目源碼、項目文檔、數據庫腳本、軟件工具等所有資料 2.帶你從零開始部署運行本套系統…

鴻蒙NEXT開發定位工具類 (WGS-84坐標系)(ArkTs)

import geoLocationManager from ohos.geoLocationManager; import { BusinessError, Callback } from ohos.base; import { LogUtil } from ./LogUtil; import { PermissionUtil } from ./PermissionUtil; import { map, mapCommon } from kit.MapKit; /*** 定位工具類 (WGS-8…

SSM從入門到上手-全面講解SSM框架的使用.

一、SSM框架整合 將Spring、Spring MVC和MyBatis結合在一起&#xff0c;形成一個高效且易于維護的Web應用程序架構。具體整合的方式如下&#xff1a; Spring管理Bean&#xff1a;Spring負責管理所有的Java對象&#xff0c;包括Service層、DAO層等。通過Spring的IoC容器進行依賴…

學員答題pk知識競賽小程序怎么做

制作學員答題PK知識競賽小程序&#xff0c;主要有以下步驟&#xff1a; 一、規劃設計 明確需求&#xff1a;確定小程序的使用場景是校園知識競賽、培訓機構考核還是企業內部培訓等。答題功能&#xff0c;規定答題的具體規則&#xff0c;包括題目類型&#xff08;單選、多選、…

視頻分析設備平臺EasyCVR視頻技術驅動下,監控上墻全組件解析與組網應用方案

隨著數字化進程的加速推進&#xff0c;視頻監控技術在工業、商業、社區等諸多領域得到了廣泛應用。盡管不同場景對監控功能的具體需求存在差異&#xff0c;但底層硬件架構具有顯著的共性特征。實際部署中&#xff0c;僅需依據網絡環境等實際情況&#xff0c;靈活調整設備的連接…

idea使用docker插件一鍵部署項目

一、首先保證我們電腦上已經安裝了docker docker -v查看docker版本&#xff0c;如果不能識別&#xff0c;需要先下載docker destop&#xff0c;在官網下載正常安裝即可。 安裝成功就可以使用docker 命令了 二、idea下載docker插件并配置docker參數 我是通過tcp連接docker服務…

SQL Tuning Advisor

什么是SQL Tuning Advisor STA可以用來優化那些已經被發現的高負載SQL. 默認情況下, Oracle數據庫在自動維護窗口中自動認證那些有問題的SQL并且執行優化建議&#xff0c;找尋提升高負載SQL執行計劃性能的方法. ** 如何查看自動優化維護窗口產生的報告? ** SQL> set ser…

uniapp-商城-31-shop頁面中的 我的訂單

前面的章節講了很多關于頁面 布局 的知識。 現在來看看其他欄目&#xff0c;我的訂單頁面。 1 頁面樣式圖 基本的樣式包含shop頁面 我的訂單 點擊我的訂單&#xff0c;跳轉到訂單頁面 點擊訂單的每一條訂單&#xff0c;跳轉到訂單詳情 2、創建訂單頁面 2.1 創建sub頁面文件…

深入探討JavaScript性能瓶頸與優化實戰指南

JavaScript作為現代Web開發的核心語言,其性能直接影響用戶體驗與業務指標。隨著2025年前端應用的復雜性持續增加,性能優化已成為開發者必須掌握的核心技能。本文將從性能瓶頸分析、優化策略、工具使用三個維度,結合實戰案例,系統梳理JavaScript性能優化的關鍵路徑。 一、Ja…

基于AI與drawio的圖表生成技術及其在學術研究中的應用前景分析

一、研究背景與沖突 在當今數字化時代&#xff0c;學術研究與信息傳播的方式發生了深刻變革。隨著數據量的爆炸式增長以及研究內容的日益復雜&#xff0c;高效、精準地呈現研究成果變得至關重要。圖表作為一種直觀、簡潔且信息承載量大的表達方式&#xff0c;在學術研究中扮演著…

uniapp 仿小紅書輪播圖效果

通過對小紅書的輪播圖分析&#xff0c;可得出以下總結&#xff1a; 1.單張圖片時容器根據圖片像素定高 2.多圖時輪播圖容器高度以首圖為錨點 3.比首圖長則固高左右留白 4.比首圖短則固寬上下留白 代碼如下&#xff1a; <template><view> <!--輪播--><s…

【ORACLE】記錄一些ORACLE的merge into語句的BUG

【ORACLE】記錄一些ORACLE的merge into語句的BUG 一、自相矛盾-DML重啟動行為差異,違反acid原則 發現版本&#xff1a;10g ~ 23ai 這個用例在我之前的文章里有提過&#xff0c;ORACLE和PG系關于并發事務行為有一個非常大的差異&#xff0c;就是ORACLE在某些并發沖突的場景下會…

2025上海車展:光峰科技全球首發“靈境”智能車載光學系統

當AI為光賦予思想&#xff0c;汽車將會變成什么樣&#xff1f;深圳光峰科技為您揭曉答案。 2025年4月23日&#xff0c;在剛剛開幕的“2025上海車展”上&#xff0c;全球領先的激光核心器件公司光峰科技舉辦了主題為“AI光影盛宴&#xff0c;智享未來出行”的媒體發布會&#x…

密碼學的hash函數,哈希碰撞, collision resistance, BTC用到的SHA-256簡介

密碼學中的哈希函數、哈希碰撞、抗碰撞性&#xff08;collision resistance&#xff09;以及比特幣中使用的 SHA-256 的簡明介紹&#xff1a; &#x1f9e9; 一、哈希函數&#xff08;Hash Function&#xff09; 定義&#xff1a; 哈希函數是一種將任意長度的輸入&#xff08;…