區分三種IO模型和select/poll/epoll

部分內容來源:JavaGuide?


select/poll/epoll 和 三種IO模型之間的關系是什么?

區分普通IO和IO多路復用

普通IO,即一個線程對應一個連接,因為每個線程只處理一個客戶端 socket,目標明確:線程中直接操作該 socket 的 read() / write(),無需關心其他連接,也就是無需遍歷文件描述符

可以理解成,一個線程只持有一個Socket的文件描述符

而IO多路復用是一個線程持有多個Socket的文件描述符,所以它有一個文件描述符集合,內核要遍歷這個文件描述集合檢查每個Socket中是否有數據


區分select/poll/epoll和三種IO模型

select/poll/epoll 是 如何遍歷文件描述符尋找有數據的 Socket 的方法;

IO 模型是Socket 拿到數據后如何處理的策略

IO多路復用是單線程如何高效管理和尋找多個Socket,而IO模型是如何處理多個Socket的數據

并且IO多路復用屬于同步IO

Reactor是基于select/epoll這些IO多路復用機制實現的,也就是基于同步IO

Proactor是基于異步IO機制實現的


IO多路復用的演進流程

線程池實現資源復用

如果要讓服務器服務多個客戶端,那么最直接的方式就是為每一條連接創建線程

其實創建進程也是可以的,原理是一樣的

進程和線程的區別在于線程比較輕量級些,線程的創建和線程間切換的成本要小些

為了描述簡述,后面都以線程為例

處理完業務邏輯后,隨著連接關閉后線程也同樣要銷毀了,但是這樣不停地創建和銷毀線程,不僅會帶來性能開銷,也會造成浪費資源,而且如果要連接幾萬條連接,創建幾萬個線程去應對也是不現實的

要這么解決這個問題呢?我們可以使用「資源復用」的方式

通過池化思想保存歷史連接

也就是不用再為每個連接創建線程,而是創建一個「線程池」,將連接分配給線程,然后一個線程可以處理多個連接的業務。


線程怎樣才能高效地處理多個連接的業務?

當一個連接對應一個線程時,線程一般采用「read -> 業務處理 -> send」的處理流程

如果當前連接沒有數據可讀,那么線程會阻塞在 read 操作上(socket 默認情況是阻塞 I/O)

不過這種阻塞方式并不影響其他線程。

但是引入了線程池,那么一個線程要處理多個連接的業務,線程在處理某個連接的 read 操作時,如果遇到沒有數據可讀,就會發生阻塞,那么線程就沒辦法繼續處理其他連接的業務。

要解決這一個問題,最簡單的方式就是將 socket 改成非阻塞,然后線程不斷地輪詢調用 read 操作來判斷是否有數據,這種方式雖然該能夠解決阻塞的問題

但是解決的方式比較粗暴

因為輪詢是要消耗 CPU 的,而且隨著一個線程處理的連接越多,輪詢的效率就會越低

為什么Socket要設置為非阻塞?

當socket設為非阻塞時,即使沒有數據可讀,read()也會立即返回一個【無數據的錯誤】

(如 Linux 的EAGAIN),不會阻塞線程

此時線程可以通過輪詢處理多個連接

線程循環遍歷自己負責的所有socket描述符,對每個socket調用read()

  1. 如果read()返回數據,就處理該連接的業務;
  2. 如果read()返回 “無數據”,就跳過這個socket,繼續輪詢下一個

監聽連接

上面的問題在于,線程并不知道當前連接是否有數據可讀,從而需要每次通過 read 去試探

那有沒有辦法在只有當連接上有數據的時候,線程才去發起讀請求呢?

答案是有的,實現這一技術的就是 I/O 多路復用

I/O 多路復用技術會用一個系統調用函數來監聽我們所有關心的連接,也就說可以在一個監控線程里面監控很多的連接


三種IO模型

小區別

IO多路復用屬于網絡監聽模型,例如Redis實現網絡監聽的時候就是使用IO多路復用的,當Redis啟動的時候,它會主動使用IO多路復用網絡監聽模型去監聽

每個 Socket 在內核中都有對應的接收緩沖區發送緩沖區

read:從該 Socket 對應的接收緩沖區中讀取數據到用戶緩沖區


Reactor 是非阻塞同步網絡模式,而 Proactor 是異步網絡模式

這里先給大家復習下阻塞、非阻塞、同步、異步 I/O 的概念

阻塞I/O

先來看看阻塞 I/O,當用戶程序執行 read,線程會被阻塞

一直等到內核數據準備好,并把數據從內核緩沖區拷貝到應用程序的緩沖區中,當拷貝過程完成,read 才會返回

注意:阻塞等待的是「內核數據準備好」和「數據從內核態拷貝到用戶態」這兩個過程

過程如下圖:


非阻塞 I/O

知道了阻塞 I/O,來看看非阻塞 I/O,非阻塞的 read 請求在數據未準備好的情況下立即返回,可以繼續下執行

此時應用程序不斷輪詢內核直到數據準備好

內核將數據拷貝到應用程序緩沖區,read 才可以獲取到結果

過程如下圖:

注意,這里最后一次 read 調用,獲取數據的過程,是一個同步的過程,是需要等待的過程。這里的同步指的是內核態的數據拷貝到用戶程序的緩存區這個過程


異步IO

如果 socket 設置了 O_NONBLOCK 標志,那么就表示使用的是非阻塞 I/O 的方式訪問

而不做任何設置的話,默認是阻塞 I/O

因此,無論 read 和 send 是阻塞 I/O,還是非阻塞 I/O 都是同步調用

因為在 read 調用時,內核將數據從內核空間拷貝到用戶空間的過程都是需要等待的,也就是說這個過程是同步的,如果內核實現的拷貝效率不高,read 調用就會在這個同步過程中等待比較長的時間

為什么這么說?

同步 的核心是:用戶線程必須親自參與數據拷貝的等待過程

并且用戶 線程必須等待拷貝完成才能繼續執行

同步IO要等待的兩個步驟:

  1. 「內核數據準備好」
  2. 「數據從內核空間拷貝到用戶空間」

阻塞IO:等待。你到咖啡店后,發現咖啡還沒做好,于是站在柜臺前一直等

非阻塞IO:輪詢。你到咖啡店后如果沒好,那你就去附近晃悠一會兒,然后再問咖啡時候做好了,直到店員說好了


真正的異步 I/O 是「內核數據準備好」和「數據從內核態拷貝到用戶態」這兩個過程都不用等待

當我們發起 aio_read(異步 I/O)之后,就立即返回,內核自動將數據從內核空間拷貝到用戶空間

這個拷貝過程同樣是異步的,內核自動完成的

和前面的同步操作不一樣,應用程序并不需要主動發起拷貝動作

過程如下圖:


理解IO的簡單例子

舉個你去飯堂吃飯的例子,你好比應用程序,飯堂好比操作系統


阻塞 I/O

你去飯堂吃飯,但是飯堂的菜還沒做好,然后你就一直在那里等啊等,等了好長一段時間終于等到飯堂阿姨把菜端了出來(數據準備的過程),但是你還得繼續等阿姨把菜(內核空間)打到你的飯盒里(用戶空間),經歷完這兩個過程,你才可以離開。


非阻塞 I/O

你去了飯堂,問阿姨菜做好了沒有,阿姨告訴你沒,你就離開了,過幾十分鐘,你又來飯堂問阿姨,阿姨說做好了,于是阿姨幫你把菜打到你的飯盒里,這個過程你是得等待的


異步 I/O

你讓飯堂阿姨將菜做好并把菜打到飯盒里后,把飯盒送到你面前,整個過程你都不需要任何等待


很明顯,異步 I/O 比同步 I/O 性能更好

因為異步 I/O 在「內核數據準備好」和「數據從內核空間拷貝到用戶空間」這兩個過程都不用等待

Proactor 正是采用了異步 I/O 技術,所以被稱為異步網絡模型


簡單總結-IO多路復用的演進流程

面試引導:

線程創建銷毀的開銷

->池化思想

->select,poll存在的問題

->輪詢機制對比事件驅動機制

->epoll,基于紅黑樹和哈希表而不是遍歷文件描述符

->引出IO多路復用的兩種實現,即Reactor和Proactor


池化思想:

如果讓一個服務器能夠服務更多的服務端,最直接的方式就是給每一條連接創建一個線程

但是線程的創建和銷毀是有一定的開銷的,會消耗CPU的時間片輪轉的資源

所以為了達到資源復用就出現了【池化思想】,也就是我們的線程池


不要弄混執行任務的線程池和處理IO的線程池,這兩個東西只是分別處理的東西不同

線程的職責可以根據任務類型劃分

有的線程專注于處理連接的 I/O 操作

有的線程專注于執行業務邏輯任務


IO線程如何高效處理多個連接的業務:

一個連接對應一個線程時線程的處理流程:

「read -> 業務處理 -> send」

線程池的目的是讓一個線程照顧多個連接

但一線程對應多連接時,線程在處理某個連接的 read 操作時,如果沒有數據可讀,則會阻塞

導致線程無法執行其它的IO任務

簡單解決方式:將Socket換成非阻塞,之后線程不斷地輪詢調用 read 操作來判斷是否有數據

但輪詢是要消耗 CPU 的,隨著一個線程處理的連接越多,輪詢的效率就會越低

當socket設為非阻塞時,即使沒有數據可讀,read()也會立即返回一個【無數據的錯誤】,不會阻塞線程


監聽連接:

問題所在:線程并不知道當前連接是否有數據可讀

因此需要每次通過 read 去試探(輪詢)

我們可以引入一種事件驅動機制,等連接來了我們再去執行,這就是epoll


三種IO模型-快速復習

小區別(防止概念混淆):

IO多路復用屬于網絡監聽模型,例如Redis實現網絡監聽的時候就是使用IO多路復用的,當Redis啟動的時候,它會主動使用IO多路復用網絡監聽模型去監聽

每個 Socket 在內核中都有對應的接收緩沖區發送緩沖區

read:從該 Socket 對應的接收緩沖區中讀取數據到用戶緩沖區


理解三種IO模型:

read 和 send 是阻塞 I/O,還是非阻塞 I/O 都是同步調用

因為在 read 調用時,內核將數據從內核空間拷貝到用戶空間的過程都是需要等待的,也就是說這個過程是同步的,如果內核實現的拷貝效率不高,read 調用就會在這個同步過程中等待比較長的時間

為什么這么說?

同步 的核心是:用戶線程必須親自參與數據拷貝的等待過程

并且用戶 線程必須等待拷貝完成才能繼續執行

同步IO要等待的兩個步驟:

  1. 「內核數據準備好」
  2. 「數據從內核空間拷貝到用戶空間」

阻塞IO:等待。你到咖啡店后,發現咖啡還沒做好,于是站在柜臺前一直等

非阻塞IO:輪詢。你到咖啡店后如果沒好,那你就去附近晃悠一會兒,然后再問咖啡時候做好了,直到店員說好了


真正的異步 I/O 是「內核數據準備好」和「數據從內核態拷貝到用戶態」這兩個過程都不用等待

當我們發起 aio_read(異步 I/O)之后,就立即返回

內核自動將數據從內核空間拷貝到用戶空間

這個拷貝過程同樣是異步的,內核自動完成的

和前面的同步操作不一樣,應用程序并不需要主動發起拷貝動作

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

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

相關文章

Actor-Critic重要性采樣原理

目錄 AC的數據低效性: 根本原因:策略更新導致數據失效 應用場景: 1. 離策略值函數估計 2. 離策略策略優化 3. 經驗回放(Experience Replay) 4. 策略梯度方法 具體場景分析 場景1:連續策略更新 場…

【贈書福利,回饋公號讀者】《智慧城市與智能網聯汽車,融合創新發展之路》

「5G行業應用」公號作家團隊推出《智慧城市與智能網聯汽車,融合創新發展之路》。本書由機械工業出版社出版,探討如何通過車城融合和創新應用,促進汽車產業轉型升級與生態集群發展,提升智慧城市精準治理與出行服務效能。&#xff0…

5G NR PDCCH之處理流程

本節主要介紹PDCCH處理流程概述。PDCCH(Physical Downlink Control Channel,物理下行控制信道)主要用于傳輸DCI(Downlink Control Information,下行控制信息),用于通知UE資源分配,調…

力扣網編程135題:分發糖果(貪心算法)

一. 簡介本文記錄力扣網上涉及數組方面的編程題:分發糖果。這里使用貪心算法的思路來解決(求局部最優,最終求全局最優解):每個孩子只需要考慮與相鄰孩子的相對關系。二. 力扣網編程135題:分發糖果&#xff…

每日mysql

什么是Mysql索引最左匹配原則?最左匹配原則是指,在復合索引中,查詢條件需要從左到右和索引開始依次完全匹配的時候,復合索引才可以被有效使用。因為聯合索引在建立b樹的過程中是根據索引的順序從左到右進行排序的,所以…

樹莓派5-ollama-linux-arm64.tgz 下載

1.下載 由于官方下載速度太慢且容易失敗,我這里上傳了一份到云盤供大家下載: 通過網盤分享的文件:ollama-linux-arm64.tgz 鏈接: https://pan.baidu.com/s/1tx_OPpl-8O2HJfXlP4tXTg?pwdffwx 提取碼: ffwx --來自百度網盤超級會員v4的分享 …

2024年團體程序設計天梯賽

比賽鏈接 https://ac.nowcoder.com/acm/contest/80027 A&#xff1a; JMU-1 考察搜索的能力百度一下可知&#xff0c;2024 年天梯賽總決賽的比賽日為4 月 20日 參考代碼 //2024 年天梯賽總決賽的比賽日為4 月 20日 void solve(){//A20-7cout<<"H\n"; } B&…

基于CMMI的軟件質量管理體系深度解析

核心理念&#xff1a;CMMI&#xff08;Capability Maturity Model Integration&#xff09;是通過過程改進驅動質量提升的體系化框架&#xff0c;其本質是建立可量化、可重復、可優化的工程管理能力一、CMMI體系框架與演進 #mermaid-svg-MdDBl2P8fSHYDHMc {font-family:"t…

2025年滲透測試面試題總結-2025年HW(護網面試) 44(題目+回答)

安全領域各種資源&#xff0c;學習文檔&#xff0c;以及工具分享、前沿信息分享、POC、EXP分享。不定期分享各種好玩的項目及好用的工具&#xff0c;歡迎關注。 目錄 2025年HW(護網面試) 44 1. SQL注入常用函數 2. SQLMap爆當前庫名參數 3. Nmap探測系統參數 4. Nmap小寫 …

【操作系統-Day 5】通往內核的唯一橋梁:系統調用 (System Call)

Langchain系列文章目錄 01-玩轉LangChain&#xff1a;從模型調用到Prompt模板與輸出解析的完整指南 02-玩轉 LangChain Memory 模塊&#xff1a;四種記憶類型詳解及應用場景全覆蓋 03-全面掌握 LangChain&#xff1a;從核心鏈條構建到動態任務分配的實戰指南 04-玩轉 LangChai…

完整 Spring Boot + Vue 登錄系統

項目名稱&#xff1a;springboot-vue-login-template? 功能一覽模塊功能后端Spring Boot MyBatis Plus JWT Shiro數據庫MySQL 用戶表前端Vue3 Element Plus Axios登錄流程用戶名/密碼驗證 → 返回 Token → 存儲 LocalStorage權限控制攔截器校驗 Token Shiro 角色權限跨…

Redis 基礎詳細介紹(Redis簡單介紹,命令行客戶端,Redis 命令,Java客戶端)

1. Redis 簡介Redis&#xff08;Remote Dictionary Server&#xff09;是一個開源的內存數據庫&#xff0c;遵守 BSD 協議&#xff0c;它提供了一個高性能的鍵值&#xff08;key-value&#xff09;存儲系統&#xff0c;常用于緩存、消息隊列、會話存儲等應用場景。1.1 特征豐富…

C/C++數據結構之多維數組

概述多維數組&#xff0c;實際上就是“數組的數組”。最常見的是二維數組&#xff0c;就像一個表格&#xff0c;擁有行和列。而三維數組則可以想象為多個這樣的表格堆疊起來形成的一個立方體。依此類推&#xff0c;我們可以構建四維、五維甚至更高維度的數組。多維數組主要用于…

[Rust 基礎課程]選一個合適的 Rust 編輯器

市面上現在有很多編輯器都可以開發 Rust&#xff0c;很多都是以安裝 Rust 插件的形式來對 Rust 做支持&#xff0c;本課程使用 RustRover&#xff0c;如果你喜歡其他的編輯器&#xff0c;可以自己搗鼓下。 RustRover https://www.jetbrains.com/rust/ jetbrains 專門對于 Ru…

【零基礎學AI】第37講:提示詞工程(Prompt Engineering)

本節課你將學到 理解提示詞工程的核心原理 掌握5種實用的Prompt設計模式 學會優化提示詞的評估方法 實現一個智能問答系統優化案例 開始之前 環境要求 Python 3.8安裝包&#xff1a;pip install openai tiktokenOpenAI API密鑰&#xff08;免費注冊&#xff1a;https://plat…

莫蘭迪色系工作總結匯報PPT模版分享

莫蘭迪色工作總結PPT模版&#xff0c;莫蘭迪調色板PPT模版&#xff0c;莫蘭迪色系高級簡約PPT模版&#xff0c;莫蘭迪色系工作匯報&#xff0c;莫蘭迪總結匯報模版 莫蘭迪色系工作總結匯報PPT模版分享&#xff1a;https://pan.quark.cn/s/35bcaa03c837

uniapp的app項目,某個頁面長時間無操作,返回首頁

最開始想做成一個公共的&#xff0c;完全提取出來的一個組件&#xff0c;組件設置背景透明&#xff0c;到時候哪個頁面需要&#xff0c;直接引入組件就可以了&#xff0c;所以最開始做的是一個vue的組件&#xff0c;在組件中&#xff0c;監聽頁面的touchstart&#xff0c;但是這…

【實證分析】上市公司綠色戰略數據集(2000-2023年)

數據簡介&#xff1a;綠色戰略是指企業根據其所處的外部環境&#xff08;包括“綠色浪潮”等環保趨勢&#xff09;和企業自身的經營條件&#xff0c;為實現企業生存與發展質量的持續提升&#xff0c;而對企業生產經營活動進行綠色化改造的總體規劃。這包括制定企業綠色可持續發…

【SpringAI】7. 基于 milvus 的向量檢索

SpringAI 基于 milvus 的向量檢索 向量數據庫可以使用 milvus&#xff0c;redis,Elasticsearch 等&#xff0c;本文以 milvus 為例&#xff1a; 1. 啟動milvus 為了盡可能快速上手springai的vectordb功能&#xff0c;我們推薦使用云上的milvus&#xff0c;注冊就能創建免費的…

如何使用數字化動態水印對教育視頻進行加密?

文章目錄前言一、什么是數字化動態水印二、使用數字化動態水印對教育視頻加密的好處&#xff1f;三、數字化動態水印的實現原理四、如何實現數字化動態水印對教育視頻加密總結前言 教育資源數字化蓬勃發展的今天&#xff0c;優質視頻課程已成為機構的核心知識資產。然而&#…