【Linux基礎】Linux的5種IO模型詳解

引入

為了更好的理解5種IO模型的區別,在介紹IO模型之前,我先介紹幾個概念

1.進程的切換

(1)定義

為了控制進程的執行,內核必須有能力掛起正在CPU上運行的進程,并恢復以前掛起的某個進程的執行。即從用戶態(較低的3G字節)切換到內核態(最高的1G字節),非常消耗系統資源。

(2)過程

  • 保存處理機上下文,包括程序計數器和其他寄存器。
  • 更新PCB信息。
  • 把進程的PCB移入相應的隊列,如就緒、在某事件阻塞等隊列。
  • 選擇另一個進程執行,并更新其PCB。
  • 更新內存管理的數據結構。
  • 恢復處理機上下文。

2.進程的阻塞

(1)定義

正在執行的進程,由于期待的某些事件未發生,由運行狀態變為阻塞狀態。

(2)特點

  • 只有處于運行狀態的進程(獲得CPU)才能被阻塞
  • 阻塞是主動行為
  • 不占用CPU資源

3.文件描述符

(1) 定義

用于描述指向文件的引用的抽象化概念

(2) 特點

  • 一個非負整數
  • 本質是一個索引值,指向內核為每一個進程所維護的該進程打開文件的記錄表

4.緩存IO

  • IO的數據緩存在文件系統的頁緩存中(先拷貝到內核的緩沖區)

  • 在應用程序和內核間多次數據拷貝,帶來很大的CPU開銷

5.并發與并行

  • 并發:同時進行的任務數

  • 并行:同時工作的物理資源數量(如CPU核數)

5種IO模型

  • IO的本質是socket的讀取,數據先拷貝到內核的緩沖區中,然后拷貝到應用程序的地址空間(進程)

1.BIO(blocking IO):同步阻塞 I/O

(1)過程

這里寫圖片描述

分析:從上圖可以看到在整個過程中,當用戶進程進行系統調用時,內核就開始了I/O的第一個階段,準備數據到緩沖區中,當數據都準備完成后,則將數據從內核緩沖區中拷貝到用戶進程的內存中,這時用戶進程才解除block的狀態重新運行。

(2)實例

  • Blocking I/O是在I/O執行的兩個階段都被block了。

  • 例如:我要去飯堂吃飯,這時飯堂的人很多,我就得排隊買飯,排隊的時間被浪費了,

(3)特點

  • 能夠及時返回數據,無延遲
  • 性能下降

2.NIO(nonblocking IO):同步非阻塞 I/O

(1)過程

這里寫圖片描述

分析:從上圖可以看到在I/O執行的兩個階段中,用戶進程只有在第二個階段被阻塞了,而第一個階段沒有阻塞,但是在第一個階段中,用戶進程需要盲等,不停的去輪詢內核,看數據是否準備好了。

(2)實例

  • nonblocking I/O是在I/O執行的第二個階段(數據復制)被block了,而第一個階段并未阻塞(數據準備)。

  • 例如:我要去飯堂吃飯,這時飯堂的人很多,一般來說我需要排隊買飯,但我們飯堂的管理最近變的比較人性化,你點完飯后,會給你一個號碼,但飯堂噪聲很大,我不得不頻繁的詢問我的飯是否做好了,但是我可以利用之前排隊的時間去買瓶飲料喝!

(3)特點

  • 拷貝數據的整個過程,進程仍然是阻塞的
  • 需要不斷詢問數據是否準備好了
  • 能夠在等待任務完成的過程中處理其他事件
  • 由于需要輪詢,所以延遲會增加

3.多路復用IO( IO multiplexing)

(1)過程

這里寫圖片描述

分析:

  • 從上圖可以看到在I/O復用模型中,由于同步非阻塞方式需要不斷主動輪詢,輪詢占據了很大一部分過程,輪詢會消耗大量的CPU時間,而 “后臺” 可能有多個任務在同時進行,

  • 如果循環查詢多個任務的完成狀態,只要有任何一個任務完成,就去處理它。輪詢不是進程的用戶態。這時 “IO 多路復用”就出現了。即UNIX/Linux 的 select、poll、epoll,

  • IO多路復用是阻塞在select,epoll這樣的系統調用之上,而沒有阻塞在真正的I/O系統調用如recvfrom之上。

  • 從整個IO過程來看,他們都是順序執行的,因此可以歸為同步模型(synchronous)。都是進程主動等待且向內核檢查狀態

(2)實例

  • 多路復用I/O執行的兩個階段用戶進程都是阻塞的,但是兩個階段是獨立的。

  • 例如:我要去飯堂吃飯,這時飯堂的人很多,點完飯后,我會拿到一個號碼,以前我不得不頻繁的詢問我的飯做好了沒,但是最近飯堂安裝了一塊電子顯示屏,你的飯好了就會在屏上顯示出來,這時候我就不用頻繁的去問了,直接看電子顯示屏就醒了,然后我就可以利用這個時間去超市買個牙膏了。

(3)特點

  • select/poll調用后會阻塞進程,但可以同時阻塞多個IO事件操作(文件描述符),有數據可讀或可寫(就緒事件),就通知用戶進程。

  • select 需要每次注冊事件(輪詢),而epoll不需要每次注冊事件(沒有輪詢,回調函數)

  • IO多路復用阻塞在select/epoll的系統調用之上的,而真正的IO系統調用如recvfrom是非阻塞的。

(4)適用場景

  • 服務器需要同時處理多個處于監聽狀態或連接狀態的套接字

  • 服務器需要處理多種網絡協議的套接字

4.信號驅動I/O( signal driven IO)

(1)過程

這里寫圖片描述

分析:從上圖可以看出,只有在I/O執行的第二階段阻塞了用戶進程,而在第一階段是沒有阻塞的。該模型在I/O執行的第一階段,當數據準備完成之后,會主動的通知用戶進程數據已經準備完成,即對用戶進程做一個回調。該通知分為兩種,一為水平觸發,即如果用戶進程不響應則會一直發送通知,二為邊緣觸發,即只通知一次。

(2)實例

  • 信號驅動I/O執行的第一階段阻塞,而第二階段不阻塞。

  • 例如:我要去飯堂吃飯,這時飯堂的人很多,點完飯后,我會拿到一個號碼,雖然說飯堂安裝了一塊電子顯示屏,但我在玩手機時還不得不抬頭看一下顯示屏上有我的號碼沒,最近飯堂買了一個大喇叭,哪個號碼好了,賣飯的阿姨就會用喊,雖說飯堂有點吵,但這個聲音還是可以聽到的,這樣我就可以專心的低頭玩手機了。

5.異步 I/O(asynchronous IO)

(1)過程

這里寫圖片描述

分析:從上圖可以看出,在該模型中,當用戶進程發起系統調用后,立刻就可以開始去做其它的事情,然后直到I/O執行的兩個階段都完成之后,內核會給用戶進程發送通知,告訴用戶進程操作已經完成了。

(2)實例

  • 異步 I/O執行的兩個階段都不會阻塞。

  • 例如:我要去飯堂吃飯,估計這會飯堂的人很多,但最近我們飯堂可以叫外賣了,這樣就省事多了,我直接打個電話,訂份飯送到我們宿舍,而我現在就可以利用原來去飯堂路上和等飯的時間寫博客了。

  • 這就是同步和異步的區別,原來我得親自去飯堂買飯,而現在我可以在宿舍叫外賣。

(3)特點

  • 讀寫操作由內核完成,完成后內核將數據放到指定的緩沖區,通知應用程序來取。

總結

這里寫圖片描述

  • 阻塞IO和非阻塞IO的區別:數據準備的過程中,進程是否阻塞。

  • 同步IO和異步IO的區別:數據拷貝的過程中,進程是否阻塞。



本人才疏學淺,若有錯,請指出,謝謝!?
如果你有更好的建議,可以留言我們一起討論,共同進步!?
衷心的感謝您能耐心的讀完本篇博文!

參考資料:聊聊Linux 五種IO模型

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

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

相關文章

計算機網絡【五】廣播通信+以太網

局域網的拓撲 廣域網使用點到點通信 局域網使用廣播通信 可以隨意向網絡中添加設備。 總線網星形網,使用集線器。現在多使用星形網絡。環狀網樹形網 其中匹配電阻用來吸收總線上傳播的信號。 共享通信媒體 靜態劃分信道 頻分復用、時分復用、波分復用、碼分復用…

聊聊Linux 五種IO模型

一篇《聊聊同步、異步、阻塞與非阻塞》已經通俗的講解了,要理解同步、異步、阻塞與非阻塞重要的兩個概念點了,沒有看過的,建議先看這篇博文理解這兩個概念點。在認知上,建立統一的模型。這樣,大家在繼續看本篇時&#…

操作系統【四】分頁存儲管理

連續分配方式的缺點: 固定分區分配:缺乏靈活性,產生大量的內部碎片,內存的利用率較低 動態分區分配:會產生許多外部碎片,雖然可以用緊湊技術處理,但是緊湊技術的時間代價較高 基本分頁存儲管理…

聊聊同步、異步、阻塞與非阻塞

近來遇到了一些常見的概念,尤其是網絡編程方面的概念,如:阻塞、非阻塞、異步I/O等等,對于這些概念自己也沒有太清晰的認識,只是很模糊的概念,說了解吧也了解,但是要讓自己準確的描述概念方面的具…

操作系統【五】分段內存管理+段頁式內存管理

基本分段存儲管理 與分頁最大的區別:離散分配時所分配地址空間的基本單位不同 進程的地址空間:按照程序自身的邏輯關系劃分為若干個段,每個段都有一個段名,每段從0開始編址 內存分配規則:以段位單位進行分配&#xff…

計算機網絡【六】網絡層協議

網絡層負責在不同網絡之間盡力轉發數據包(基于數據包的IP地址轉發)。不負責丟失重傳,也不負責順序(每一個數據包都是單獨選擇路徑)。 可靠傳輸是由傳輸層實現。 網絡設備和OSI參考模型 通過分層,屏蔽了…

epoll 水平觸發與邊緣觸發

https://blog.csdn.net/lihao21/article/details/67631516?refmyread epoll也是實現I/O多路復用的一種方法,為了深入了解epoll的原理,我們先來看下epoll水平觸發(level trigger,LT,LT為epoll的默認工作模式&#xff…

計算機網絡【3】網絡層

主要任務時把分組從源端發送到目的端,為分組交換網上的不同主機提供服務。網絡層傳輸單位是數據報 功能: 路由選擇與分組轉發(最佳路徑 )異構網絡互聯擁塞控制 數據交換方式 電路交換:通信時延小、有序傳輸、沒有沖…

C++空類的大小

https://blog.csdn.net/lihao21/article/details/47973609 本文中所說是C的空類是指這個類不帶任何數據,即類中沒有非靜態(non-static)數據成員變量,沒有虛函數(virtual function),也沒有虛基類(virtual base class)。 直觀地看&#xff0c…

Linux探秘之用戶態與內核態

https://www.cnblogs.com/bakari/p/5520860.html 一、 Unix/Linux的體系架構 如上圖所示,從宏觀上來看,Linux操作系統的體系架構分為用戶態和內核態(或者用戶空間和內核)。內核從本質上看是一種軟件——控制計算機的硬件資源&…

哈夫曼算法證明+哈夫曼編碼譯碼程序實現

哈夫曼算法證明 哈夫曼算法是一種貪心算法,我們考慮證明其最優子結構和貪心選擇性質: 最優子結構:假設一個樹是哈夫曼樹,則以其任意節點為根節點的最大子樹也是哈夫曼樹。 證明:子樹的根節點的值是其所有葉子節點出現…

Python3小知識

對于迭代器對象,Python默認賦值是將引用賦值,即指向同一片內存空間。為了實現對內存空間的賦值,我們可以使用分片進行深復制。例如: 當定義元組的時候,我們一般使用小括號將元素包圍起來,也可以不使用括號…

匯編:實現日歷星期數查詢工具

編制一個簡單日歷查詢工具,輸入年、月、日,能夠判斷當日的星期數,并進行輸出,數據的輸入和結果的輸出要有必要的提示,且提示獨占一行。 查閱資料 ? 經過查閱資料,發現有兩個相關的算法可以解決這個問題&…

一個通用純C隊列的實現

https://blog.csdn.net/kxcfzyk/article/details/31728179 隊列并不是很復雜的數據結構,但是非常實用,這里實現一個隊列是因為在我的另一篇博客非常精簡的Linux線程池實現中要用到。 隊列API定義如下: //queue.h #ifndef QUEUE_H_INCLUDED…

Dijkstra算法介紹+正確性證明+性能分析

算法介紹 源點s,數組d[u]表示s到u的最短距離,空集S,點集Q初始化:將源點s從點集中去掉,加入S,d[s]0,?v∈Q,d[v]w[s][v]\forall v\in Q ,d[v]w[s][v]?v∈Q,d[v]w[s][v]將Q中d[v]最小的點去掉加入S,并對u∈…

Linux C 實現一個簡單的線程池

https://www.cnblogs.com/GyForever1004/p/9185240.html 線程池的定義 線程池是一種多線程處理形式,處理過程中將任務添加到隊列,然后在創建線程后自動啟動這些任務。線程池線程都是后臺線程。每個線程都使用默認的堆棧大小,以默認的優先級…

斐波那契數列求解+尾遞歸

1.普通遞歸 這里觀察f[4]的遞歸樹代替f[10]的遞歸樹(后者比較大,畫不下)。 使用遞歸求解的時候復雜度為T(n)T(n?1)T(n?2)T(n)T(n-1)T(n-2)T(n)T(n?1)T(n?2),觀察遞歸樹,發現降速最快的是最右邊每次減2&#xff0c…

循環服務器,并發服務器模型以及I/O多路轉接模型

https://blog.csdn.net/xinianbuxiu/article/details/53455784 一、基于TCP/IP協議的基本循環服務器 tcp_server.c #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <sys/socket.h> #incl…

c++繼承父類的子類,如何調用父類的同名函數?

https://blog.csdn.net/qq_26399665/article/details/52080215 子類調用父類的同名函數&#xff1a; 子類和父類返回值參數相同&#xff0c;函數名相同&#xff0c;有virtual關鍵字&#xff0c;則由對象的類型決定調用哪個函數。 子類和父類只要函數名相同&#xff0c;沒有vi…

LCS最長公共子串

問題介紹 LCS問題(longest common subsequence problem)指的是求解兩個字符串最長公共子序列問題。這里的子序列是可以不連續的。LCS問題廣泛地出現在計算生物學中&#xff08;DNA序列、系統生成樹等等&#xff09;。這里介紹如何解決LCS問題&#xff0c;以及算法的正確性證明…