成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

手把手教Linux驅動8-Linux IO模型

系統
在計算機系統中I/O就是輸入(Input)和輸出(Output)的意思,針對不同的操作對象,可以劃分為磁盤I/O模型,網絡I/O模型,內存映射I/O, Direct I/O、數據庫I/O等,只要具有輸入輸出類型的交互系統都可以認為是I/O系統,也可以說I/O是整個操作系統數據交換與人機交互的通道,這個概念與選用的開發語言沒有關系,是一個通用的概念。

[[344024]]

什么是IO?

IO模型中,先討論下什么是IO?

在計算機系統中I/O就是輸入(Input)和輸出(Output)的意思,針對不同的操作對象,可以劃分為磁盤I/O模型,網絡I/O模型,內存映射I/O, Direct I/O、數據庫I/O等,只要具有輸入輸出類型的交互系統都可以認為是I/O系統,也可以說I/O是整個操作系統數據交換與人機交互的通道,這個概念與選用的開發語言沒有關系,是一個通用的概念。

在如今的系統中I/O卻擁有很重要的位置,現在系統都有可能處理大量文件,大量數據庫操作,而這些操作都依賴于系統的I/O性能,也就造成了現在系統的瓶頸往往都是由于I/O性能造成的。因此,為了解決磁盤I/O性能慢的問題,系統架構中添加了緩存來提高響應速度;或者有些高端服務器從硬件級入手,使用了固態硬盤(SSD)來替換傳統機械硬盤;一個系統的優化空間,往往都在低效率的I/O環節上,很少看到一個系統CPU、內存的性能是其整個系統的瓶頸。

那么數據被Input到哪,Output到哪呢?

Input(輸入)數據到內存中,Output(輸出)數據到IO設備(磁盤、網絡等需要與內存進行數據交互的設備)中;

 

主存(通常時DRAM)的一塊區域,用來緩存文件系統的內容,包含各種數據和元數據。

IO接口

IO設備與內存直接的數據傳輸通過IO接口,操作系統封裝了IO接口,我們編程時可以直接使用;

 

對于用來講,如果要和外設通信,只需要通過這些系統調用即可實現。

無處不在的緩存

 

  1. 如圖,當程序調用各類文件操作函數后,用戶數據(User Data)到達磁盤(Disk)的流程如圖所示。圖中描述了Linux下文件操作函數的層級關系和內存緩存層的存在位置。中間的黑色實線是用戶態和內核態的分界線。
  2. 從上往下分析這張圖,首先是C語言stdio庫定義的相關文件操作函數,這些都是用戶態實現的跨平臺封裝函數。stdio中實現的文件操作函數有自己的stdio buffer,這是在用戶態實現的緩存。此處使用緩存的原因很簡單——系統調用總是昂貴的。如果用戶代碼以較小的size不斷的讀或寫文件的話,stdio庫將多次的讀或者寫操作通過buffer進行聚合是可以提高程序運行效率的。stdio庫同時也支持fflush(3)函數來主動的刷新buffer,主動的調用底層的系統調用立即更新buffer里的數據。特別地,setbuf(3)函數可以對stdio庫的用戶態buffer進行設置,甚至取消buffer的使用。
  3. 系統調用的read(2)/write(2)和真實的磁盤讀寫之間也存在一層buffer,這里用術語Kernel buffer cache來指代這一層緩存。在Linux下,文件的緩存習慣性的稱之為Page Cache,而更低一級的設備的緩存稱之為Buffer Cache. 這兩個概念很容易混淆,這里簡單的介紹下概念上的區別:Page Cache用于緩存文件的內容,和文件系統比較相關。文件的內容需要映射到實際的物理磁盤,這種映射關系由文件系統來完成;Buffer Cache用于緩存存儲設備塊(比如磁盤扇區)的數據,而不關心是否有文件系統的存在(文件系統的元數據緩存在Buffer Cache中)。
  4. 綜上,既然討論Linux下的IO操作,自然是跳過stdio庫的用戶態這一堆東西,直接討論系統調用層面的概念了。對stdio庫的IO層有興趣的同學可以自行去了解。從上文的描述中也介紹了文件的內核級緩存是保存在文件系統的Page Cache中的。所以后面的討論基本上是討論IO相關的系統調用和文件系統Page Cache的一些機制。

Linux IO棧

雖然我們通過系統調用就可以簡單的實現對外設的數據讀取,實際上這得益于Linux完整的IO棧架構。

 

由圖可見,從系統調用的接口再往下,Linux下的IO棧致大致有三個層次:

  1. 文件系統層,以 write(2) 為例,內核拷貝了write(2)參數指定的用戶態數據到文件系統Cache中,并適時向下層同步
  2. 塊層,管理塊設備的IO隊列,對IO請求進行合并、排序(還記得操作系統課程學習過的IO調度算法嗎?)
  3. 設備層,通過DMA與內存直接交互,完成數據和具體設備之間的交互

結合這個圖,想想Linux系統編程里用到的Buffered IO、mmap(2)、Direct IO。

這些機制怎么和Linux IO棧聯系起來呢?

上面的圖有點復雜,畫一幅簡圖,把這些機制所在的位置添加進去:

 

傳統的Buffered IO使用read(2)讀取文件的過程什么樣的?

假設要去讀一個冷文件(Cache中不存在),open(2)打開文件內核后建立了一系列的數據結構,接下來調用read(2),到達文件系統這一層,發現Page Cache中不存在該位置的磁盤映射,然后創建相應的Page Cache并和相關的扇區關聯。然后請求繼續到達塊設備層,在IO隊列里排隊,接受一系列的調度后到達設備驅動層,此時一般使用DMA方式讀取相應的磁盤扇區到Cache中,然后read(2)拷貝數據到用戶提供的用戶態buffer中去(read(2)的參數指出的)。

整個過程有幾次拷貝?

從磁盤到Page Cache算第一次的話,從Page Cache到用戶態buffer就是第二次了。

而mmap(2)做了什么?

mmap(2)直接把Page Cache映射到了用戶態的地址空間里了,所以mmap(2)的方式讀文件是沒有第二次拷貝過程的。

那Direct IO做了什么?

這個機制更狠,直接讓用戶態和塊IO層對接,直接放棄Page Cache,從磁盤直接和用戶態拷貝數據。

好處是什么?

寫操作直接映射進程的buffer到磁盤扇區,以DMA的方式傳輸數據,減少了原本需要到Page Cache層的一次拷貝,提升了寫的效率。

對于讀而言,第一次肯定也是快于傳統的方式的,但是之后的讀就不如傳統方式了(當然也可以在用戶態自己做Cache,有些商用數據庫就是這么做的)。

除了傳統的Buffered IO可以比較自由的用偏移+長度的方式讀寫文件之外,mmap(2)和Direct IO均有數據按頁對齊的要求,Direct IO還限制讀寫必須是底層存儲設備塊大小的整數倍(甚至Linux 2.4還要求是文件系統邏輯塊的整數倍)。所以接口越來越底層,換來表面上的效率提升的背后,需要在應用程序這一層做更多的事情。所以想用好這些高級特性,除了深刻理解其背后的機制之外,也要在系統設計上下一番功夫。

阻塞/非阻塞與同步/異步

了解了IO的概念,現在我們來講解什么是阻塞、非阻塞、同步、異步。

阻塞/非阻塞

針對的對象是調用者自己本身的情況

阻塞

指調用者在調用某一個函數后,一直在等待該函數的返回值,線程處于掛起狀態。

非阻塞

指調用者在調用某一個函數后,不等待該函數的返回值,線程繼續運行其他程序(執行其他操作或者一直遍歷該函數是否返回了值)

同步/異步

針對的對象是被調用者的情況

同步

指的是被調用者在被調用后,操作完函數所包含的所有動作后,再返回返回值

異步

指的是被調用者在被調用后,先返回返回值,然后再進行函數所包含的其他動作。

五種IO模型

下面以recvfrom/recv函數為例,這兩個函數都是操作系統的內核函數,用于從(已連接)socket上接收數據,并捕獲數據發送源的地址。

recv函數原型:

  1. ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags) 
  2.   sockfd:接收端套接字描述符 
  3.   buff:用來存放recv函數接收到的數據的緩沖區 
  4.   nbytes:指明buff的長度 
  5.   flags:一般置為0 

網絡IO的本質是socket的讀取,socket在linux系統被抽象為流,IO可以理解為對流的操作。對于一次IO訪問(以read舉例),數據會先被拷貝到操作系統內核的緩沖區中,然后才會從操作系統內核的緩沖區拷貝到應用程序的地址空間。

所以說,當一個recv操作發生時,它會經歷兩個階段:

  • 第一階段:等待數據準備 (Waiting for the data to be ready)。
  • 第二階段:將數據從內核拷貝到進程中 (Copying the data from the kernel to the process)。

對于socket流而言:

  • 第一步:通常涉及等待網絡上的數據分組到達,然后被復制到內核的某個緩沖區。
  • 第二步:把數據從內核緩沖區復制到應用進程緩沖區。

阻塞IO(Blocking IO)

指調用者在調用某一個函數后,一直在等待該函數的返回值,線程處于掛起狀態。好比你去商場試衣間,里面有人,那你就一直在門外等著。(全程阻塞)

 

BIO程序流

當用戶進程調用了recv()/recvfrom()這個系統調用,kernel就開始了IO的第一個階段:準備數據(對于網絡IO來說,很多時候數據在一開始還沒有到達。比如,還沒有收到一個完整的UDP包。這個時候kernel就要等待足夠的數據到來)。這個過程需要等待,也就是說數據被拷貝到操作系統內核的緩沖區中是需要一個過程的。而在用戶進程這邊,整個進程會被阻塞(當然,是進程自己選擇的阻塞)。

第二個階段:當kernel一直等到數據準備好了,它就會將數據從kernel中拷貝到用戶內存,然后kernel返回結果,用戶進程才解除block的狀態,重新運行起來。

所以,blocking IO的特點就是在IO執行的兩個階段都被block了。

優點:

1. 能夠及時返回數據,無延遲;

2. 對內核開發者來說這是省事了;

缺點:

對用戶來說處于等待就要付出性能的代價了;

非阻塞IO

指調用者在調用某一個函數后,不等待該函數的返回值,線程繼續運行其他程序(執行其他操作或者一直遍歷該函數是否返回了值)。好比你要喝水,水還沒燒開,你就隔段時間去看一下飲水機,直到水燒開為止。(復制數據時阻塞)

 

非阻塞IO程序流

當用戶進程發出read操作時,如果kernel中的數據還沒有準備好,那么它并不會block用戶進程,而是立刻返回一個error。從用戶進程角度講,它發起一個read操作后,并不需要等待,而是馬上就得到了一個結果。用戶進程判斷結果是一個error時,它就知道數據還沒有準備好,于是它可以再次發送read操作。一旦kernel中的數據準備好了,并且又再次收到了用戶進程的system call,那么它馬上就將數據拷貝到了用戶內存,然后返回。

所以,nonblocking IO的特點是用戶進程需要不斷的主動詢問kernel數據好了沒有。

同步非阻塞方式相比同步阻塞方式:

優點:

能夠在等待任務完成的時間里干其他活了(包括提交其他任務,也就是 “后臺” 可以有多個任務在同時執行)。

缺點:

任務完成的響應延遲增大了,因為每過一段時間才去輪詢一次read操作,而任務可能在兩次輪詢之間的任意時間完成。這會導致整體數據吞吐量的降低。

IO多路復用

I/O是指網絡I/O,多路指多個TCP連接(即socket或者channel),復用指復用一個或幾個線程。意思說一個或一組線程處理多個連接。比如課堂上學生做完了作業就舉手,老師就下去檢查作業。(對一個IO端口,兩次調用,兩次返回,比阻塞IO并沒有什么優越性;關鍵是能實現同時對多個IO端口進行監聽,可以同時對多個讀/寫操作的IO函數進行輪詢檢測,直到有數據可讀或可寫時,才真正調用IO操作函數。)

 

IO多路復用程序流

這種模型其實和BIO是一模一樣的,都是阻塞的,只不過在socket上加了一層代理select,select可以通過監控多個socekt是否有數據,通過這種方式來提高性能。

一旦檢測到一個或多個文件描述有數據到來,select函數就返回,這時再調用recv函數(這塊也是阻塞的),數據從內核空間拷貝到用戶空間,recv函數返回。

多路復用的特點是通過一種機制一個進程能同時等待IO文件描述符,內核監視這些文件描述符(套接字描述符),其中的任意一個進入讀就緒狀態,select, poll,epoll函數就可以返回。對于監視的方式,又可以分為 select, poll, epoll三種方式。

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

在I/O編程過程中,當需要同時處理多個客戶端接入請求時,可以利用多線程或者I/O多路復用技術進行處理。I/O多路復用技術通過把多個I/O的阻塞復用到同一個select的阻塞上,從而使得系統在單線程的情況下可以同時處理多個客戶端請求。與傳統的多線程/多進程模型比,I/O多路復用的最大優勢是系統開銷小,系統不需要創建新的額外進程或者線程,也不需要維護這些進程和線程的運行,降底了系統的維護工作量,節省了系統資源,I/O多路復用的主要應用場景如下:

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

2. 服務器需要同時處理多種網絡協議的套接字。

在用戶進程進行系統調用的時候,他們在等待數據到來的時候,處理的方式不一樣,直接等待,輪詢,select或poll輪詢,兩個階段過程:

第一個階段有的阻塞,有的不阻塞,有的可以阻塞又可以不阻塞。

第二個階段都是阻塞的。

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

信號驅動IO

 

信號驅動IO程序流

在用戶態程序安裝SIGIO信號處理函數(用sigaction函數或者signal函數來安裝自定義的信號處理函數),即recv函數。然后用戶態程序可以執行其他操作不會被阻塞。

一旦有數據到來,操作系統以信號的方式來通知用戶態程序,用戶態程序跳轉到自定義的信號處理函數。

在信號處理函數中調用recv函數,接收數據。數據從內核空間拷貝到用戶態空間后,recv函數返回。recv函數不會因為等待數據到來而阻塞。

這種方式使異步處理成為可能,信號是異步處理的基礎。

在 Linux 中,通知的方式是信號:

如果這個進程正在用戶態忙著做別的事,那就強行打斷之,調用事先注冊的信號處理函數,這個函數可以決定何時以及如何處理這個異步任務。由于信號處理函數是突然闖進來的,因此跟中斷處理程序一樣,有很多事情是不能做的,因此保險起見,一般是把事件 “登記” 一下放進隊列,然后返回該進程原來在做的事。

如果這個進程正在內核態忙著做別的事,例如以同步阻塞方式讀寫磁盤,那就只好把這個通知掛起來了,等到內核態的事情忙完了,快要回到用戶態的時候,再觸發信號通知。

如果這個進程現在被掛起了,例如無事可做 sleep 了,那就把這個進程喚醒,下次有 CPU 空閑的時候,就會調度到這個進程,觸發信號通知。

異步 API 說來輕巧,做來難,這主要是對 API 的實現者而言的。Linux 的異步 IO(AIO)支持是 2.6.22 才引入的,還有很多系統調用不支持異步 IO。Linux 的異步 IO 最初是為數據庫設計的,因此通過異步 IO 的讀寫操作不會被緩存或緩沖,這就無法利用操作系統的緩存與緩沖機制。

很多人把 Linux 的 O_NONBLOCK 認為是異步方式,但事實上這是前面講的同步非阻塞方式。需要指出的是,雖然 Linux 上的 IO API 略顯粗糙,但每種編程框架都有封裝好的異步 IO 實現。操作系統少做事,把更多的自由留給用戶,正是 UNIX 的設計哲學,也是 Linux 上編程框架百花齊放的一個原因。

異步IO

 

異步IO程序流

異步IO的效率是最高的。

異步IO通過aio_read函數實現,aio_read提交請求,并遞交一個用戶態空間下的緩沖區。即使內核中沒有數據到來,aio_read函數也立刻返回,應用程序就可以處理其他的事情。

當數據到來后,操作系統自動把數據從內核空間拷貝到aio_read函數遞交的用戶態緩沖區。拷貝完成以信號的方式通知用戶態程序,用戶態程序拿到數據后就可以執行后續操作。

異步IO和信號驅動IO的不同?

在于信號通知用戶態程序時數據所處的位置。異步IO已經把數據從內核空間拷貝到用戶空間了;而信號驅動IO的數據還在內核空間,等著recv函數把數據拷貝到用戶態空間。

異步IO主動把數據拷貝到用戶態空間,主動推送數據到用戶態空間,不需要調用recv方法把數據從內核空間拉取到用戶態空間。異步IO是一種推數據的機制,相比于信號處理IO拉數據的機制效率更高。

 

推數據是直接完成的,而拉數據是需要調用recv函數,調用函數會產生額外的開銷,故效率低。

本文轉載自微信公眾號「一口Linux」,可以通過以下二維碼關注。轉載本文請聯系一口Linux公眾號。

 

責任編輯:武曉燕 來源: 一口Linux
相關推薦

2021-04-12 12:00:13

Linux運維Linux系統

2020-09-04 10:14:02

Linux驅動7內核

2021-02-04 11:53:49

Linuxplatform總線

2011-01-10 14:41:26

2022-09-14 17:12:15

flowable源碼DEMO

2009-11-06 10:44:31

Visual Stud

2020-11-10 09:00:00

JavaMule ESB開發

2010-04-02 16:51:09

虛擬機安裝linux

2009-12-11 09:04:10

Windows搭建Li

2022-01-17 07:50:37

Linux Patch項目

2021-09-18 14:26:49

Linux Linux 啟動流程Linux 系統

2009-10-21 10:47:03

Siliverligh

2010-07-07 10:24:46

Python多線程

2010-08-18 09:15:45

路由器網絡診斷

2020-06-01 16:25:43

WindowsLinux命令

2009-06-15 16:58:57

Java安裝Linux

2009-12-21 11:36:24

Linux啟動加密

2016-04-27 09:49:16

用戶模型產品總結

2018-10-10 15:14:20

Linux虛擬機配置

2020-09-23 07:00:00

Selenium We架構
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产欧美精品一区二区三区 | 国产精品日产欧美久久久久 | 国产乱码精品一区二区三区忘忧草 | 午夜av电影院 | 亚洲第一av| 日韩三级免费观看 | 羞羞网站免费 | 91久久精品一区二区二区 | 久久国产成人 | 久久久婷| 国产精品久久久久久久久久久久冷 | 成人av一区 | 99精品在线免费观看 | 精品在线视频播放 | 欧美天堂在线 | 毛片一区 | 日韩中文字幕区 | 一级高清免费毛片 | 国产一区不卡 | 国产在线资源 | 亚州毛片 | 亚洲成人一区 | 精品久久久久久国产 | 在线观看不卡av | 国产成人高清成人av片在线看 | 福利社午夜影院 | 国内自拍偷拍视频 | av片在线播放 | 欧美大片一区 | 欧美激情亚洲天堂 | 国产电影一区二区三区爱妃记 | 四虎海外 | 久久久久久久久综合 | 国产欧美日韩视频 | 国产精品久久久乱弄 | 男人天堂午夜 | 国产精品久久国产精品久久 | 亚州成人 | 亚洲免费一区二区 | 四虎首页 | 欧美一区二区三区日韩 |