http://blog.chinaunix.net/uid-223060-id-2127383.html
2008
主要涉及到 setbuf, fflush, fsync,sync等函數(shù)。
首先來說輸入輸出庫的緩沖。
The three types of buffering available are unbuffered, block buffered, and line buffered. When an output stream is unbuffered, information appears on thedestination file or terminal as soon as written; when it is
block buffered many characters are saved up and written as a block; when it is line buffered characters are
saved up until a newline is output or input is read from any stream attached to a terminal device (typically
stdin). The function fflush(3) may be used to force the block out early. (See fclose(3).) Normally all files
are block buffered. When the first I/O operation occurs on a file, malloc(3) is called, and a buffer is
obtained. If a stream refers to a terminal (as stdout normally does) it is line buffered. The standard error
stream stderr is always unbuffered by default.
一般來說,block buffered的效率高些,將多次的操作合并成一次操作?,F(xiàn)在標(biāo)準(zhǔn)庫里緩存一部分,
直到該緩沖區(qū)滿了,或者程序顯示的調(diào)用fflush時(shí),將進(jìn)行更新操作。
而setbuf 則可以設(shè)置該緩沖區(qū)的大小。
#include
void setbuf(FILE *stream, char *buf);
這個(gè)函數(shù)應(yīng)該必須在如何輸出被寫到該文件之前調(diào)用。一般放在main里靠前面的語句!
但是setbuf有個(gè)經(jīng)典的錯(cuò)誤,man手冊(cè)上也提到了,c陷阱和缺陷上也提到了
You must make sure that both buf and the space it points tostill exist by the time stream is closed, which also happens atprogram termination. For example, the following is illegal:
#include
int main()
{
char buf[BUFSIZ];
setbuf(stdin, buf);
printf("Hello, world!\n");
return 0;
}
之前C運(yùn)行庫所必須進(jìn)行的清理工作的一部分,但是此時(shí)buf字符數(shù)組已經(jīng)釋放。
修改的方法是 將buf設(shè)置為static,或者全局變量; 或者調(diào)用malloc來動(dòng)態(tài)申請(qǐng)內(nèi)存。
char * malloc();
setbuf(stdout,malloc(BUFSIZE));
這里不需要判斷malloc的返回值,如果malloc調(diào)用失敗,將返回一個(gè)null指針,setbuf的第二個(gè)參數(shù)可以
是null,此時(shí)不進(jìn)行緩沖!
對(duì)應(yīng)的,fflush函數(shù)則刷新緩沖區(qū),將緩沖區(qū)上的內(nèi)容更新到文件里。
#include
int fflush(FILE *stream);
The function fflush forces a write of all user-space buffereddata for the given output or update stream via the stream underlyingwrite function. The open status of the stream is unaffected.
If the stream argument is NULL, fflush flushes all open output streams.
但是fflush僅僅刷新C庫里的緩沖。
其他的一些數(shù)據(jù)的刷新需要調(diào)用fsync或者sync!!
Note that fflush() only flushes the user space buffers provided by the C library. To ensure that the data is physically stored on disk the kernel buffers must be flushed too, e.g. with sync(2) or fsync(2).
fsync和sync最終將緩沖的數(shù)據(jù)更新到文件里。
#include
int fsync(int fd);
fsync copies all in-core parts of a file to disk, and waits until thedevice reports that all parts are on stable storage. It also updatesmetadata stat information. It does not necessarily ensure that theentry in the directory containing the file has also reacheddisk. For that an explicit fsync on the file descriptor of thedirectory is also needed.
NAME
sync - commit buffer cache to disk
SYNOPSIS
#include
void sync(void);
DESCRIPTION
sync first commits inodes to buffers, and then buffers to disk.
ERRORS
This function is always successful.
同步命令sync就直接調(diào)用了sync函數(shù)來更新磁盤上的緩沖??!
傳統(tǒng)的UNIX實(shí)現(xiàn)在內(nèi)核中設(shè)有緩沖區(qū)高速緩存或頁面高速緩存,大多數(shù)磁盤I/O都通過緩沖進(jìn)行。當(dāng)將數(shù)據(jù)寫入文件時(shí),內(nèi)核通常先將該數(shù)據(jù)復(fù)制到其中一個(gè)緩沖區(qū)中,如果該緩沖區(qū)尚未寫滿,則并不將其排入輸出隊(duì)列,而是等待其寫滿或者當(dāng)內(nèi)核需要重用該緩沖區(qū)以便存放其他磁盤塊數(shù)據(jù)時(shí),再將該緩沖排入輸出隊(duì)列,然后待其到達(dá)隊(duì)首時(shí),才進(jìn)行實(shí)際的I/O操作。這種輸出方式被稱為延遲寫(delayedwrite)(Bach [1986]第3章詳細(xì)討論了緩沖區(qū)高速緩存)。
延遲寫減少了磁盤讀寫次數(shù),但是卻降低了文件內(nèi)容的更新速度,使得欲寫到文件中的數(shù)據(jù)在一段時(shí)間內(nèi)并沒有寫到磁盤上。當(dāng)系統(tǒng)發(fā)生故障時(shí),這種延遲可能造成文件更新內(nèi)容的丟失。為了保證磁盤上實(shí)際文件系統(tǒng)與緩沖區(qū)高速緩存中內(nèi)容的一致性,UNIX系統(tǒng)提供了sync、fsync和fdatasync三個(gè)函數(shù)。
改過的塊緩沖區(qū)排入寫隊(duì)列,然后就返回,它并不等待實(shí)際寫磁盤操作結(jié)束。
通常稱為update的系統(tǒng)守護(hù)進(jìn)程會(huì)周期性地(一般每隔30秒)調(diào)用sync函數(shù)。這就保證了定期沖洗內(nèi)核的塊緩沖區(qū)。命令sync(1)也調(diào)用sync函數(shù)。
fsync函數(shù)只對(duì)由文件描述符filedes指定的單一文件起作用,并且等待寫磁盤操作結(jié)束,然后返回。fsync可用于數(shù)據(jù)庫這樣的應(yīng)用程序,這種應(yīng)用程序需要確保將修改過的塊立即寫到磁盤上。
fdatasync函數(shù)類似于fsync,但它只影響文件的數(shù)據(jù)部分。而除數(shù)據(jù)外,fsync還會(huì)同步更新文件的屬性。
本書說明的所有四種平臺(tái)都支持sync和fsync函數(shù)。但是,F(xiàn)reeBSD 5.2.1和Mac OS X 10.3并不支持fdatasync。
聯(lián)系客服