虎牙一面:內核緩沖區(qū)
接上篇,寫這倆篇文章的起因主要是最近復習計網滑動窗口中看到的一句話 “窗口的本質是內核緩沖區(qū)”,之前一直沒有仔細去理解,以為就是緩存,很多博客寫得也是緩存......,But 緩沖和緩存在概念上其實是有區(qū)別的,上篇文章已經詳細解釋過了緩沖與緩存的區(qū)別,本文就來進一步介紹內核緩沖區(qū)
內核態(tài)和用戶態(tài)
先來回顧下內核態(tài)和用戶態(tài):
眾所周知,CPU 上會運行兩種程序,一種是操作系統(tǒng)的內核程序(也稱為系統(tǒng)程序),一種是應用程序。前者完成系統(tǒng)任務,后者實現應用任務。兩者之間有控制和被控制的關系,前者有權管理和分配資源,而后者只能向系統(tǒng)申請使用資源。
顯然,我們應該把在 CPU 上運行的這兩類程序加以區(qū)分,這就是內核態(tài)和用戶態(tài)出現的原因。
內核態(tài)(kernel mode):當 CPU 處于內核態(tài)時,這是操作系統(tǒng)管理程序(也就是內核)運行時所處的狀態(tài)。運行在內核態(tài)的程序可以訪問計算機的任何資源,不受限制,為所欲為,例如協(xié)調 CPU 資源,分配內存資源,提供穩(wěn)定的環(huán)境供應用程序運行等。 用戶態(tài)(user mode):應用程序基本都是運行在用戶態(tài)的,或者說用戶態(tài)就是提供應用程序運行的空間。運行在用戶態(tài)的程序只能訪問當前 CPU 上執(zhí)行程序所在的地址空間,這樣有效地防止了操作系統(tǒng)程序受到應用程序的侵害。

對操作系統(tǒng)來說,什么樣的程序應該放在內核態(tài)呢?
這取決于對資源的需求、時間的緊迫和效率高低等因素。比如 CPU、內存、設備等資源管理器程序應該在內核態(tài)運行,否則安全性沒有保證。對于文件系統(tǒng)和數據來說,文件系統(tǒng)數據和管理必須放在內核態(tài),但是用戶的數據和管理可以放在用戶態(tài)。
應用程序如果想要訪問系統(tǒng)資源,可以通過系統(tǒng)調用 or 中斷(外中斷、內中斷)從而使得 CPU 從用戶態(tài)轉向內核態(tài)
所謂系統(tǒng)調用,其實就是一些函數,操作系統(tǒng)直接提供了這些函數用于對文件和設備進行訪問和控制。
最常見的就是 read 和 write 這倆
簡單介紹下:
read:從文件中讀取內容 write:往文件中寫入內容
內核緩沖區(qū)
根據內核態(tài)和用戶態(tài)的定義,我們不難理解內核空間和用戶空間的定義
用戶操作系統(tǒng)內核能夠訪問的內存區(qū)域呢,就稱為內核空間,它獨立于普通的應用程序,是受保護的內存空間 而普通應用程序可訪問的內存區(qū)域呢,就是用戶空間
當我們說一個應用程序從磁盤上讀取文件時,通常分兩步走:

操作系統(tǒng)(內核)先從磁盤上讀取數據存到內核空間,再把數據從內核空間拷貝到用戶空間。此后,用戶應用程序才可以操作此數據。
所以,在這個過程中有兩次數據讀取操作:
第一步:從磁盤上讀取 第二步:從內存中讀取
眾所周知,訪問磁盤的速度要遠遠低于訪問內存的速度,完全不是一個量級的,所以理論上 read 磁盤的速度要遠遠慢于 read 內存。
那么整個文件讀取過程的最大時間瓶頸就出現在了對磁盤的讀取上。
要解決這個問題,內核緩沖區(qū)(Kernel Buffer Cache)就應運而生了。
本質上其實就是內核空間的一塊內存區(qū)域罷了
從 Buffer Cache(緩沖區(qū)緩存)這個名字上能看出來,內核緩沖區(qū)(準確的說,應該是內核緩沖區(qū)緩存),其實有兩個作用,緩沖(Buffer) + 緩存(Cache)
小牛肉 PS:實話實說,各種各樣的翻譯很容易讓我們的學習曲線陡峭起來,記住
Buffer Cache比記住內核緩沖區(qū)或者用戶緩沖區(qū)這倆名詞要好得多,這倆容易讓人摸不著頭腦。
先來看看它是怎么充當 Cache 的:
? 數據預讀
數據預讀指的是,當程序發(fā)起 read() 系統(tǒng)調用時,內核會比請求更多地讀取磁盤上的數據,保存在緩沖區(qū),以備程序后續(xù)使用。這種數據的預取策略其實就是基于局部性原理
因此當我們向內核請求讀取數據時,內核會先到內核緩沖區(qū)中去尋找,如果命中數據,則不需要進行真正的磁盤 I/O,直接從緩沖區(qū)中返回數據就行了;如果緩存未命中,則內核會從磁盤中讀取請求的 page,并同時讀取緊隨其后的幾個 page(比如三個),如果文件是順序訪問的,那么下一個讀取請求就會命中之前預讀的緩存(當然了,預讀算法非常復雜,這里只是一個簡化的邏輯)。
再來看看內核緩沖區(qū)是怎么充當 Buffer 的:
? 延時回寫
回寫指的是,當程序發(fā)起 write() 系統(tǒng)調用時,內核并不會直接把數據寫入到磁盤文件中,而僅僅是寫入到緩沖區(qū)中,幾秒后(或者說等數據堆積了一些后)才會真正將數據刷新到磁盤中。對于系統(tǒng)調用來說,數據寫入緩沖區(qū)后,就返回了。
延遲往磁盤寫入數據的最大一個好處就是,可以合并更多的數據一次性寫入磁盤,把小塊的 I/O 變成大塊 I/O,減少磁盤處理命令次數,從而提高提盤性能。
另一個好處是,當其它進程緊接著訪問該文件時,內核可以從直接從緩沖區(qū)中提供更新的文件數據(這里又是充當 Cache 了)。
說起來一大堆,其實很簡單,把握緩沖和緩存的定義就行了,如果你是讀,我就會拿多一點放在內核緩沖區(qū),這樣你下次讀的時候大概率就不需要訪問磁盤了,直接從內核緩沖區(qū)拿就行;如果你是寫,我就會等內核緩沖區(qū)中的數據堆積得多了再寫磁盤,而不是來一點數據就寫一次磁盤
無論是讀操作還是寫操作,無論是充當緩存還是緩沖,究其根本,內核緩沖區(qū)的作用都是為了減少磁盤 IO 的次數
用戶緩沖區(qū)
上面提到,read 磁盤的速度要遠遠慢于 read 內存,不過事實上,read 內存這個操作也挺費時的,因為應用程序想要訪問系統(tǒng)資源的話,就要通過系統(tǒng)調用 or 中斷(外中斷、內中斷)使得 CPU 從用戶態(tài)轉向內核態(tài),這個狀態(tài)的改變需要涉及堆棧的環(huán)境和數據變化,還是挺需要時間的。
那為了減少系統(tǒng)調用的發(fā)生呢(或者說,減少用戶態(tài)和內核態(tài)的轉換次數),就設計了用戶緩沖區(qū)。
作用和內核緩沖區(qū)一樣,數據預讀 + 延時回寫,既充當 Cache 又充當 Buffer。
不同的就是,內核緩沖區(qū)處理的是內核空間和磁盤之間的數據傳遞,目的是減少訪問磁盤的次數;而用戶緩沖區(qū)處理的是用戶空間和內核空間的數據傳遞,目的是減少系統(tǒng)調用的次數(感覺這句話總結的不錯,給自己點個贊)

另外,從上面的分析我們可以看出,read() 和 write() 都并非真正執(zhí)行 I/O 操作(或者說,都并不直接和磁盤進行交互),它只代表數據在用戶空間 / 內核空間傳遞的完成,read 是把數據從內核緩沖區(qū)復制到用戶緩沖區(qū),write 是把用戶緩沖區(qū)復制到內核緩沖區(qū)
心之所向,素履以往,我是小牛肉,小伙伴們下篇文章再見 ??
