久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

這是一份很全很全的IO基礎(chǔ)知識與概念(應(yīng)用程序不能直接操作內(nèi)核空間需要將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間才能使用無論是read操作還是write操作都只能在內(nèi)核空間里執(zhí)行)

 山峰云繞 2022-02-16

什么是 IO


  (應(yīng)用程序不能直接操作內(nèi)核空間需要將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間才能使用無論是read操作還是write操作都只能在內(nèi)核空間里執(zhí)行)

在計算機操作系統(tǒng)中,,所謂的I/O就是 輸入(Input)和輸出(Output),,也可以理解為讀(Read)和寫(Write),針對不同的對象,,I/O模式可以劃分為磁盤IO模型和網(wǎng)絡(luò)IO模型,。

IO操作會涉及到用戶空間內(nèi)核空間的轉(zhuǎn)換,先來理解以下規(guī)則:

  • 內(nèi)存空間分為用戶空間和內(nèi)核空間,,也稱為用戶緩沖區(qū)和內(nèi)核緩沖區(qū),;

  • 用戶的應(yīng)用程序不能直接操作內(nèi)核空間,需要將數(shù)據(jù)從內(nèi)核空間拷貝到用戶空間才能使用,;

  • 無論是read操作,,還是write操作,都只能在內(nèi)核空間里執(zhí)行,;

  • 磁盤IO和網(wǎng)絡(luò)IO請求加載到內(nèi)存的數(shù)據(jù)都是先放在內(nèi)核空間的,;

再來看看所謂的讀(Read)和寫(Write)操作:

  • 讀操作:操作系統(tǒng)檢查內(nèi)核緩沖區(qū)有沒有需要的數(shù)據(jù),如果內(nèi)核緩沖區(qū)已經(jīng)有需要的數(shù)據(jù)了,,那么就直接把內(nèi)核空間的數(shù)據(jù)copy到用戶空間,,供用戶的應(yīng)用程序使用,。如果內(nèi)核緩沖區(qū)沒有需要的數(shù)據(jù),對于磁盤IO,,直接從磁盤中讀取到內(nèi)核緩沖區(qū)(這個過程可以不需要cpu參與),。而對于網(wǎng)絡(luò)IO,應(yīng)用程序需要等待客戶端發(fā)送數(shù)據(jù),,如果客戶端還沒有發(fā)送數(shù)據(jù),,對應(yīng)的應(yīng)用程序?qū)蛔枞钡娇蛻舳税l(fā)送了數(shù)據(jù),,該應(yīng)用程序才會被喚醒,,從Socket協(xié)議找中讀取客戶端發(fā)送的數(shù)據(jù)到內(nèi)核空間,然后把內(nèi)核空間的數(shù)據(jù)copy到用戶空間,,供應(yīng)用程序使用,。

  • 寫操作:用戶的應(yīng)用程序?qū)?shù)據(jù)從用戶空間copy到內(nèi)核空間的緩沖區(qū)中(如果用戶空間沒有相應(yīng)的數(shù)據(jù),則需要從磁盤—>內(nèi)核緩沖區(qū)—>用戶緩沖區(qū)依次讀?。?,這時對用戶程序來說寫操作就已經(jīng)完成,至于什么時候再寫到磁盤或通過網(wǎng)絡(luò)發(fā)送出去,,由操作系統(tǒng)決定,。除非應(yīng)用程序顯示地調(diào)用了sync 命令,立即把數(shù)據(jù)寫入磁盤,,或執(zhí)行flush()方法,,通過網(wǎng)絡(luò)把數(shù)據(jù)發(fā)送出去。

  • 絕大多數(shù)磁盤IO和網(wǎng)絡(luò)IO的讀寫操作都是上述過程,,除了后面要講到的零拷貝IO,。

用戶空間&內(nèi)核空間

野生程序員對于這個概念可能比較陌生,這其實是 Linux 操作系統(tǒng)中的概念,。虛擬內(nèi)存(操作系統(tǒng)中的概念,,和物理內(nèi)存是對應(yīng)的)被操作系統(tǒng)劃分成兩塊:User Space(用戶空間Kernel Space(內(nèi)核空間),本質(zhì)上電腦的物理內(nèi)存是不劃分這些的,,只是操作系統(tǒng)開機啟動后在邏輯上虛擬劃分了地址和空間范圍,。

操作系統(tǒng)會給每個進(jìn)程分配一個獨立的、連續(xù)的虛擬內(nèi)存地址空間(物理上可能不連續(xù)),,以32位操作系統(tǒng)為例,,該大小一般是4G,即232 ,。其中將高地址值的內(nèi)存空間分配給系統(tǒng)內(nèi)核占用(網(wǎng)上查資料得知:Linux下占1G,,Windows下占2G),其余的內(nèi)存地址空間分配給用戶進(jìn)程使用,。

因為我們不是要深入學(xué)習(xí)操作系統(tǒng),,所以這里以32位系統(tǒng)舉例旨在幫助你理解原理。32 位的 LInux 操作系統(tǒng)下,,0~3G為用戶空間,,3~4G為內(nèi)核空間

這是一份很全很全的 IO 基礎(chǔ)知識與概念

那為什么要這樣劃分出空間范圍呢?

也很好理解,,畢竟操作系統(tǒng)身份高貴,,太重要了,不能和用戶應(yīng)用程序在一起玩耍,,各自的數(shù)據(jù)都要分開存儲并且嚴(yán)格控制權(quán)限不能越界,。這樣才能保證操作系統(tǒng)的穩(wěn)定運行,用戶應(yīng)用程序太不可控了,,不同公司或者個人都可以開發(fā),,碰到坑爹的誤操作或者惡意破壞系統(tǒng)數(shù)據(jù)直接宕機玩完了。隔離后應(yīng)用程序要掛你就掛,,操作系統(tǒng)可以正常運行,。

簡單說,內(nèi)核空間 是操作系統(tǒng) 內(nèi)核代碼運行的地方,,用戶空間用戶程序代碼運行的地方,。當(dāng)應(yīng)用進(jìn)程執(zhí)行系統(tǒng)調(diào)用陷入內(nèi)核代碼中執(zhí)行時就處于內(nèi)核態(tài),當(dāng)應(yīng)用進(jìn)程在運行用戶代碼時就處于用戶態(tài),。

同時內(nèi)核空間可以執(zhí)行任意的命令,,而用戶空間只能執(zhí)行簡單的運算,不能直接調(diào)用系統(tǒng)資源和數(shù)據(jù),。必須通過操作系統(tǒng)提供接口,,向系統(tǒng)內(nèi)核發(fā)送指令。

一旦調(diào)用系統(tǒng)接口,,應(yīng)用進(jìn)程就從用戶空間切換到內(nèi)核空間了,,因為開始運行內(nèi)核代碼了。

簡單看幾行代碼,,分析下是應(yīng)用程序在用戶空間和內(nèi)核空間之間的切換過程:

str = "i am qige" // 用戶空間
x = x + 2
file.write(str) // 切換到內(nèi)核空間
y = x + 4 // 切換回用戶空間

上面代碼中,,第一行和第二行都是簡單的賦值運算,在用戶空間執(zhí)行,。第三行需要寫入文件,,就要切換到內(nèi)核空間,因為用戶不能直接寫文件,,必須通過內(nèi)核安排,。第四行又是賦值運算,就切換回用戶空間,。

用戶態(tài)切換到內(nèi)核態(tài)的3種方式:

  • 系統(tǒng)調(diào)用,。也稱為 System Call,,是說用戶態(tài)進(jìn)程主動要求切換到內(nèi)核態(tài)的一種方式,用戶態(tài)進(jìn)程使用操作系統(tǒng)提供的服務(wù)程序完成工作,,比如上面示例代碼中的寫文件調(diào)用,,還有像 fork() 函數(shù)實際上就是執(zhí)行了一個創(chuàng)建新進(jìn)程的系統(tǒng)調(diào)用。而系統(tǒng)調(diào)用的機制其核心還是使用了操作系統(tǒng)為用戶特別開放的一個中斷來實現(xiàn),。

  • 異常,。當(dāng)CPU在用戶空間執(zhí)行程序代碼時發(fā)生了不可預(yù)期的異常,這時會觸發(fā)由當(dāng)前運行進(jìn)程切換到處理此異常的內(nèi)核相關(guān)程序中,,切換到內(nèi)核態(tài),,比如缺頁異常。

  • 外圍設(shè)備的中斷,。 當(dāng)外圍設(shè)備完成用戶請求的某些操作后,,會向CPU發(fā)送相應(yīng)的中斷信號,這時CPU會暫停執(zhí)行下一條即將執(zhí)行的指令轉(zhuǎn)而去執(zhí)行與中斷信號對應(yīng)的處理程序,,如果當(dāng)前正在運行用戶態(tài)下的程序指令,,自然就發(fā)了由用戶態(tài)到內(nèi)核態(tài)的切換。比如硬盤數(shù)據(jù)讀寫完成,,系統(tǒng)會切換到中斷處理程序中執(zhí)行后續(xù)操作等,。

以上3種方式,除了系統(tǒng)調(diào)用是進(jìn)程主動發(fā)起切換,,異常和外圍設(shè)備中斷是被動切換的,。

查看 CPU 時間在 User SpaceKernel Space 之間的分配情況,可以使用top命令,。它的第三行輸出就是 CPU 時間分配統(tǒng)計,。

這是一份很全很全的 IO 基礎(chǔ)知識與概念

我們來看看圖中圈出來的 CPU 使用率的三個指標(biāo):

其中,第一項 7.57% user 就是 CPU 消耗在 User Space 的時間百分比,,第二項 7.0% sys是消耗在 Kernel Space 的時間百分比,。第三項 85.4% idle 是 CPU 消耗在閑置進(jìn)程的時間百分比,這個值越低,,表示 CPU 越忙,。

PIO&DMA

大家都知道一般我們的數(shù)據(jù)是存儲在磁盤上的,應(yīng)用程序想要讀寫這些數(shù)據(jù)肯定就需要加載到內(nèi)存中,。接下來給大家介紹下 PIODMA 這兩種 IO 設(shè)備和內(nèi)存之間的數(shù)據(jù)傳輸方式,。

PIO 工作原理

這是一份很全很全的 IO 基礎(chǔ)知識與概念
  1. 用戶進(jìn)程通過read等系統(tǒng)調(diào)用接口向操作系統(tǒng)(即CPU)發(fā)出IO請求,請求讀取數(shù)據(jù)到自己的用戶內(nèi)存緩沖區(qū)中,,然后該進(jìn)程進(jìn)入阻塞狀態(tài),。

  2. 操作系統(tǒng)收到用戶進(jìn)程的請求后,進(jìn)一步將IO請求發(fā)送給磁盤。

  3. 磁盤驅(qū)動器收到內(nèi)核的IO請求后,,把數(shù)據(jù)讀取到自己的緩沖區(qū)中,,此時不占用CPU。當(dāng)磁盤的緩沖區(qū)被讀滿之后,,向內(nèi)核發(fā)起中斷信號告知自己緩沖區(qū)已滿,。

  4. 內(nèi)核收到磁盤發(fā)來的中斷信號,使用CPU將磁盤緩沖區(qū)中的數(shù)據(jù)copy到內(nèi)核緩沖區(qū)中,。

  5. 如果內(nèi)核緩沖區(qū)的數(shù)據(jù)少于用戶申請讀的數(shù)據(jù),,則重復(fù)步驟2,、3,、4,直到內(nèi)核緩沖區(qū)的數(shù)據(jù)符合用戶的要求為止,。

  6. 內(nèi)核緩沖區(qū)的數(shù)據(jù)已經(jīng)符合用戶的要求,,CPU停止向磁盤IO請求。

  7. CPU將數(shù)據(jù)從內(nèi)核緩沖區(qū)拷貝到用戶緩沖區(qū),,同時從系統(tǒng)調(diào)用中返回,。

  8. 用戶進(jìn)程讀取到數(shù)據(jù)后繼續(xù)執(zhí)行原來的任務(wù)。

PIO缺點:每次IO請求都需要CPU多次參與,,效率很低,。

DMA 工作原理

DMA(直接內(nèi)存訪問,Direct Memory Access),。

這是一份很全很全的 IO 基礎(chǔ)知識與概念
  1. 用戶進(jìn)程通過read等系統(tǒng)調(diào)用接口向操作系統(tǒng)(即CPU)發(fā)出IO請求,,請求讀取數(shù)據(jù)到自己的用戶內(nèi)存緩沖區(qū)中,然后該進(jìn)程進(jìn)入阻塞狀態(tài),。

  2. 操作系統(tǒng)收到用戶進(jìn)程的請求后,,進(jìn)一步將IO請求發(fā)送給DMA,然后CPU就可以去干別的事了,。

  3. DMA將IO請求轉(zhuǎn)發(fā)給磁盤,。

  4. 磁盤驅(qū)動器收到內(nèi)核的IO請求后,把數(shù)據(jù)讀取到自己的緩沖區(qū)中,,當(dāng)磁盤的緩沖區(qū)被讀滿后,,向DMA發(fā)起中斷信號告知自己緩沖區(qū)已滿。

  5. DMA收到磁盤驅(qū)動器的信號,,將磁盤緩沖區(qū)中的數(shù)據(jù)copy到內(nèi)核緩沖區(qū)中,,此時不占用CPU( PIO 這里是占用CPU的)。

  6. 如果內(nèi)核緩沖區(qū)的數(shù)據(jù)少于用戶申請讀的數(shù)據(jù),,則重復(fù)步驟3,、4、5,直到內(nèi)核緩沖區(qū)的數(shù)據(jù)符合用戶的要求為止,。

  7. 內(nèi)核緩沖區(qū)的數(shù)據(jù)已經(jīng)符合用戶的要求,,DMA停止向磁盤發(fā)IO請求。

  8. DMA發(fā)送中斷信號給CPU,。

  9. CPU收到DMA的信號,,知道數(shù)據(jù)已經(jīng)準(zhǔn)備好,于是將數(shù)據(jù)從內(nèi)核空間copy到用戶空間,,系統(tǒng)調(diào)用返回,。

  10. 用戶進(jìn)程讀取到數(shù)據(jù)后繼續(xù)執(zhí)行原來的任務(wù)。

PIO模式相比,,DMA就是CPU的一個代理,,它負(fù)責(zé)了一部分的拷貝工作,從而減輕了CPU的負(fù)擔(dān),。

需要注意的是,,DMA承擔(dān)的工作是從磁盤的緩沖區(qū)到內(nèi)核緩沖區(qū)或網(wǎng)卡設(shè)備到內(nèi)核的 soket buffer的拷貝工作,以及內(nèi)核緩沖區(qū)到磁盤緩沖區(qū)或內(nèi)核的 soket buffer 到網(wǎng)卡設(shè)備的拷貝工作,,而內(nèi)核緩沖區(qū)到用戶緩沖區(qū)之間的拷貝工作仍然由CPU負(fù)責(zé),。

可以肯定的是,PIO模式的計算機我們現(xiàn)在已經(jīng)很少見到了,。

緩沖IO和直接IO

學(xué)習(xí)用戶空間和內(nèi)核空間的時候我們也說了,,用戶空間是不能直接訪問內(nèi)核空間的數(shù)據(jù)的,如果需要訪問怎么辦,?很簡單,,就需要將數(shù)據(jù)從內(nèi)核空間拷貝的用戶空間。

  • 緩沖 IO:其實就是磁盤中的數(shù)據(jù)通過 DMA 先拷貝到內(nèi)核空間,,然后再從內(nèi)核空間拷貝到用戶空間,。

  • 直接 IO:磁盤中的數(shù)據(jù)直接通過 DMA 拷貝到用戶空間。

緩沖 IO

緩沖 IO 也被成為標(biāo)準(zhǔn) IO,,大多數(shù)的文件系統(tǒng)系統(tǒng)默認(rèn)都是以緩沖 IO 的方式來工作的,。在Linux的緩沖I/O機制中,數(shù)據(jù)先從磁盤復(fù)制到內(nèi)核空間的緩沖區(qū),,然后從內(nèi)核空間緩沖區(qū)復(fù)制到應(yīng)用程序的地址空間,。

接下來我們看看緩沖 IO 下讀寫操作是如何進(jìn)行?

  • 讀操作:

操作系統(tǒng)檢查內(nèi)核的緩沖區(qū)有沒有需要的數(shù)據(jù),,如果已經(jīng)緩沖了,,那么就直接從緩沖中返回;否則從磁盤中讀取到內(nèi)核緩沖中,,然后再復(fù)制到用戶空間緩沖中,。

  • 寫操作:

將數(shù)據(jù)從用戶空間復(fù)制到內(nèi)核空間的緩沖中,。這時對用戶程序來說寫操作就已經(jīng)完成,至于什么時候再寫到磁盤中由操作系統(tǒng)決定,,除非顯示地調(diào)用了sync同步命令,。

緩沖I/O的優(yōu)點:

  1. 在一定程度上分離了內(nèi)核空間和用戶空間,保護(hù)系統(tǒng)本身的運行安全,;

  2. 因為內(nèi)核中有緩沖,,可以減少讀盤的次數(shù),從而提高性能,。

緩沖I/O的缺點:

在緩沖 I/O 機制中,,DMA 方式可以將數(shù)據(jù)直接從磁盤讀到內(nèi)核空間頁緩沖中,或者將數(shù)據(jù)從內(nèi)核空間頁緩沖直接寫回到磁盤上,,而不能直接在用戶地址空間和磁盤之間進(jìn)行數(shù)據(jù)傳輸,,這樣數(shù)據(jù)在傳輸過程中需要在應(yīng)用程序地址空間(用戶空間)和內(nèi)核緩沖(內(nèi)核空間)之間進(jìn)行多次數(shù)據(jù)拷貝操作,這些數(shù)據(jù)拷貝操作所帶來的CPU以及內(nèi)存開銷是非常大的,。

直接IO

顧名思義,,直接IO就是應(yīng)用程序直接訪問磁盤數(shù)據(jù),,而不經(jīng)過內(nèi)核緩沖區(qū),,也就是繞過內(nèi)核緩沖區(qū),自己管理I/O緩沖區(qū),這樣做的目的是減少一次從內(nèi)核緩沖區(qū)到用戶程序緩沖的數(shù)據(jù)復(fù)制,。

這是一份很全很全的 IO 基礎(chǔ)知識與概念

引入內(nèi)核緩沖區(qū)這個主要是為了提升從磁盤讀寫數(shù)據(jù)文件的性能,,這也是很多系統(tǒng)優(yōu)化中常見的手段,多一層緩存可以有效減少很多磁盤 IO 操作,;而當(dāng)用戶程序需要向磁盤文件中寫入數(shù)據(jù)時,,實際上只需要寫入到內(nèi)核緩沖區(qū)便可以返回了,而真正的落盤是有一定的延遲策略的,,但這無疑提升了應(yīng)用程序?qū)懭胛募捻憫?yīng)速度,。

在數(shù)據(jù)庫管理系統(tǒng)這類應(yīng)用中,它們更傾向于選擇自己實現(xiàn)的緩存機制,,因為數(shù)據(jù)庫管理系統(tǒng)往往比操作系統(tǒng)更了解數(shù)據(jù)庫中存放的數(shù)據(jù),,數(shù)據(jù)庫管理系統(tǒng)可以提供一種更加有效的緩存機制來提高數(shù)據(jù)庫中數(shù)據(jù)的存取性能。

直接I/O的優(yōu)點:

應(yīng)用程序直接訪問磁盤數(shù)據(jù),,不經(jīng)過操作系統(tǒng)內(nèi)核數(shù)據(jù)緩沖區(qū),,這樣做的最直觀目的是減少一次從內(nèi)核緩沖區(qū)到用戶程序緩沖的數(shù)據(jù)復(fù)制。這種方式通常用在數(shù)據(jù)庫,、消息中間件中,,由應(yīng)用程序來實現(xiàn)數(shù)據(jù)的緩存管理。

直接I/O的缺點:

如果訪問的數(shù)據(jù)不在應(yīng)用程序緩沖中,,那么每次數(shù)據(jù)都會直接從磁盤進(jìn)行加載,,這種直接加載會非常緩慢。通常 直接I/O異步I/O 結(jié)合使用會得到較好的性能。(異步IO:當(dāng)訪問數(shù)據(jù)的線程發(fā)出請求之后,,線程會接著去處理其他事,,而不是阻塞等待)

IO 訪問方式

我們常說的 IO 操作,不僅僅是磁盤 IO,,還有常見的網(wǎng)絡(luò)數(shù)據(jù)傳輸即網(wǎng)絡(luò) IO,。

磁盤 IO

這是一份很全很全的 IO 基礎(chǔ)知識與概念

讀操作:

當(dāng)應(yīng)用程序調(diào)用read()方法時,操作系統(tǒng)檢查內(nèi)核高速緩沖區(qū)中是否存在需要的數(shù)據(jù),,如果存在,,那么就直接把內(nèi)核空間的數(shù)據(jù)copy到用戶空間,供用戶的應(yīng)用程序使用,。如果內(nèi)核緩沖區(qū)沒有需要的數(shù)據(jù),,通過通過DMA方式從磁盤中讀取數(shù)據(jù)到內(nèi)核緩沖區(qū),然后由CPU控制,,把內(nèi)核空間的數(shù)據(jù)copy到用戶空間,。

這個過程會涉及到兩次緩沖區(qū)copy,第一次是從磁盤到內(nèi)核緩沖區(qū),,第二次是從內(nèi)核緩沖區(qū)到用戶緩沖區(qū),,第一次是DMA的copy,第二次是CPU的copy,。

寫操作:

當(dāng)應(yīng)用程序調(diào)用write()方法時,,應(yīng)用程序?qū)?shù)據(jù)從用戶空間copy到內(nèi)核空間的緩沖區(qū)中(如果用戶空間沒有相應(yīng)的數(shù)據(jù),則需要從磁盤—>內(nèi)核緩沖區(qū)—>用戶緩沖區(qū)),,這時對用戶程序來說寫操作就已經(jīng)完成,,至于什么時候把數(shù)據(jù)再寫到磁盤(從內(nèi)核緩沖區(qū)到磁盤的寫操作也由DMA控制,不需要cpu參與),,由操作系統(tǒng)決定,。除非應(yīng)用程序顯示地調(diào)用了sync命令,立即把數(shù)據(jù)寫入磁盤,。

如果應(yīng)用程序沒準(zhǔn)備好寫的數(shù)據(jù),,則必須先從磁盤讀取數(shù)據(jù)才能執(zhí)行寫操作,這時會涉及到四次緩沖區(qū)的copy,,第一次是從磁盤的緩沖區(qū)到內(nèi)核緩沖區(qū),,第二次是從內(nèi)核緩沖區(qū)到用戶緩沖區(qū),第三次是從用戶緩沖區(qū)到內(nèi)核緩沖區(qū),,第四次是從內(nèi)核緩沖區(qū)寫回到磁盤,。前兩次是為了讀,后兩次是為了寫,。這其中有兩次 CPU 拷貝,,兩次DMA拷貝。

磁盤IO的延時:

為了讀或?qū)?,磁頭必須能移動到所指定的磁道上,,并等待所指定的扇區(qū)的開始位置旋轉(zhuǎn)到磁頭下,,然后再開始讀或?qū)憯?shù)據(jù)。磁盤IO的延時分成以下三部分:

  • 尋道時間:把磁頭移動到指定磁道上所經(jīng)歷的時間;

  • 旋轉(zhuǎn)延遲時間 :指定扇區(qū)移動到磁頭下面所經(jīng)歷的時間;

  • 傳輸時間 :數(shù)據(jù)的傳輸時間(數(shù)據(jù)讀出或?qū)懭氲臅r間),;

網(wǎng)絡(luò) IO

這是一份很全很全的 IO 基礎(chǔ)知識與概念

讀操作:

網(wǎng)絡(luò) IO 既可以從物理磁盤中讀數(shù)據(jù),也可以從Socket中讀數(shù)據(jù)(從網(wǎng)卡中獲?。?。當(dāng)從物理磁盤中讀數(shù)據(jù)的時候,其流程和磁盤IO的讀操作一樣,。當(dāng)從Socket中讀數(shù)據(jù),,應(yīng)用程序需要等待客戶端發(fā)送數(shù)據(jù),如果客戶端還沒有發(fā)送數(shù)據(jù),,對應(yīng)的應(yīng)用程序?qū)蛔枞?,直到客戶端發(fā)送了數(shù)據(jù),該應(yīng)用程序才會被喚醒,,從Socket協(xié)議棧(網(wǎng)卡)中讀取客戶端發(fā)送的數(shù)據(jù)到內(nèi)核空間(這個過程也由DMA控制),,然后把內(nèi)核空間的數(shù)據(jù) copy 到用戶空間,供應(yīng)用程序使用,。

寫操作:

為了簡化描述,,我們假設(shè)網(wǎng)絡(luò)IO的數(shù)據(jù)從磁盤中獲取,,讀寫操作的流程如下:

  • 當(dāng)應(yīng)用程序調(diào)用read()方法時,,通過DMA方式將數(shù)據(jù)從磁盤拷貝到內(nèi)核緩沖區(qū);

  • 由cpu控制,,將內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到用戶空間的緩沖區(qū)中,,供應(yīng)用程序使用;

  • 當(dāng)應(yīng)用程序調(diào)用 write() 方法時,,CPU 會把用戶緩沖區(qū)中的數(shù)據(jù) copy 到內(nèi)核緩沖區(qū)的 Socket Buffer 中,;

  • 最后通過DMA方式將內(nèi)核空間中的Socket Buffer拷貝到Socket協(xié)議棧(即網(wǎng)卡設(shè)備)中傳輸;

網(wǎng)絡(luò)IO 的寫操作也有四次緩沖區(qū)的copy,,第一次是從磁盤緩沖區(qū)到內(nèi)核緩沖區(qū)(由DMA控制),,第二次是內(nèi)核緩沖區(qū)到用戶緩沖區(qū)(CPU控制),第三次是用戶緩沖區(qū)到內(nèi)核緩沖區(qū)的 Socket Buffer(由CPU控制),,第四次是從內(nèi)核緩沖區(qū)的 Socket Buffer 到網(wǎng)卡設(shè)備(由DMA控制),。四次緩沖區(qū)的copy工作兩次由CPU控制,兩次由DMA控制,。

網(wǎng)絡(luò)IO的延時:

網(wǎng)絡(luò)IO主要延時是由:服務(wù)器響應(yīng)延時+帶寬限制+網(wǎng)絡(luò)延時+跳轉(zhuǎn)路由延時+本地接收延時 決定,。一般為幾十到幾千毫秒,,受環(huán)境影響較大。所以,,一般來說,,網(wǎng)絡(luò)IO延時要大于磁盤IO延時(不過同數(shù)據(jù)中心的交互除外,會比磁盤 IO 更快),。

零拷貝 IO

在上述IO中,,一次讀寫操作要經(jīng)過四次緩沖區(qū)的拷貝,并經(jīng)歷了四次內(nèi)核態(tài)和用戶態(tài)的切換,。 零拷貝(zero copy)IO 技術(shù)減少不必要的內(nèi)核緩沖區(qū)跟用戶緩沖區(qū)之間的拷貝,,從而減少CPU的開銷和狀態(tài)切換帶來的開銷,達(dá)到性能的提升,。

我們還是對比上面不使用零拷貝時的網(wǎng)絡(luò) IO 傳輸過程來對比分析下:

這是一份很全很全的 IO 基礎(chǔ)知識與概念

和上圖普通的網(wǎng)絡(luò) IO 傳輸過程對比,,零拷貝的傳輸過程:硬盤 -> kernel buffer (快速拷貝到kernel socket buffer) -> Socket協(xié)議棧(網(wǎng)卡設(shè)備中)。

  • 當(dāng)應(yīng)用程序調(diào)用read()方法時,,通過DMA方式將數(shù)據(jù)從磁盤拷貝到內(nèi)核緩沖區(qū),;

  • CPU控制,將內(nèi)核緩沖區(qū)的數(shù)據(jù)直接拷貝到另外一個與 Socket 相關(guān)的內(nèi)核緩沖區(qū),,即kernel socket buffer,;

  • 然后由 DMA 把數(shù)據(jù)從 kernel socket buffer 直接拷貝給 Socket 協(xié)議棧(網(wǎng)卡設(shè)備中);

這里,,只經(jīng)歷了三次緩沖區(qū)的拷貝,,第一次是從磁盤緩沖區(qū)到內(nèi)核緩沖區(qū),第二次是從內(nèi)核緩沖區(qū)到 kernel socket buffer,,第三次是從 kernel socket bufferSocket 協(xié)議棧(網(wǎng)卡設(shè)備中),。只發(fā)生兩次內(nèi)核態(tài)和用戶態(tài)的切換,第一次是當(dāng)應(yīng)用程序調(diào)用read方法時,,用戶態(tài)切換到內(nèi)核態(tài)執(zhí)行read系統(tǒng)調(diào)用,,第二次是將數(shù)據(jù)從網(wǎng)絡(luò)中發(fā)送出去后系統(tǒng)調(diào)用返回,從內(nèi)核態(tài)切換到用戶態(tài),。

零拷貝(zero copy)的應(yīng)用:

  • Linux 下提供了zero copy的接口:sendfilesplice,,用戶可通過這兩個接口實現(xiàn)零拷貝傳輸;

  • Nginx 可以通過sendfile配置開啟零拷貝,;

  • 在 Linux 系統(tǒng)中,,Java NIO中 FileChannel.transferTo 的實現(xiàn)依賴于 sendfile()調(diào)用;

  • Apache 使用了 sendfile64() 來傳送文件,,sendfile64() 是 sendfile() 的擴(kuò)展實現(xiàn),;

  • Kafka也用到了零拷貝的功能;

注意:零拷貝要求輸入的fd必須是文件句柄,,不能是socket,,輸出的fd必須是socket,,也就是說,數(shù)據(jù)的來源必須是從本地的磁盤,,而不能是從網(wǎng)絡(luò)中,,如果數(shù)據(jù)來源于socket,就不能使用零拷貝功能了,。我們看一下sendfile接口就知道了:

#include <sys/sendfile.h>
ssize_t sendfile(int out_fd, int in_fd, off_t *offset, size_t count)
  • out_fd:待寫入文件描述符;

  • in_fd:待讀出文件描述符;

  • offset:從讀入文件流的哪個位置開始讀,,如果為空,則默認(rèn)從起始位置開始,;

  • count:指定在文件描述符in_fdout_fd之間傳輸?shù)淖止?jié)數(shù),;

  • 返回值:成功時,返回出傳輸?shù)淖止?jié)數(shù),,失敗返回-1,;

in_fd 必須指向真實的文件,不能是socket和管道,;而out_fd則必須是一個socket,。由此可見,sendfile 幾乎是專門為在網(wǎng)絡(luò)上傳輸文件而設(shè)計的,。

在Linxu系統(tǒng)中,,一切皆文件,因此socket也是一個文件,,也有文件句柄(或文件描述符),。

同步&異步、阻塞&非阻塞

這兩組概念,,我接觸編程以來,,經(jīng)過聽到別人說服務(wù)端是 同步非阻塞模型 或者 異步阻塞的 IO 模型,也前后了解過幾次,,但是理解都不夠透徹,,特別是這個非阻塞和異步同步和阻塞的概念很容易懵逼,,每個人的說法都不一樣,最近我耐心看了幾篇文章,,這次我感覺我是頓悟了,,這里分享下我的理解:

同步和異步是針對應(yīng)用程序向內(nèi)核發(fā)起任務(wù)后的狀態(tài)而言的:如果發(fā)起調(diào)用后,在沒有得到結(jié)果之前,,當(dāng)前調(diào)用就不返回,,不能接著做后面的事情,一直等待就是同步,。異步就是發(fā)出調(diào)用后,,雖然不能立即得到結(jié)果,,但是可以繼續(xù)執(zhí)行后面的事情,等調(diào)用結(jié)果出來時,,會通過狀態(tài),、通知和回調(diào)來通知調(diào)用者。

舉個例子加深下理解:

  1. 在互聯(lián)網(wǎng)普及之前,,我們?nèi)メt(yī)院看病都是排隊的模式,,想看病就得排隊等,直到輪到你,,在此之前你必須一直排隊等待,,這個就是同步;

  2. 現(xiàn)在互聯(lián)網(wǎng)普及了,,都是直接大屏叫號,,我們預(yù)約登記后,就可以去休息廳坐著,,打游戲啥的都可以干,,到自己看病的時候會有通知的,這就是異步,;

阻塞blocking,、非阻塞non-blocking,則聚焦的是CPU在等待結(jié)果的過程中的狀態(tài),。

阻塞調(diào)用是指調(diào)用結(jié)果返回之前,,當(dāng)前線程會被掛起,只有在得到結(jié)果之后才會返回,。你可能會把阻塞調(diào)用和同步調(diào)用等同起來,,實際上它們是不同的,同步只是說必須等到出結(jié)果才可以返回,,但是等的過程中線程可以是激活的,,阻塞是說線程被掛起了。

非阻塞和阻塞的概念相對應(yīng),,指在不能立刻得到結(jié)果之前,,該函數(shù)不會阻塞當(dāng)前線程,而會立刻返回,。

比如前面的例子,,排隊的過程中什么也不能做就是阻塞,CPU 執(zhí)行權(quán)是交出去的,;一邊排隊,,一邊看手機就是非阻塞,CPU 執(zhí)行權(quán)還在自己手里,,但是沒看完病之前依舊是在排隊死等,,所以還是同步的,。

總結(jié)

通過今天的學(xué)習(xí),我們掌握了什么是 IO,、常見的 IO 操作類型以及對應(yīng)操作的原理,,還有非常重要但是卻很容易搞混的同步&異步、阻塞&非阻塞之間的區(qū)別,,講解的應(yīng)該還是比較清楚的,。

本文內(nèi)容還是比較簡單的,是一些基礎(chǔ)知識,,但是如果想深入學(xué)習(xí)網(wǎng)絡(luò)編程這些基礎(chǔ)是繞不開的,,了解了操作系統(tǒng)對于 IO 操作的優(yōu)化,才能搞明白各種高性能網(wǎng)絡(luò)服務(wù)器的原理,。

原文鏈接:
https://mp.weixin.qq.com/s/csgfmUs6wZ1TQr8P7IcqEg

作者:七哥聊編程

    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點,。請注意甄別內(nèi)容中的聯(lián)系方式,、誘導(dǎo)購買等信息,謹(jǐn)防詐騙,。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多