Linux基礎篇五——緩衝

在現代操作系統裏幾乎所有的I/O設備在和處理機交換數據時都使用了緩衝機制,緩衝區是一個存儲區域,可以是專門的硬件寄存器組成但是因爲硬件的成本較高容量也小,一般的情況下,更多的利用內存來作爲緩衝區。

緩衝區管理:組織緩衝區並提供獲得和釋放緩衝區的手段。

    緩衝技術是爲了協調吞吐速度相差很大的設備之間數據調用而採用的技術

 緩衝的引用要解決的問題實際上有:

      1、改善CPU和I/O設備之間速度不匹配的情況。

      2、可以減少I/O設備對CPU的中斷次數及放寬對CPU的中斷響應時間要求。

      3、提高CPU和I/O設備之間的並行性

       eg:  在生產者(CPU)和消費者(打印機)之間設置緩衝區,生產者在生產了一批數據並將其入緩衝區接着投入下一次生產,而消費此時就可拿出數據,這樣生產者和消費者就可處於並行的工作狀態。如果他們之間沒有緩衝區的話,生產者生產好了一批數據之後必須停下工作等待消費者,這樣會使得生產者的效率降低。

1、單緩衝區

wKiom1dJq7bhJpH6AAAc0fYLJ9c537.png

    假設數據從I/O設備傳遞給緩衝區的時間爲T,CPU對數據的處理時間是C,緩衝區將數據傳送給CPU的時間是M,那麼憂鬱在I/O設備給緩衝區傳送數據時,CPU可以同時處理數據,所以系統對數據處理的總時間爲Max(C,T)+M.

    **在字符設備輸入時緩衝區是用於暫存用戶輸入的一行數據,在輸入期間用戶進程掛起等待,輸出時,用戶進程將一行數據輸入到緩衝區後繼續進行處理,當用戶程序已有第二行數據輸出但是第一行數據尚未被提取完成則會造成用戶進程的阻塞。

2.雙緩衝區

wKioL1dJrMSBB5dpAAAkf_dS-w8382.png

    雙緩衝區實際上是爲了解決消費者和生產者在使用緩衝區時互斥的問題。如果消費者尚未取走緩衝區的數據,那麼即使生產者產生了新數據也無法送入緩衝區

    雙緩衝又被稱爲緩衝對換,在設備如屬實可將數據先送入第一緩衝區,等到第一緩衝區裝滿後轉向第二緩衝區,此時操作系統就可以從第一緩衝區移出數據送入用戶進程,讓CPU對數據進行處理。

    如果在實現兩臺機器之間通信時他們只設置了單緩衝,那麼他們之間只能在任一時刻實現單向數據傳輸,爲了實現雙向數據傳輸必須在每個機器上分別設置發送緩衝區及接收緩衝區。

3.環形緩衝區

wKiom1dJq9fDylP7AAAgM2w_4aE917.png-wh_50

 環形緩衝區中包含多個緩衝區,其中每個緩衝的大小相同,並且被分爲三種類型:

     R:裝輸入數據

     G:已裝滿數據的緩衝區

     C:進程正在使用的緩衝區

 環形緩衝區裏含有三個指針:

     Nexti:指向輸入進程下次可用的R

     Nxetg:指向計算進程下次可使用的G

     Cuurent:指向進程正在使用的緩衝區

 在對環形緩衝區進行處理的時候有兩個重要的方法:

     1.Getbuf:將指針Nextg指向的緩衝區提供給進程並且讓修改current的值,最後讓Nextg指向下一個G緩衝區

     2.Releasebuf:將使用完成的C緩衝區釋放將其修改成R,當R緩衝區滿時將其修改爲G

環形緩衝區還會出現下面兩種問題:

     1.系統計算受限:Nexti追上Nextg

     2.系統I/O受限:Nextg追上Nexti


緩衝池

    我們在之前所說的緩衝區都可以稱爲專用緩衝。當系統較大時,爲了提高利用率,我們使用即可輸入又可輸出的公用緩衝池,在池中設置若干個緩衝區。

緩衝池的組成:

     1.空白緩衝隊列:空緩衝區所鏈成

     2.輸入隊列:裝滿輸入數據的緩衝區鏈成

     3.輸出隊列:裝滿輸出數據的緩衝區鏈成


緩衝區的工作方式:收容輸入、收容輸出、提取輸入、提取輸出

    在我們的學習過程中大家實際上已經和緩衝很熟悉了但是我們卻視若無睹,我們知道在linux裏有三種緩衝機制,行緩衝,全緩衝,無緩衝。

    全緩衝:直到緩衝區填滿之後調用系統I/O

    行緩衝:直到遇到換行或者行緩衝填滿之後進行調用系統I/O

    我們來看兩個關於行緩衝的例子:

    第一例:神祕消失的hello world

wKiom1dJq_bDCUAKAABnL7qEKmo760.png

    在上面的程序裏我們沒有在標準輸出裏使用‘\n’並且使用了_exit(0)導致行緩衝的內容沒有被處理

    所以在我們運行程序時,我們並沒有看見hello world

  **

        exit ()調用exit函數之後,它首先會執行一系列的清理處理,包括調用執行各終止處理程序,關閉所有標準IO流等,然後進入內核。

    _exit ()。與exit不同的是,它不進行清理工作而直接進入內核。

    _Exit ()。同樣,它也不進行清理工作而直接進入內核。

  第二例:進度條小程

wKioL1dJrQXCMGsJAAEFPVnQStY224.png

    顯然在此例裏,我們藉助了fflush來刷新我們的緩衝區,在使用該函數時無論緩衝區是否被填滿都會調用系統I/O。

    再此我們須理解換行和回車的不同概念,換行是指跳到當前行的下一行,而回車是指回到該行的行首,此例中我們使用了‘\r’來控制每次從行首的覆蓋輸出實現進度條的前進,是不是很神奇呢,你也快去試一試吧!j_0038.gif


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章