1. 程式人生 > >Linux 環境程式設計——淺談標準I/O緩衝區

Linux 環境程式設計——淺談標準I/O緩衝區

標準I/O庫提供緩衝的目的是儘可能地減少使用read和write呼叫的次數。它也對每個I/O流自動地進行緩衝管理,從而避免了應用程式需要考慮這一點所帶來的麻煩。不幸的是,標準I/O庫最令人迷惑的也是它的緩衝。

 

標準I/O提供了三種類型的緩衝:

1、全緩衝:

在填滿標準I/O緩衝區後才進行實際I/O操作。常規檔案(如普通文字檔案)通常是全緩衝的。

2、行緩衝:

當在輸入和輸出中遇到換行符時,標準I/O庫執行I/O操作。這允許我們一次輸出一個字元,但只有在寫了一行之後才進行實際I/O操作。標準輸入和標準輸出對應終端裝置(如螢幕)時通常是行緩衝的。

3、不帶緩衝:

使用者程式每次調庫函式做寫操作都要通過系統呼叫寫回核心(如系統呼叫函式)。標準錯誤輸出通常是無緩衝的,這樣使用者程式產生的錯誤資訊可以儘快輸出到裝置。

 

下面是各個緩衝區的驗證。

全緩衝:
int main(int argc, char *argv[])
{
    FILE *fp = NULL;
    // 讀寫方式開啟,檔案不存在則建立
    fp = fopen("sunplusedu.txt", "w+");
    if(NULL == fp)
    {
        printf("open error\n");
        return 1;
    }
    char *str = "sunplusedu\n";
    fwrite(str, 1, strlen(str), fp);    // 往檔案寫內容
    while(1);    // 程式阻塞在這裡
 
    return 0;
}

執行程式發現,sunplusedu.txt並沒有內容。因為常規檔案通常是全緩衝的,只有緩衝區滿了後,才會把內容寫到檔案中。接下來,我們改一下上面那個例子。


#include <stdio.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
    FILE *fp = NULL;
    // 讀寫方式開啟,檔案不存在則建立
    fp = fopen("sunplusedu.txt", "w+");
    if(NULL == fp)
    {
        printf("open error\n");
        return 1;
    }
    char *str = "sunplusedu\n";
    int i = 0;
    while(i <= 512){    // 緩衝區大小不確定,i的大小隻是一個除錯值
        fwrite(str, 1, strlen(str), fp);    // 往檔案寫內容
        i++;
    }
    while(1);    // 程式阻塞在這裡
 
    return 0;
}


上面的例子是迴圈給檔案寫內容,讓緩衝區有填滿的可能,結果發現,檔案是有內容的。實際上要想成功給檔案寫進內容,除了緩衝區填滿,還有別的方法。


1)人為關閉檔案,就算緩衝區沒有填滿,內容也會寫進檔案


#include <stdio.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
    FILE *fp = NULL;
    // 讀寫方式開啟,檔案不存在則建立
    fp = fopen("sunplusedu.txt", "w+");
    if(NULL == fp)
    {
        printf("open error\n");
        return 1;
    }
    char *str = "sunplusedu\n";
    fwrite(str, 1, strlen(str), fp);    // 往檔案寫內容
    fclose(fp);        // 人為關閉檔案,就算緩衝區沒有填滿,內容也會寫進檔案
    
    while(1);    // 程式阻塞在這裡
 
    return 0;
}

2)程式正常結束,就算緩衝區沒有填滿,沒有關閉檔案,內容也會寫進檔案。


#include <stdio.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
    FILE *fp = NULL;
    // 讀寫方式開啟,檔案不存在則建立
    fp = fopen("sunplusedu.txt", "w+");
    if(NULL == fp)
    {
        printf("open error\n");
        return 1;
    }
    char *str = "sunplusedu\n";
    fwrite(str, 1, strlen(str), fp);    // 往檔案寫內容
    
    return 0;
    // 程式正常結束,就算緩衝區沒有填滿,沒有關閉檔案,內容也會寫進檔案。
}

行緩衝:
#include <stdio.h>
 
int main(int argc, char *argv[])
{
    printf("hello sunplusedu");
    while(1);
    
    return 0;
}

執行這個程式,會發現 hello sunplusedu 並沒有列印到螢幕上。因為標準輸入和標準輸出對應終端裝置時通常是行緩衝的,當在輸入和輸出中遇到換行符時,標準I/O庫執行I/O操作。如下:


#include <stdio.h>
 
int main(int argc, char *argv[])
{
    printf("hello sunplusedu\n");
    while(1);
    
    return 0;
}

除了遇到換行符,還有別的方法可以執行I/O操作。

1)緩衝區填滿


int main(int argc, char *argv[])
{
    while(1){    // 迴圈列印,總有緩衝區填滿的可能
        printf("hello sunplusedu");
    }
    while(1);
    
    return 0;
}


2)人為重新整理緩衝區


#include <stdio.h>
 
int main(int argc, char *argv[])
{
    printf("hello sunplusedu");
    fflush(stdout);    // 人為重新整理
 
    while(1);
    
    return 0;
}


3)程式正常結束


#include <stdio.h>
 
int main(int argc, char *argv[])
{
    printf("hello sunplusedu");
    
    return 0;
    // 程式正常結束
}


不帶緩衝:
#include <unistd.h>
#include <string.h>
 
int main(int argc, char *argv[])
{
    char *str = "hello sunplusedu.com";    
    // 有沒有\n,緩衝區有沒有填滿,都沒關係
    write(1, str, strlen(str));    // 往標準輸出寫內容
    while(1);
    
    return 0;
}

--------------------- 
作者:Mike__Jiang 
來源:CSDN 
原文:https://blog.csdn.net/tennysonsky/article/details/43490985 
版權宣告:本文為博主原創文章,轉載請附上博文連結!