天天看點

淺談标準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;
}
           

繼續閱讀