linux 标准IO缓冲机制探究
生活随笔
收集整理的這篇文章主要介紹了
linux 标准IO缓冲机制探究
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
一、什么是緩存I/O(Buffered I/O)
緩存I/O又被稱作標(biāo)準(zhǔn)I/O,大多數(shù)文件系統(tǒng)默認(rèn)I/O操作都是緩存I/O。在Linux的緩存I/O機(jī)制中,操作系統(tǒng)會將I/O的數(shù)據(jù)緩存在文件系統(tǒng)的頁緩存(page cache)中,也就是說,數(shù)據(jù)會先被拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū)中,然后才會從操作系統(tǒng)內(nèi)核的緩沖區(qū)拷貝到應(yīng)用程序的地址空間。
1.緩存I/O有以下優(yōu)點(diǎn):
A.緩存I/O使用了操作系統(tǒng)內(nèi)核緩沖區(qū),在一定程度上分離了應(yīng)用程序空間和實(shí)際的物理設(shè)備。
B.緩存I/O可以減少讀盤的次數(shù),從而提高性能
當(dāng)應(yīng)用程序嘗試讀取某塊數(shù)據(jù)的時(shí)候,如果這塊數(shù)據(jù)已經(jīng)存放在頁緩存中,那么這塊數(shù)據(jù)就可以立即返回給應(yīng)用程序,而不需要經(jīng)過實(shí)際的物理讀盤操作。當(dāng)然,如果數(shù)據(jù)在應(yīng)用程序讀取之前并未被存放在頁緩存中,那么就需要先將數(shù)據(jù)從磁盤讀到頁緩存中去。對于寫操作來說,應(yīng)用程序也會將數(shù)據(jù)先寫到頁緩存中去,數(shù)據(jù)是否被立即寫到磁盤上去取決于應(yīng)用程序所采用的寫操作機(jī)制:如果用戶采用的是同步寫機(jī)制,那么數(shù)據(jù)會立即被寫回到磁盤上,應(yīng)用程序會一直等到數(shù)據(jù)被寫完為止;如果用戶采用的是延遲寫機(jī)制,那么應(yīng)用程序就完全不需要等到數(shù)據(jù)全部被 寫回到磁盤,數(shù)據(jù)只要被寫到頁緩存中去就可以了。在延遲寫機(jī)制的情況下,操作系統(tǒng)會定期地將放在頁緩存中的數(shù)據(jù)刷到磁盤上。與異步寫機(jī)制不同的是,延遲寫機(jī)制在數(shù)據(jù)完全寫到磁盤上得時(shí)候不會通知應(yīng)用程序,而異步寫機(jī)制在數(shù)據(jù)完全寫到磁盤上得時(shí)候是會返回給應(yīng)用程序的。所以延遲寫機(jī)制本省是存在數(shù)據(jù)丟失的風(fēng)險(xiǎn)的,而異步寫機(jī)制則不會有這方面的擔(dān)心。
2.緩存I/O的缺點(diǎn) 在緩存I/O機(jī)制中,DMA方式可以將數(shù)據(jù)直接從磁盤讀到頁緩存中,或者將數(shù)據(jù)從頁緩存直接寫回到磁盤上,而不能直接在應(yīng)用程序地址空間和磁盤之間進(jìn)行數(shù)據(jù)傳輸,這樣的話,數(shù)據(jù)在傳輸過程中需要在應(yīng)用程序地址空間和頁緩存之間進(jìn)行多次數(shù)據(jù)拷貝操作,這些數(shù)據(jù)拷貝操作說帶來的cpu以及內(nèi)存開銷是非常大的。
二、文件指針
FILE指針:每個(gè)被使用的文件都在內(nèi)存中開辟一個(gè)區(qū)域,用來存放文件的有關(guān)信息,這些信息是保存在一個(gè)結(jié)構(gòu)體類型的變量中,該結(jié)構(gòu)體類型是由系統(tǒng)定義的,取名為FILE。
標(biāo)準(zhǔn)I/O庫的所有操作都是圍繞流(stream)來進(jìn)行的,在標(biāo)準(zhǔn)I/O中,流用FILE *來描敘的。
其在Linux操作系統(tǒng)中的定義:
三、行緩沖、全緩沖、不緩沖的定義
1.Fully buffered means that I/O takes place only when the buffer is fully, the process explicitly calls fflush, or the process terminates by calling exit. A common size for the standard I/O buffer is 4096 bytes;
2. Line buffered means that I/O takes place when a newline is encountered, when the process calls fflush, or when the process terminates by calling exit.
3. Unbuffered means that I/O take place each time a standard I/O output function is called.
Most unix implementations of the standard I/O libarary use the following rules.
1. Standard error is always unbuffered.
2. Standard input and standard output are fully buffered, unless they refer to a terminal device, in which case, they are line buffered.
3. All other streams are fully buffered unless they refer to a terminal device, in which case, they are line buffered.
四、一步步探究
#include?<stdio.h>
int?stream_attribute(FILE?*fp)
{
if(fp->_flags?&?_IO_UNBUFFERED)
{
printf("The IO type is unbuffered\n");
}else?if(fp->_flags?&?_IO_LINE_BUF){
printf("The IO type is line buf\n");
}else{
printf("The IO type is full buf\n");
}
printf("The IO size : %d\n",fp->_IO_buf_end?-?fp->_IO_buf_base);
return 0;
}
int?main()
{
FILE?*fp;
stream_attribute(stdin);
printf("___________________________________\n\n");
stream_attribute(stdout);
printf("___________________________________\n\n");
stream_attribute(stderr);
printf("___________________________________\n\n");
if((fp?=?fopen("test.txt","w+"))?==?NULL)
{
perror("fail to fopen");
}
stream_attribute(fp);
return 0;
}
運(yùn)行結(jié)果:
我們修改一下代碼再看 #include?<stdio.h>
int?stream_attribute(FILE?*fp)
{
if(fp->_flags?&?_IO_UNBUFFERED)
{
printf("The IO type is unbuffered\n");
}else?if(fp->_flags?&?_IO_LINE_BUF){
printf("The IO type is line buf\n");
}else{
printf("The IO type is full buf\n");
}
printf("The IO size : %d\n",fp->_IO_buf_end?-?fp->_IO_buf_base);
return 0;
}
int?main()
{
FILE?*fp;
getchar();
stream_attribute(stdin);
printf("___________________________________\n\n");
stream_attribute(stdout);
printf("___________________________________\n\n");
stream_attribute(stderr);
printf("___________________________________\n\n");
if((fp?=?fopen("test.txt","w+"))?==?NULL)
{
perror("fail to fopen");
}
printf("before write:\n");
stream_attribute(fp);
fputc('a',fp);
printf("after write:\n");
stream_attribute(fp);
return 0;
} 運(yùn)行結(jié)果:
從以上我們可以看出,標(biāo)準(zhǔn)I/O并不是一開始就分配的,只有進(jìn)行了輸入或者輸出的操作才進(jìn)行分配的,標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出默認(rèn)是全緩沖,但是如果和終端關(guān)了就是行緩沖。可以看到在linux操作系統(tǒng)中行緩沖的大小是1k,全緩沖的大小是4k。
緩存I/O又被稱作標(biāo)準(zhǔn)I/O,大多數(shù)文件系統(tǒng)默認(rèn)I/O操作都是緩存I/O。在Linux的緩存I/O機(jī)制中,操作系統(tǒng)會將I/O的數(shù)據(jù)緩存在文件系統(tǒng)的頁緩存(page cache)中,也就是說,數(shù)據(jù)會先被拷貝到操作系統(tǒng)內(nèi)核的緩沖區(qū)中,然后才會從操作系統(tǒng)內(nèi)核的緩沖區(qū)拷貝到應(yīng)用程序的地址空間。
1.緩存I/O有以下優(yōu)點(diǎn):
A.緩存I/O使用了操作系統(tǒng)內(nèi)核緩沖區(qū),在一定程度上分離了應(yīng)用程序空間和實(shí)際的物理設(shè)備。
B.緩存I/O可以減少讀盤的次數(shù),從而提高性能
當(dāng)應(yīng)用程序嘗試讀取某塊數(shù)據(jù)的時(shí)候,如果這塊數(shù)據(jù)已經(jīng)存放在頁緩存中,那么這塊數(shù)據(jù)就可以立即返回給應(yīng)用程序,而不需要經(jīng)過實(shí)際的物理讀盤操作。當(dāng)然,如果數(shù)據(jù)在應(yīng)用程序讀取之前并未被存放在頁緩存中,那么就需要先將數(shù)據(jù)從磁盤讀到頁緩存中去。對于寫操作來說,應(yīng)用程序也會將數(shù)據(jù)先寫到頁緩存中去,數(shù)據(jù)是否被立即寫到磁盤上去取決于應(yīng)用程序所采用的寫操作機(jī)制:如果用戶采用的是同步寫機(jī)制,那么數(shù)據(jù)會立即被寫回到磁盤上,應(yīng)用程序會一直等到數(shù)據(jù)被寫完為止;如果用戶采用的是延遲寫機(jī)制,那么應(yīng)用程序就完全不需要等到數(shù)據(jù)全部被 寫回到磁盤,數(shù)據(jù)只要被寫到頁緩存中去就可以了。在延遲寫機(jī)制的情況下,操作系統(tǒng)會定期地將放在頁緩存中的數(shù)據(jù)刷到磁盤上。與異步寫機(jī)制不同的是,延遲寫機(jī)制在數(shù)據(jù)完全寫到磁盤上得時(shí)候不會通知應(yīng)用程序,而異步寫機(jī)制在數(shù)據(jù)完全寫到磁盤上得時(shí)候是會返回給應(yīng)用程序的。所以延遲寫機(jī)制本省是存在數(shù)據(jù)丟失的風(fēng)險(xiǎn)的,而異步寫機(jī)制則不會有這方面的擔(dān)心。
2.緩存I/O的缺點(diǎn) 在緩存I/O機(jī)制中,DMA方式可以將數(shù)據(jù)直接從磁盤讀到頁緩存中,或者將數(shù)據(jù)從頁緩存直接寫回到磁盤上,而不能直接在應(yīng)用程序地址空間和磁盤之間進(jìn)行數(shù)據(jù)傳輸,這樣的話,數(shù)據(jù)在傳輸過程中需要在應(yīng)用程序地址空間和頁緩存之間進(jìn)行多次數(shù)據(jù)拷貝操作,這些數(shù)據(jù)拷貝操作說帶來的cpu以及內(nèi)存開銷是非常大的。
二、文件指針
FILE指針:每個(gè)被使用的文件都在內(nèi)存中開辟一個(gè)區(qū)域,用來存放文件的有關(guān)信息,這些信息是保存在一個(gè)結(jié)構(gòu)體類型的變量中,該結(jié)構(gòu)體類型是由系統(tǒng)定義的,取名為FILE。
標(biāo)準(zhǔn)I/O庫的所有操作都是圍繞流(stream)來進(jìn)行的,在標(biāo)準(zhǔn)I/O中,流用FILE *來描敘的。
其在Linux操作系統(tǒng)中的定義:
三、行緩沖、全緩沖、不緩沖的定義
1.Fully buffered means that I/O takes place only when the buffer is fully, the process explicitly calls fflush, or the process terminates by calling exit. A common size for the standard I/O buffer is 4096 bytes;
2. Line buffered means that I/O takes place when a newline is encountered, when the process calls fflush, or when the process terminates by calling exit.
3. Unbuffered means that I/O take place each time a standard I/O output function is called.
Most unix implementations of the standard I/O libarary use the following rules.
1. Standard error is always unbuffered.
2. Standard input and standard output are fully buffered, unless they refer to a terminal device, in which case, they are line buffered.
3. All other streams are fully buffered unless they refer to a terminal device, in which case, they are line buffered.
四、一步步探究
運(yùn)行結(jié)果:
我們修改一下代碼再看
從以上我們可以看出,標(biāo)準(zhǔn)I/O并不是一開始就分配的,只有進(jìn)行了輸入或者輸出的操作才進(jìn)行分配的,標(biāo)準(zhǔn)輸入和標(biāo)準(zhǔn)輸出默認(rèn)是全緩沖,但是如果和終端關(guān)了就是行緩沖。可以看到在linux操作系統(tǒng)中行緩沖的大小是1k,全緩沖的大小是4k。
原文地址: http://blog.chinaunix.net/uid-26833883-id-3198114.html
總結(jié)
以上是生活随笔為你收集整理的linux 标准IO缓冲机制探究的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: linux 进程(一)---基本概念
- 下一篇: Linux 内核自解压流程分析