緩沖區(qū)
作用:在實(shí)際編程中,I/O速度取決于顯示器、鍵盤、硬盤等I/O設(shè)備的性能,而這些設(shè)備比起CPU和內(nèi)存是比較慢的。因此系統(tǒng)采用緩沖區(qū)的方式來減少I/O的讀寫,以便提高系統(tǒng)性能。
I/O的緩沖區(qū)的種類:1、無緩沖;2、行緩沖;3、全緩沖。
一、行緩沖:
看一個(gè)例子:
[cpp]
view plaincopy#include <stdio.h>
int main(void)
{
printf("123\n456");
while(1){}
return 0;
}
結(jié)果:
[cpp]
view plaincopy123
這段代碼只輸出了“123\n”而沒有輸出“456”。原因是標(biāo)準(zhǔn)I/O:stdin,stdout是行緩沖。
行緩沖的特性是:C標(biāo)準(zhǔn)輸出先寫到行緩沖區(qū)里,當(dāng)遇到下列四種情況才一次性把行緩沖區(qū)的數(shù)據(jù)寫到I/O設(shè)備里去:
1、遇到\n字符;
2、行緩沖區(qū)(linux默認(rèn)大小為1024字節(jié))被填滿后。
3、調(diào)用沖洗緩沖區(qū)的函數(shù):fflush等。
4、進(jìn)程返回、調(diào)用exit退出、文件流關(guān)閉等。
上例中printf的作用是把"123\n456"依次寫入緩沖區(qū),由于中途遇到\n,因此立即會(huì)把緩沖區(qū)里的所有數(shù)據(jù)——"123\n"寫入I/O設(shè)備(此處是屏幕),接著的是把“456”寫到緩沖區(qū)里。“456”之后沒有“\n”、緩沖區(qū)又沒有滿、程序死循環(huán)在while(1)里沒有結(jié)束,因此“456”將永遠(yuǎn)不會(huì)輸出到I/O設(shè)備里。
屬于行緩沖的I/O設(shè)備通常是需要交互的I/O:鍵盤(默認(rèn)的stdin),屏幕(默認(rèn)的stdout)等。
二、全緩沖
還是上面的代碼(假設(shè)生成的執(zhí)行程序名為“a.ex”,并且目錄下有個(gè)“b.txt”的文本),如果這樣啟動(dòng):
[cpp]
view plaincopy$ a.ex > b.txt
那么程序?qū)⒉粫?huì)輸出任何字符到b.txt中。
因?yàn)閷?duì)于文件(文件是在硬盤上的),硬盤I/O屬于全緩沖。
全緩沖的特性是:C標(biāo)準(zhǔn)輸出先寫到全緩沖區(qū)里,當(dāng)遇到下列三種情況才一次性把全緩沖區(qū)的數(shù)據(jù)寫到I/O設(shè)備里去:
1、全緩沖區(qū)被填滿后。
2、調(diào)用沖洗緩沖區(qū)的函數(shù):fflush等。
3、進(jìn)程返回、調(diào)用exit退出、文件流關(guān)閉等。
上例中啟動(dòng)a.ex程序時(shí),用重定向符號(hào)“>”將stdout重定向到b.txt里。由于b.txt是文件,屬于硬盤I/O,所以并滿足全緩沖的寫入條件。
屬于全緩沖的I/O設(shè)備有:硬盤等。
三、無緩沖
[cpp]
view plaincopy#include <stdio.h>
#include <unistd.h>
int main(void)
{
write(STDOUT_FILENO,"123\n456",7);
while(1){}
return 0;
}
結(jié)果是:
[cpp]
view plaincopy123
456
沒錯(cuò),無緩沖會(huì)直接將字符串寫入I/O設(shè)備里去。
write寫文件或者屏幕等設(shè)備都是無緩沖的;stderr無論重定向到哪里都是無緩沖的。
四、最后補(bǔ)充一些注意:
[cpp]
view plaincopy#include <unistd.h>
#include <stdio.h>
int main(void)
{
printf("123\n456");
_exit(0);
}
結(jié)果是:
[cpp]
view plaincopy123
因?yàn)閡nix系統(tǒng)中_exit 函數(shù)并不沖洗緩沖區(qū)。