使用者程序緩沖區和核心緩沖區
緩沖區的目的,是為了減少頻繁的系統IO調用。大家都知道,系統調用需要儲存之前的程序資料和狀态等資訊,而結束調用之後回來還需要恢複之前的資訊,為了減少這種損耗時間、也損耗性能的系統調用,于是出現了緩沖區。
有了緩沖區,作業系統使用read函數把資料從核心緩沖區複制到程序緩沖區,write把資料從程序緩沖區複制到核心緩沖區中。等待緩沖區達到一定數量的時候,再進行IO的調用,提升性能。至于什麼時候讀取和存儲則由核心來決定,使用者程式不需要關心。
在linux系統中,系統核心也有個緩沖區叫做核心緩沖區。每個程序有自己獨立的緩沖區,叫做程序緩沖區。
是以,使用者程式的IO讀寫程式,大多數情況下,并沒有進行實際的IO操作,而是在讀寫自己的程序緩沖區。
1. 使用者程序和系統程序
使用者程序:運作在作業系統上的程序,都運作在使用者空間
系統空間:作業系統運作的空間
這是一個計算機系統運作時的簡化模型,我們把所有運作在作業系統上的程序成為使用者程序,它們都運作在使用者空間(可以看到使用者空間有很多程序)。把作業系統運作的空間成為系統空間。
2. 核心态和使用者态(kernel mode和user mode)
(1)核心态可以通路系統資源,比如:
ps:上面所說的這些系統資源,在使用者程序中是無法被直接通路的,隻能通過作業系統來通路,是以也把作業系統提供的這些功能成為:“系統調用”。
比如下圖,展示一個使用者通過shell控制計算機所經過的資料流向:檔案讀寫和終端控制,都是通過核心進行的。
提供這些限制的基礎就是cpu提供的核心态和使用者态。比如intel x86 CPU有四種不同的執行級别0-3,linux隻使用了其中的0級和3級分别來表示核心态和使用者态。
在使用者态,不僅僅是系統資源了,就是别的程序的記憶體對于你來說,都是“透明的”(并不是沒辦法通路,否則遊戲作弊器怎麼實作?)
一、使用者程序緩沖區
前面提到,使用者程序通過系統調用通路系統資源的時候,需要切換到核心态,而這對應一些特殊的堆棧和記憶體環境,必須在系統調用前建立好。而在系統調用結束後,cpu會從核心模式切回到使用者模式,而堆棧又必須恢複成使用者程序的上下文。而這種切換就會有大量的耗時。
你看一些程式在讀取檔案時,會先申請一塊記憶體數組,稱為buffer,然後每次調用read,讀取設定位元組長度的資料,寫入buffer。(用較小的次數填滿buffer)。之後的程式都是從buffer中擷取資料,當buffer使用完後,在進行下一次調用,填充buffer。
是以說:使用者緩沖區的目的是為了減少系統調用次數,進而降低作業系統在使用者态與核心态切換所耗費的時間。
二、核心緩沖區
除了在程序中設計緩沖區,核心也有自己的緩沖區。
當一個使用者程序要從磁盤讀取資料時,核心一般不直接讀磁盤,而是将核心緩沖區中的資料複制到程序緩沖區中。
但若是核心緩沖區中沒有資料,核心會把對資料塊的請求,加入到請求隊列,然後把程序挂起,為其它程序提供服務。
等到資料已經讀取到核心緩沖區時,把核心緩沖區中的資料讀取到使用者程序中,才會通知程序,當然不同的io模型,在排程和使用核心緩沖區的方式上有所不同,下一小結介紹。
你可以認為,read是把資料從核心緩沖區複制到程序緩沖區。write是把程序緩沖區複制到核心緩沖區。
當然,write并不一定導緻核心的寫動作,比如os可能會把核心緩沖區的資料積累到一定量後,再一次寫入。這也就是為什麼斷電有時會導緻資料丢失。
是以說核心緩沖區,是為了在OS級别,提高磁盤IO效率,優化磁盤寫操作。
緩沖區和緩存
還有一部分人把緩沖區和緩存混淆,後來我明白這也是因為翻譯導緻的把兩種東西進行混淆。緩沖區的英文是buffer,而緩存的應為是cache。
CPU緩存(Cache Memory)是位于CPU與記憶體之間的臨時存儲器,因為cpu的計算速度要比記憶體的讀寫速度快很多,而把這些可能會被重複通路到的資料存儲于cpu緩存中,就會提高讀取速度。可以說緩存是cpu和記憶體之間的臨時存儲器。
也就是說,buffer是因為減少調用次數,集中調用,提高系統性能。而cache是将讀取過的資料儲存起來,重新讀取時若命中(找到需要的資料)就不要去讀硬碟了,若沒有命中就讀硬碟。