緩衝區的個人理解

緩衝區的個人理解

這裏所說的緩衝區指的是爲標準輸入與標準輸出設置的緩衝區,爲什麼要設置一個標準輸入緩衝區主要是從效率上來考慮的,如果不設緩衝區會降低cpu的效率,因爲它總是會等待用戶輸入完之後纔會去執行某些指令!同樣設置一個標準輸出緩衝區是爲了解決打印的問題!總之這樣做的目的就是爲了效率!

接下來講解一下怎麼設置標準輸入與標準輸出緩衝區。

如果我們不認爲的設置的話,系統會自動的爲標準輸入與標準輸入設置一個緩衝區,這個緩衝區的大小通常是4Kb的大小,這和計算機中的分頁機制有關,因爲進程在計算機中分配內存使用的就是分頁與分段的機制,並且每個頁的大小是4Kb,因此通常情況下緩衝區的大小會設置爲4Kb的大小!並且這個緩衝區的類型是一個全緩衝的緩衝區!所謂全緩衝指的是:當緩衝區裏的數據寫滿的時候(或者可以說達到頂端)緩衝區中的數據纔會“寫”到標準輸入磁盤文件中,這裏說的寫不是將緩衝區中的數據移動到磁盤文件中,而是拷貝到磁盤文件中,也就說此時磁盤文件中保留了一份緩衝區內容的備份!除了全緩衝外還有不緩衝和行緩衝,不緩衝不太常見與常用,在這裏我就不做講解了!下面講解一下什麼是行緩衝。行緩衝指的是當在鍵盤上敲下回車鍵的時候數據會存儲在緩衝區中,這是毫無疑問的,同時也將緩衝區的數據拷貝一份到磁盤文件中!那麼磁盤文件中備份的內容有什麼用呢??本人能力有限目前還沒有發現有什麼用!

當熱我們還可以自己設置緩衝區,緩衝區的大小可以由我們自己決定,緩衝區的類型也由我們自己決定!在這裏有兩個函數,一個是setbuf(   FILE *stream  ,  char *buffer  ) 另一個是setvbuf( FILE *stream  ,   char *buffer  ,  int mode  ,   unsigned int  size  ) 

其中緩衝區的類型可以是:_IOFBF :全緩衝   _IOLBF :行緩衝  _IONBF : 不緩衝

下面講解一下緩衝區是怎麼工作的!

當我們從鍵盤輸入數據的時候數據並不是直接被我們得到(這個問題我在上面已經講解過了,不在重複),而是將這些輸入的數據放在了緩衝區中,然後我們從緩衝區中得到我們想要的數據 !如果我們通過函數(setbuf , setvbuf)將緩衝區設置10個字節的大小,而我們從鍵盤輸入了20個字節大小的數據,這樣我們輸入的前10個數據會放在緩衝區中,因爲我們設置的緩衝區的大小隻能夠裝下10個字節大小的數據,裝不下20個字節大小的數據。那麼剩下的那10個字節大小的數據怎麼辦呢??暫時放在了輸入流中!如果不能夠理解這個,那我舉一個比較形象的例子:

 

上面的箭頭表示的區域就相當是一個輸入流,紅色的地方相當於一個開關,這個開關可以控制往深綠色區域(標註的是緩衝區)裏放進去的數據,輸入20個字節的數據只往緩衝區中放進去了10個字節,剩下的10個字節的數據就被停留在了輸入流裏!等待下去往緩衝區中放入!接下來系統是如何來控制這個緩衝區呢?

C語言方式下  是一個結構體數組  類型是FILE結構體

struct _iobuf {

        char *_ptr;

        int   _cnt;

        char *_base;

        int   _flag;

        int   _file;

        int   _charbuf;

        int   _bufsiz;

        char *_tmpfname;

        };

結構體中的成員簡單的介紹下
_ptr     //指向當前緩衝區內容的指針
_cnt     //如果是輸入緩衝區  那他就是顯示現在緩衝區裏還有多少個有效數據
_base    //緩衝區基地址
_flag    //標誌位   具體好像就是什麼可寫啊 可讀啊之類的
_file    //這個是設備句柄(也可以說是文件句柄)
_bufsiz  //緩衝區總大小   一般都是0x1000    也就是4k   也就是一個分頁

 

在上面我們向緩衝區中放入了10個字節大小的數據,FILE結構體中的_cnt變爲了10 ,說明此時緩衝區中有10個字節大小的數據可以讀,同時我們假設緩衝區的基地址也就是_base0x00428e60 ,它是不變的 ,而此時_ptr的值也爲0x00428e60 表示從0x00428e60這個位置開始讀取數據,當我們從緩衝區中讀取5個數據的時候,_cnt變爲了,表示緩衝區還有5個數據可以讀,_ptr則變爲了0x0042e865表示下次應該從這個位置開始讀取緩衝區中的數據 ,如果接下來我們再讀取5個數據的時候,_cnt則變爲了,表示緩衝區中已經沒有任何數據了,_ptr變爲了0x0042869表示下次應該從這個位置開始從緩衝區中讀取數據,但是此時緩衝區中已經沒有任何數據了,所以要將輸入流中的剩下的那10個數據放進來,這樣緩衝區中又有了10個數據,此時_cnt變爲了10 ,注意了剛纔我們講到_ptr的值是0x00428e69 ,而當緩衝區中重新放進來數據的時候這個_ptr的值變爲了0x00428e60 ,這是因爲當緩衝區中沒有任何數據的時候要將_ptr這個值進行一下刷新,使其指向緩衝區的基地址也就是0x0042e860這個值!因爲下次要從這個位置開始讀取數據!

 

在這裏有點需要說明:當我們從鍵盤輸入字符串的時候需要敲一下回車鍵才能夠將這個字符串送入到緩衝區中,那麼敲入的這個回車鍵(\r)會被轉換爲一個換行符\n,這個換行符\n也會被存儲在緩衝區中並且被當成一個字符來計算!比如我們在鍵盤上敲下了123456這個字符串,然後敲一下回車鍵\r將這個字符串送入了緩衝區中,那麼此時緩衝區中的字節個數是,而不是6

緩衝區的刷新就是將指針_ptr變爲緩衝區的基地址 ,同時_cnt的值變爲,因爲緩衝區刷新后里面是沒有數據的!

 

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