今天來為大家分享一波關于緩沖區的知識!那么既然我們要談緩沖區,那么就得從是什么?為什么?有什么作用這幾個方面來談論一下緩沖區!然后再通過一些代碼來更加深刻的理解緩沖區的知識!
引言:
是什么?
從最簡單的理解方面來,我們可以將緩沖區理解成一塊內存!那么這塊內存是從哪里來的呢?在linux中一般我們所說的緩沖區都是由C提供的語言級別的緩沖區!
干什么的?
那么緩沖區的作用主要是用來干什么的呢?可以從我們生活中的例子來理解!假設你的朋友小張下個月就要過生日了,你要送他一個生日禮物!但是你們兩個距離很遠!一個在西藏,一個在海南!如果讓你自行將生日禮物送給他,那么無疑將會浪費你的很多成本!但是現實中存在快遞站,只需要你下樓將禮物交付給快遞站,然后由快遞站代替你送過去即可!那么在本例子內,快遞站的作用就是一個緩沖區的作用!
為什么要存在緩沖區?
根據上面提到的例子,很容易理解,因為有了快遞站的存在,使我們方便了很多!所以類似于此,緩沖區存在的意義就是為了提高效率,減少我們的成本!
下面通過一段代碼來證明一下緩沖區確實存在!
我們用戶通常寫程序在屏幕上打印一段文字的時候!其中就利用到了緩沖區!例如下面這個例子!
運行這段程序之后,顯示屏上并沒沒有立刻打印出“hello linux”,這是為什么呢?根據我們所了解到的知識,程序是自上向下運行的,運行到sleep的時候,printf語句一定是執行過了,但是為什么沒有打印出結果呢?根據此例子可以充分的證明緩沖區的存在!!既然證明了緩沖區的存在,那么我們將來一步一步的進行分析緩沖區的相關知識1
那么從系統角度來將該如何理解的呢?
從操作系統角度上來看!用戶輸入一段指令,該指令并沒有直接傳遞到內核文件內存中!而是將用戶輸入的指令存放到了C提供的語言級別的緩沖區內!然后在C語言的緩沖區中經過刷新之后!再傳遞到內核結構中的文件緩沖區中!最后系統會定期的將內存的數據刷新到磁盤中!此階段也可以稱之為刷新!在此,我們提到了兩個緩沖區,一個是用戶層的C語言提供的語言級別的緩沖區,一個是內核結構中的內核文件緩沖區!一般我們所考慮的都是C語言提供的語言級別的緩沖區!
緩沖區的一些特性:
根據緩沖區能夠存儲一定的數據可以推出:緩沖區一定存在著刷新的方式!
1.無緩沖(立即刷新!)
2.行緩沖(行刷新!)
一般對于顯示器文件,都是基于行緩沖的模式!
3.全緩沖(存放滿然后進行刷新!)
對于磁盤文件,都是基于全緩沖的方式!
那么根據以上的特征,緩沖區也會有著特殊的情況!
1.強制刷新!
2.進程退出后,會自動進行刷新!(無論是否滿足刷新的條件!)
實例:充分理解緩沖區
下面通過一段代碼來充分理解緩沖區中的行緩沖和全緩沖!
上面代碼運行過后,每行代碼都打印了出來!這是為什么呢?剛才不是還說是存在緩沖區的么?其實不難理解,因為每段代碼都有了\n換行符,強制讓緩沖區內的數據進行刷新!所以數據都原樣的打印了出來!!
那么將上面的代碼經過簡單的修改就會出現另外一種結果!
經過上面代碼簡單的修改,我們發現C函數的調用都打印了兩次,而是用系統調用的write確只調用了一次!這是為什么呢?其實很簡單!
我們可以看出,我們將輸出結果由原來的行緩沖轉化成了全緩沖(因為將結果打印到了log.txt文本文件中,文本文檔默認為全緩沖的刷新方式!)所以只有當將緩沖區填滿的時候,才會進行刷新!才能打印到顯示屏中!又因為調用了fork函數,創建了新的子進程!根據fork的特性會繼承父進程的代碼和數據塊!因為此時代碼仍然在緩沖區內!所以子進程也會繼承這些相同的代碼和數據塊!然后當一個進程結束后,就會發生寫時拷貝!這是因為當一個進程退出的時候,一般都會對緩沖區的數據進行刷新,那么算不算清空或寫入的操作呢?答案是肯定的!當時算!所以就會發生寫時拷貝!所以可以推出,一旦一個進程退出,那么就會發生寫時拷貝!
根據上圖結果看出,系統調用write只打印了一次!從這里可以推出:write沒用使用C語言的緩沖區!因為C語言的一些函數,大多都是對系統調用的封裝!大多都是因為封裝的原因!而導致他們使用C提供的緩沖區!而系統調用處于內核級別,在用戶級別的下面,直接將數據寫入到內核文件系統中!所以不使用C提供的緩沖區!
實例中的主要知識點:
1.當我們直接向顯示器打印的時候,顯示器文件的刷新方式是行刷新!而是我們的代碼輸出的所有字符串,都有\n,fork之前,數據已經全部被刷新!包括systemcall!
2.重定向到log.txt之后,本質是向磁盤文件中寫入(而不再是顯示器里面!),我們系統對于數據的刷新方式已經由行刷新轉化到了全刷新的方式!變成了全緩沖!
3.全緩沖意味著緩沖區變大,實際寫入的簡單數據,不足以將緩沖區填滿!fork執行的時候,數據依然在緩沖區內部!
4.我們目前所談的緩沖區,是和操作系統沒有關系的!只能和C語言本身有關!!
5.C/C++提供的緩沖區,里面保存的一定是用戶的數據!其屬于當前進程運行的數據!但是如果當把數據交付給OS,這些數據就屬于OS了,不再屬于該進程了!
6.當進程退出的時候,一般會進行刷新緩沖區,即使我們的數據沒有滿足刷新條件!
證明緩沖區的存在以及其在內核中的結構!
既然我們都講了這么多關于緩沖區的知識了,那么我們確實已經知道了緩沖區真實存在!那么能否讓我看一看其到底是什么樣子的呢?
通過以上函數,我們可以發現,大多的輸入輸出操作,以及文件的操作都用到了FILE該結構體!那么該結構體之中我們之前知道其包含了文件描述符fd,那么其是否介意再包含一個緩沖區的成員變量呢?答案是當然不介意的啦!
我們可以通過對FILE的觀察來看一下緩沖區的真實存在!
我們通過grep指令來查看FILE的路徑!然后在FILE內部繼續進行查找,最后看到FILE內部有我們熟悉的文件描述符_fileno,以及我們今天所講的緩沖區的內容!
至此,本文關于緩沖區的介紹到此為止,希望讀完本篇文章,能對讀者有一定的收獲!