标准I/O库之缓冲
標(biāo)準(zhǔn)I/O庫提供緩沖的目的是盡可能減少使用read和write調(diào)用的次數(shù)。它也對每個I/O流自動地進(jìn)行緩沖管理,從而避免了應(yīng)用程序需要考慮這一點所帶來的麻煩。
標(biāo)準(zhǔn)I/O提供了三種類型的緩沖:
(1)全緩沖。這種情況下,在填滿標(biāo)準(zhǔn)I/O緩沖區(qū)后才進(jìn)行實際的I/O操作。對于駐留在磁盤上的文件通常是由標(biāo)準(zhǔn)I/O庫實施全緩沖的。在一個流上執(zhí)行第一次I/O操作時,相關(guān)標(biāo)準(zhǔn)I/O函數(shù)通常調(diào)用malloc獲得需使用的緩沖區(qū)。
術(shù)語沖洗(flush)說明標(biāo)準(zhǔn)I/O緩沖區(qū)的寫操作。緩沖區(qū)可由標(biāo)準(zhǔn)I/O例程自動沖洗(例如當(dāng)填滿一個緩沖區(qū)時),或者可以調(diào)用函數(shù)fflush沖洗一個流。值得引起注意的是在UNIX環(huán)境中,flush有兩種意思:在標(biāo)準(zhǔn)I/O庫方面,flush(沖洗)意味著將緩沖區(qū)中的內(nèi)容寫到磁盤上(該緩沖區(qū)可能只是局部填寫的)。在終端驅(qū)動程序方面,flush(刷清)表示丟棄已存儲在緩沖區(qū)中的數(shù)據(jù)。
(2)行緩沖。在這種情況下,當(dāng)在輸入和輸出中遇到換行符時,標(biāo)準(zhǔn)I/O庫執(zhí)行I/O操作。這允許我們一次輸出一個字符(用標(biāo)準(zhǔn)I/O fputc函數(shù),該函數(shù)一次只輸出一個字符,沒有換行符),但只有在寫了一行之后才進(jìn)行實際I/O操作。當(dāng)流涉及一個終端時(例如標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出),通常使用行緩沖。
對于行緩沖有兩個限制。第一,因為標(biāo)準(zhǔn)I/O庫用來收集每一行的緩沖區(qū)的長度是固定的,所以只要填滿了緩沖區(qū),那么即使還沒有寫一個換行符,也進(jìn)行I/O操作。第二,任何時候只要通過標(biāo)準(zhǔn)I/O庫要求從(a)一個不帶緩沖的流,或者(b)一個行緩沖的流(它要求從內(nèi)核得到數(shù)據(jù))得到輸入數(shù)據(jù),那么就會造成沖洗所有行緩沖輸出流。在(b)中帶了一個括號中的說明,其理由是,所需的數(shù)據(jù)可能已在該緩沖區(qū)中,它并不要求在需要數(shù)據(jù)時才從內(nèi)核讀數(shù)據(jù)。很明顯,從不帶緩沖的一個流中進(jìn)行輸入((a)項)要求當(dāng)時從內(nèi)核得到數(shù)據(jù)。
(3)不帶緩沖。標(biāo)準(zhǔn)I/O庫不對字符進(jìn)行緩沖存儲。例如,如果用標(biāo)準(zhǔn)I/O函數(shù)fputs寫15個字符到不帶緩沖的流中,則該函數(shù)很可能用write系統(tǒng)調(diào)用函數(shù)將這些字符立即寫到相關(guān)聯(lián)的打開文件上。
標(biāo)準(zhǔn)出錯流stderr通常是不帶緩沖的,這就使得出錯信息可以盡快顯示出來,而不管它們是否含有一個換行符。
ISO C要求下列緩沖特征:
- 當(dāng)且僅當(dāng)標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出并不涉及交互式設(shè)備時,它們才是全緩沖的。
- 標(biāo)準(zhǔn)出錯絕不會是全緩沖的。
但是,這并沒有告訴我們?nèi)绻麡?biāo)準(zhǔn)輸入和輸出涉及交互式設(shè)備時,它們是不帶緩沖的還是行緩沖的;以及標(biāo)準(zhǔn)出錯是不帶緩沖的還是行緩沖的。很多系統(tǒng)默認(rèn)使用下列類型的緩沖:
- 標(biāo)準(zhǔn)出錯是不帶緩沖的。
- 如若是涉及終端設(shè)備的其他流,則它們是行緩沖的;否則是全緩沖的。
對任何一個給定的流,如果我們并不喜歡這些系統(tǒng)默認(rèn)的情況,則可調(diào)用下列兩個函數(shù)中的一個更改緩沖類型:
#include <stdio.h> void setbuf( FILE *restrict fp, char *restrict buf ); int setvbuf( FILE *restrict fp, char *restrict buf, int mode, size_t size ); 返回值:若成功則返回0,若出錯則返回非0值這些函數(shù)一定要在流已被打開后調(diào)用,而且也應(yīng)該在對該流執(zhí)行任何一個其他操作之前調(diào)用。
可以使用setbuf函數(shù)打開或關(guān)閉緩沖機制。為了帶緩沖進(jìn)行I/O,參數(shù)buf必須指向一個長度為BUFSIZE的緩沖區(qū)(該常量定義在<stdio.h>中)。通常在此之后該流就是全緩沖的,但是如果流與一個終端相關(guān),那么某些系統(tǒng)也可將其設(shè)置為行緩沖。為了關(guān)閉緩沖,將buf設(shè)置為NULL。
使用setvbuf,我們可以精確地指定所需的緩沖類型。這是用mode參數(shù)實現(xiàn)的:
| _IOFBF | 全緩沖 |
| _IOLBF | 行緩沖 |
| _IONBF | 不帶緩沖 |
如果指定一個不帶緩沖的流,則忽略buf和size參數(shù)。如果指定全緩沖或行緩沖,則buf和size可選擇地指定一個緩沖區(qū)及其長度。如果該流是帶緩沖的,而buf是NULL,則標(biāo)準(zhǔn)I/O庫將自動地為該流分配適當(dāng)長度的緩沖區(qū)。適當(dāng)長度指的是由常量BUFSIZE所指定的值。
某些C函數(shù)庫實現(xiàn)使用stat結(jié)構(gòu)中的成員st_blksize所指定的值決定最佳I/O緩沖區(qū)長度。GNU C函數(shù)庫就使用這種方法。
表5-1列出了這兩個函數(shù)的動作,以及它們的各個選項。
要了解,如果在一個函數(shù)內(nèi)分配一個自動變量類的標(biāo)準(zhǔn)I/O緩沖區(qū),則從該函數(shù)返回之前,必須關(guān)閉該流。另外,有些實現(xiàn)將緩沖區(qū)的一部分用于存放它自己的管理操作信息,所以可以存放在緩沖區(qū)中的實際數(shù)據(jù)字節(jié)數(shù)少于size。一般而言,應(yīng)由系統(tǒng)選擇緩沖區(qū)的長度,并自動分配緩沖區(qū)。在這種情況下關(guān)閉此流時,標(biāo)準(zhǔn)I/O庫將自動釋放緩沖區(qū)。
任何時候,我們都可以強制沖洗一個流。
#include <stdio.h> int fflush( FILE *fp ); 返回值:若成功則返回0,若出錯則返回EOF此函數(shù)使該流所有未寫的數(shù)據(jù)都被傳送至內(nèi)核。作為一個特例,如若fp是NULL,則此函數(shù)將導(dǎo)致所有輸出流被沖洗。
?
?
本篇博文內(nèi)容摘自《UNIX環(huán)境高級編程》(第二版),僅作個人學(xué)習(xí)記錄所用。關(guān)于本書可參考:http://www.apuebook.com/。
?
轉(zhuǎn)載于:https://www.cnblogs.com/nufangrensheng/p/3505307.html
總結(jié)
- 上一篇: 在论坛中出现的各种疑难问题:日志收缩问题
- 下一篇: [转载]jquery cookie的用法