ごく一般的な理解という意味では、reotantanさんのご理解は間違っていないですが、厳密に言えば、C言語のストリームという言葉は、いわゆるバッファリングとは無関係の概念を表しています。
詳しくは こちら をご覧頂ければと思いますが、ストリームとは、プログラムが文字を読み書きする対象すべてを一元的に扱うためのインターフェイスであり、抽象的な概念に過ぎません。
ファイルもキーボードもコンソールのディスプレイも、すべてがストリームです。
これはちょうど、Unix系のOSで、入出力の対象となるあらゆるデバイスを**仮想ファイルシステム(VFS)**という抽象化された管理機構によって一元的に管理しているのと同じです。(参照)
OSのファイルシステムの場合、具体的な実装として、ext4 や Btrfs、NFS などを使用目的に合わせて選択しますが、それぞれのファイルシステムは独自のバッファリング機構を持っています。
C言語のストリームも同様で、
バッファリングしないと、ストリームに対し、文字を一字づつ読み込みまたは書き込みます。バッファリングすると、書き込みに対しては、文字を受け取り、バッファが満杯になると書き込みます。読み込みに対しては、文字を渡し、バッファが空になると、満たします。
が、これらは使用目的に応じてプログラマーが選択します。
( getchar や putchar ) 誤記訂正→ read
やwrite
のように、ストリームに対するアクセスを、OSのシステムコールを直接呼び出すことで実現した関数は「低水準入出力関数」と呼ばれますが、これがいわゆるバッファリングなしです。
この場合、ストリームの 中 に滞留する文字は無いため、通常はストリームの存在を意識する事はあまりなく教科書の説明にも登場しないです。
一方、gets
やputs
などの「高水準入出力関数」は、「ファイル構造体 (FILE) 」というデータを介してファイルにアクセスします。このファイル構造体は、いわゆるバッファ(=メモリー上に確保された領域)をソフトウェア的に表現したものであり、構造体をどのように定義するかによってバッファリング動作が決まります。(詳細はこちらを参照)
つまり、高水準入出力関数を使用する場合は自動的にバッファリングされる事になり、しかも教科書ではバッファリング動作の説明のためにストリームという用語を何度も繰り返すので、「ストリーム=バッファリングあり」と誤解されているのだと思います。
さらに言えば、このバッファは、ファイル構造体という形でC言語処理系が用意するものであり、OSの動作とは無関係です。
一方、OSの方は、プログラム(C言語処理系)の側がバッファリングするかどうかに関わりなく、ファイルシステムとしてのバッファリングを行うのが普通です。
ですから、以下のご質問
例えば打った文字や数字は一旦バッファ(あるメモリ領域)に保存されて、必要になったらバッファから取り出すという事ですか?ただし、バッファがいっぱいになったらOSが自動的にファイルへ書きこむとはどういう事でしょうか?
の直接の回答としては、
- 「低水準入出力関数」を使用した場合は、OSのVFSとの間で即時に文字のやりとりが実施される
- 「高水準入出力関数」を使用した場合は、バッファ(=ファイル構造体)の単位でOSのVFSとやりとりされる
ただし、実際にファイルに 物理的に(HDDに) 書き込まれるのは、OSのVFS側でバッファが一杯になったタイミングです。
とは言え、プログラムからはVFSしか見えない(OSのバッファリング動作は隠蔽されている)ので、バッファリングあり(高水準入出力関数を使用)の場合でも、ファイル構造体の中身だけを意識していれば良い、ということになります。
次に、
このストリーム(流れ)により,プログラム側では1文字ずつ読み書きする処理であっても,ファイルへのアクセスが効率的に行われるわけです。
という点についてですが、この効率的かどうかについても、やはり目的次第です。
通常のアプリケーションプログラムの場合、いわゆる文章を行単位に処理する事が多く、その場合にはバッファリングを行いつつレコード番号によってアクセスできた方が速いし楽です。
しかし、リアルタイムOSや、いわゆる組み込み系ソフトのようにクリティカルな処理の求められる場合には、勝手にバッファリングされると困る場合もあります。
一見、不便で出番の少ない「低水準入出力関数」がいつまでも無くならない理由は、そういうところにもあると思います。
以上、かなり細かくなってしまいましたが、ご参考になれば幸いです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2015/09/08 13:03
2015/09/08 13:16
2015/09/08 13:30