使用者程序緩衝區和核心緩衝區

2021-09-20 06:53:55 字數 2700 閱讀 5763

常常聽到有程式設計師會跟你討論:「我們在讀寫檔案的時候,系統是有快取的」。但實際上有一部分人把使用者程序緩衝區和系統空間的緩衝區的概念混淆了,包括這兩種緩衝區的用法和所要解決的問題,還有其它類似的概念。本文就來區分一下不同的緩衝區概念(主要針對類unix平台)。

使用者程序和作業系統的關係

首先我用一張圖來解釋「使用者程序和作業系統的關係」

這是乙個計算機系統執行時的簡化模型,我們把所有執行在作業系統上的程序成為使用者程序,它們都執行在使用者空間(可以看到使用者空間有很多程序)。把作業系統執行的空間成為系統空間

為什麼將程序分為使用者程序和系統程序,首先你一定聽說過核心態和使用者態(kernel mode和user mode),在核心態可以訪問系統資源,比如:

處理器cpu:cpu控制著乙個程式的執行。

輸入輸出io:linux有句話叫「一切都是流」,也就是所有輸入輸出裝置的資料,包括硬碟,記憶體,終端都可以像流一樣操作。

程序管理:類似對程序的建立,休眠,喚醒,釋放之類的排程。比如linux下的fork和windows下的createprocess()函式。

記憶體:包括記憶體的申請,釋放等管理操作。

裝置:這個就是常常說的外設了,比如滑鼠,鍵盤。

計時器:計算機能計時是因為晶體振盪器產生的電磁脈衝。那麼所有的定時任務都是以它為基礎的。

程序間通訊ipc:程序之間是不能夠互相訪問記憶體的,所以程序與程序之間的互動需要通訊,而通訊也是一種資源。

網路通訊:網路通訊可以看做是程序見通訊的特殊形式。

而上面所說的這些系統資源,在使用者程序中是無法被直接訪問的,只能通過作業系統來訪問,所以也把作業系統提供的這些功能成為:「系統呼叫」。

比如下圖,展示乙個使用者通過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效率,優化磁碟寫操作。

流程在《unix網路程式設計》中的五種io模型,也提到過程序緩衝區和核心緩衝區。因為這個並不是此篇文章的重點,所以這裡只對比阻塞模型和非阻塞。

對比阻塞和非阻塞,在阻塞io中,直到資料從核心緩衝區拷貝到使用者緩衝區才通知使用者程序呼叫完成並喚醒,而非阻塞,在輪訓得知資料準備好後,資料還是在核心緩衝區中,等你去讀取,這也就是說資料準備好,並不代表已經讀好可以使用。當然也不代表一定能讀。

緩衝區和快取

還有一部分人把緩衝區和快取混淆,後來我明白這也是因為翻譯導致的把兩種東西進行混淆。緩衝區的英文是buffer,而快取的應為是cache。

cpu快取(cache memory)是位於cpu與記憶體之間的臨時儲存器,因為cpu的計算速度要比記憶體的讀寫速度快很多,而把這些可能會被重複訪問到的資料儲存於cpu快取中,就會提高讀取速度。可以說快取是cpu和記憶體之間的臨時儲存器。

也就是說,buffer是因為減少呼叫次數,集中呼叫,提高系統效能。而cache是將讀取過的資料儲存起來,重新讀取時若命中(找到需要的資料)就不要去讀硬碟了,若沒有命中就讀硬碟。

核心緩衝區應用

include define fifo size 1024 typedef struct tags fifo s fifo int fifo min unsigned int ulfirstdat,unsigned int ulsndvalue else int fifo init s fifo p...

輸入緩衝區與輸出緩衝區

本博文通過一段程式來理解輸入緩衝區與輸出緩衝區。程式如下 author wanghao created time thu 17 may 2018 06 03 12 ampdt file name test.c description include int main int argc,const c...

php 緩衝區,PHP的輸出緩衝區

1 什麼是緩衝區?緩衝區的作用是把輸入或者輸出的內容先放進記憶體,而不顯示或者讀取,最本質的作用就是協調高速cpu和相對緩慢的io裝置 磁碟等 的運作。2 php在執行的時候,在什麼地方有用到緩衝區?當執行php的時候,如果碰到了echo print r之類的會輸出資料的 php就會將要輸出的資料放...