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
版權宣告:本文為博主原創文章,轉載請附上博文連結!