バッファ付きI/OとバッファなしI/Oの区別と連絡

7809 ワード

回転元:http://blog.csdn.net/lmh12506/article/details/6803847
まず,バッファを持たない概念を理解する必要がある:バッファを持たないとは,カーネルがバッファを提供しないのではなく,単純なシステム呼び出しであり,関数ライブラリの呼び出しではない.システムカーネルはディスクの読み書きに対してすべて1つのブロックバッファを提供して、write関数でそれに対してデータを書く時、直接システム呼び出しを呼び出して、データをブロックバッファに書き込んで並んで、ブロックバッファが一定の量に達する時、やっとデータをディスクに書きます.したがって、バッファリングされていないI/Oとは、プロセスがバッファリング機能を提供しないことを意味する(ただし、カーネルはバッファリングを提供する).writeまたはread関数を呼び出すたびに、直接システム呼び出しが行われます.バッファ付きI/Oとは、プロセスが入出力ストリームを改善し、ストリームバッファを提供することであり、fwrite関数ネットワークディスクでデータを書く場合、まずストリームバッファにデータを書き込み、ストリームバッファがいっぱいになったり、ストリームバッファをリフレッシュしたりするなどの条件に達した場合、カーネルが提供したブロックバッファにデータを一度に送り、ブロックバッファを介してディスクに書き込む.(二重バッファ)したがって、バッファ付きI/Oは、ディスクに同じデータ量を書き込む場合、バッファなしのI/Oよりもシステム呼び出しの回数が少なくなります.次のものは私がネットで調べたこの2つの理解で、私はまだ十分だと思います.
以下では,open,writeなどの基本系IOの帯域バッファリングと非帯域バッファリングの違いについて主に論じる.
キャッシュ付きファイル操作は標準Cライブラリの実現であり、初めてキャッシュ付きファイル操作関数を呼び出すと標準ライブラリは自動的にメモリを割り当て、一定サイズのコンテンツを読み出してキャッシュに格納する.したがって、以降の読み取りと書き込みは、ハードディスク(HDD)上のファイルに対して直接行われるのではなく、メモリ内のキャッシュに対して行われます.ハードディスク(HDD)からファイルを読み込むか、ハードディスク(HDD)にファイルを書き込むかについて、標準ライブラリのメカニズム制御があります.キャッシュされていないファイル操作は通常、システムが提供するシステム呼び出しであり、より低級であり、ハードディスクから直接ファイルを読み取り、書き込む.IOボトルネックのため、速度が望ましくなく、原子操作にはプログラマー自身が保証する必要があるが、適切に使用すれば効率は悪くない.また、標準ライブラリにおけるキャッシュ付きファイルIOは、呼び出しシステムが提供するキャッシュなしIOで実現される.
「バッファなしという用語は、各readおよびwriteがカーネル内のシステム呼び出しを呼び出すことを意味する.すべてのディスクI/Oはカーネルのブロックバッファ(カーネルのバッファキャッシュとも呼ばれる)を通過しなければならない.唯一の例外は元のディスクデバイスに対するI/Oである.readまたはwriteのデータがカーネルにバッファリングされる以上、用語「バッファなしI/O」「この2つの関数は、ユーザーのプロセス中に自動的にバッファリングされず、readまたはwriteのたびにシステム呼び出しが行われることを意味します.」--
プログラムでopenとwriteで開いて作成し「hello world」を「ファイルtest.txtを書き込み、fopenとfwriteでファイルtest 2.txtを操作します.プログラムがopenとfopenに実行された後、sleepは15秒で、lsで表示してファイルを生成しましたか.openで開いたtest.txtが現れ、fopenで開いたtest 2.txtも現れました.プログラムがwriteとfwriteを実行した後、15秒の睡眠中にcatでtest.txtを表示します.その内容は「hello,world」;しかしこの時catでtest 2.txtを見て、その内容は空です.睡眠が終わった後、close(fd)を実行し、その時catでtest 2.txtを見て、その内容も「hello,world」.この例はopenとwriteがバッファリングされていないことを証明している.すなわち、プログラムはio操作を実行するとすぐに実行され、システムが提供するバッファにとどまらず、close操作が完了するまで実行する必要はない.それに比べてfopenとfwriteはバッファリングされており、(一般的には)fclose操作が完了するまで実行されない.
関連するソースコードの例は次のとおりです.
#include <unistd.h>

#include <iostream>

#include <fcntl.h>

#include <string>

#include <sys/types.h>

#include <sys/stat.h>



using namespace std;



int main(){

int fd;

FILE *file;

char *s="hello,world
"; if((fd=open("test.txt",O_WRONLY|O_CREAT,S_IRUSR|S_IWUSR))==-1){ cout<<"Error open file"<<endl; return -1; } if((file=fopen("test2.txt","w"))==NULL){ cout<<"Error Open File."<<endl; return -1; } cout<<"File has been Opened."<<endl; sleep(15); if(write(fd,s,strlen(s))<strlen(s)){ cout<<"Write Error"<<endl; return -1; } if(fwrite(s,sizeof(char),strlen(s),file)<strlen(s)){ cout<<"Write Error in 2."<<endl; return -1; } cout<<"After write"<<endl; sleep(15); cout<<"After sleep."<<endl; close(fd); return 0; }

詳細は以下を参照してください.http://blog.csai.cn/user1/27828/archives/2007/14285.html ssize_t write(int filedes,const void*buff,size_t nbytes)とsize_t fwrite(const void*ptr,size_t size,size_t nobj,FILE*fp)で、unixシステムのキャッシュ付きI/OとキャッシュなしI/Oの違いを説明します.
まず,バンドキャッシュとは,上記の2つの関数のbuffパラメータを指すものではないという概念を明らかにする.
ファイルにデータが書き込まれると、カーネルはまずそのデータをキャッシュに書き込み、キャッシュが満たされていない場合は出力キューに入れない.キャッシュが満たされているか、カーネルが再びこのキャッシュを再使用する必要がある場合に入力キューに並べ替え、キューに到着してから実際のI/O操作を行う.つまり、このときデータをディスクに書き込む技術を遅延書き込みという..
カーネルに設定されたキャッシュが100バイトであると仮定し、writeを使用し、buffのsizeが10である場合、9つの同じbuffをファイルに書き込む場合は、9回のwrite、つまり9回のシステム呼び出しを呼び出す必要があります.この場合もハードディスクには書かれていません.すぐにハードディスクに書き、fsyncを呼び出す場合は、実際のI/O操作を行うことができます.
標準I/O、つまりキャッシュ付きI/OはFILE*を採用し、FILEは実際にストリームを管理するために必要なすべての情報を含んでいる:実際のI/Oのファイル記述子、ストリームキャッシュへのポインタ(標準I/Oキャッシュ、mallocによって割り当てられ、ユーザー状態プロセス空間のキャッシュとも呼ばれ、カーネルが設定したキャッシュとは異なる),キャッシュ長さ,現在キャッシュ中のバイト数,エラーフラグなど,ストリームキャッシュの長さが50バイトであると仮定し,以上のデータをファイルに書き込むと,2回のシステム呼び出し(fwrite呼び出しwriteシステム呼び出し)しか必要としないが,まずストリームキャッシュにデータを書き,それがいっぱいになった後あるいはfflushを呼び出すとカーネルキャッシュに埋め込まれるため,2回のシステム呼び出しwriteを行った.
fflushはストリームのすべての未書き込みデータをカーネル(カーネルバッファ)に送り込み(リフレッシュ)、fsyncはすべてのカーネルバッファのデータをファイル(ディスク)に書き込む.
キャッシュを持たないreadとwriteはfread/fwriteなどのストリーム関数に対して説明される.freadとfwriteはユーザ関数(3)であるため、ユーザ層でデータのキャッシュを1回行い、read/writeはシステム呼び出し(2)であるだから彼らはユーザー層にキャッシュがないので、readとwriteはキャッシュのないIOと呼ばれていますが、実はカーネルにとってキャッシュが行われていますが、ユーザー層は見えません.
詳細は以下を参照してください.http://blog.sina.com.cn/s/blog_4a92ce12010004ub.html