博客 / 詳情

返回

數據緩衝區

\r 和 \n 的區別

  • \r 表示回車 (回車表示換到當前行的最開始)
  • \n 表示換行(換行只是換到下一行)
  • 注意:但是在實際使用時,\n 就直接表示了 \r\n 回車換行。
    image.png

緩衝區的概念

  • 行緩衝:常見的是對顯示器進行刷新數據時

    • 即必須緩衝區中一行填滿了或者遇到 \n 才會輸出到顯示器
  • 全緩衝:對文件進行寫入時採用全緩衝

    • 即將整個緩衝區填滿才會刷新到磁盤中。
  • 無緩衝:即刷新數據時沒有緩衝區。

行緩衝示例一:

  • 下列代碼執行後的結果是:停止5秒後才顯示 hello world

    • printf 這行代碼是先執行的
    • 但是 printf 中沒有 \n ,並且緩衝區中的一行並沒有填滿,所以沒有輸出到顯示器
    • 所以繼續執行下面的 sleep 代碼
    • 在程序結束後會刷新緩衝區,將緩衝區的內容輸出到顯示器,所以最後仍然會顯示。
void test()
{
    printf("hello world");  //加入 \n  後就會立即輸出到顯示器了。
    sleep(5);    
}

行緩衝示例二

  • 下列代碼顯示結果為:倒計時,並且下一次的數字會覆蓋上一次的數字。
  • 因為 \r 只是回車,並未換行,所以依然會在之前那一行繼續輸出
  • 並且回車後,會回到這一行的起始位置,所以覆蓋了上一次的值。
#include <unistd.h>
void test()
{
    int i = 10;
    while(i)
    {
        printf("%2d\r",i);  //%2d 表示顯示兩個字符
        fflush(stdout);  //fflush是一個庫函數,用來立即刷新緩衝區輸出到顯示器中
        sleep(1);  
        i--;
    }
      
}

全緩衝與無緩衝示例一

#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main()
{
    //C語言函數
  printf("hello printf\n");
  fprintf(stdout,"hello fprintf\n");

  //系統函數
  const char * msg = "hello write\n";
  write(1,msg,strlen(msg));
  
  fork();                                                                                                                                
  return 0;
}

image.png

  • 正常輸出到顯示器中時,是正常顯示三行
  • 但是重定向輸出到文件中時,會多打印2行
  • 當往顯示器中打印時,系統採用的是行緩衝,即運行到 printf 等函數後,立馬將數據刷新到顯示器。
  • 但是當重定向打印到文件時,緩衝方式發生變化,變成全緩衝,全緩衝會等到程序結束時,一次性將緩衝區內容打印到文件中
  • 程序最後創建了子進程,子進程會繼承父進程的緩衝區(子進程的緩衝區和父進程緩衝區內容相同,但是不是一個緩衝區,進程的獨立性,發生寫實拷貝)
  • 所以父進程刷新一次緩衝區後,子進程也會刷新緩衝區,所以會打印兩次 C 函數的內容。
  • 因為系統函數(系統接口)沒有緩衝區,所以 write函數只打印一次,並且是第一個被打印。

緩衝區位置

  • 緩衝區是由 C 語言本身自帶的,所有的 C 函數接口都有緩衝區,而系統接口沒有緩衝區。
  • 緩衝區是維護在文件結構體 files_struct 中,files_struct 提供文件描述符和用户緩衝區。
user avatar jichenssg 頭像
1 位用戶收藏了這個故事!

發佈 評論

Some HTML is okay.