[解決済み] C言語でバッファリングを理解する
質問
特にC言語プログラミングにおけるバッファリングの奥深さを理解するのに苦労しており、このトピックについて本当に長い間検索しましたが、今まで満足できるものが見つかりませんでした。
もう少し具体的に説明します。 バッファリングの背後にあるコンセプト(異なるハードウェアデバイスによる操作の調整や、これらのデバイスの速度差の最小化)は理解していますが、これらやその他のバッファリングの潜在的な理由について、より完全な説明をお願いします(完全というのは、より長く、より深いということです)。
他の質問としては、バッファフラッシュにおけるいくつかのルールが私のプログラムによって守られていないことに気づいたことです。
#include <stdio.h>
int main(void)
{
FILE * fp = fopen("hallo.txt", "w");
fputc('A', fp);
getchar();
fputc('A', fp);
getchar();
return 0;
}
このプログラムは、差し迫った入力が最初の getchar() が呼ばれたときに直ちに任意のストリームをフラッシュすることを示すためのものですが、何度やっても、何度修正しても、これは単に
stdout
(この場合
printf()
このため、私はこのルールを間違って理解しているのか、それとも他に考慮すべきことがあるのでしょうか。
Windows 8.1 で Gnu GCC を使用しています。
更新しました。
そういえば、あるサイトで、文字列リテラルをバッファと呼んだり、配列をバッファと呼んだりしているのを読んだのですが、これは正しいのでしょうか、それとも私が何か見逃しているのでしょうか? この点についても解説をお願いします。
どのように解決するのですか?
単語 バッファ は、コンピュータサイエンスにおいて様々な意味で使われています。より一般的な意味では、最終目的地(または他のバッファ)に処理またはコピーされるまでの間、データを一時的に保存するメモリの部分を指します。
質問にあったように、バッファには多くの種類がありますが、大まかなグループ分けとして
-
ハードウェア・バッファ。ハードウェアデバイスに移動する前にデータが格納されるバッファです。または、HWデバイスから受信したデータをアプリケーションで処理するまで保存しておくバッファです。これは、I/O操作には通常メモリとタイミングの要件があり、バッファがそれを満たすために必要です。メモリに直接読み書きするDMAデバイスを考えてみてください。メモリが適切にセットアップされていないと、システムがクラッシュする可能性があります。また、マイクロ秒以下の精度が必要なサウンドデバイスでは、動作が悪くなります。
-
キャッシュバッファー。ファイルやデバイスに書き込んだり、デバイスから読み込んだりする前にデータをグループ化するバッファで、一般的にパフォーマンスが改善されます。
-
ヘルパーバッファ。このようなバッファにデータを出し入れするのは、アルゴリズムにとって簡単だからです。
ケース 2 は、あなたの
FILE*
の例です。を呼び出したとします。
書く
システムコール(
WriteFile()
Win32の場合、呼び出しだけで1ms、1バイトごとに1usかかります(現実にはもっと複雑です)。では、そうすると。
FILE *f = fopen("file.txt", "w");
for (int i=0; i < 1000000; ++i)
fputc('x', f);
fclose(f);
バッファリングがない場合、このコードでは
1000000 * (1ms + 1us)
, 約1000秒になります。しかし、10000バイトのバッファがあれば、10000バイトずつのシステムコールが100回だけ発生することになります。そうすると
100 * (1ms + 10000us)
. わずか0.1秒です!
また、OSが独自のバッファリングを行い、最も効率的なサイズを使って実際のデバイスにデータを書き込むことに注意してください。これは、HWとキャッシュバッファを同時に行うことになりますね。
フラッシュに関する問題ですが、ファイルは通常、閉じたときか手動でフラッシュされるだけです。いくつかのファイル、例えば
stdout
はラインフラッシュされます。
'\n'
が書き込まれます。また
stdin/stdout
は特別です。
stdin
では
stdout
がフラッシュされます。他のファイルはそのままで
stdout
. これは、インタラクティブなプログラムを書いている場合に便利です。
私のケースその3は、例えばこんな時です。
FILE *f = open("x.txt", "r");
char buffer[1000];
fgets(buffer, sizeof(buffer), f);
int n;
sscanf(buffer, "%d", &n);
バッファを使ってファイルから1行を保持し、その行からデータをパースするのです。そうです。
fscanf()
行の種類を分析したり、コメントをスキップしたり、行数を数えたり...。
また、例えばキーボードから一度に1バイトずつ受け取る場合を想像してみてください。バッファに文字を蓄積しておき、Enterキーが押されたときにその行を解析するだけです。ほとんどの対話型コンソールプログラムがそうなっています。
関連
-
[解決済み】Cコンパイルエラー。"変数サイズのオブジェクトが初期化されていない可能性がある"
-
[解決済み] c - 初期化がキャストなしでポインタから整数を作る、さらに2つのコンパイラーエラー
-
[解決済み】C言語におけるファイルスコープでの可変長配列の変更
-
[解決済み】LEALアセンブリ命令は何をするのですか?
-
[解決済み】「構造体でもユニオンでもないものにメンバー'*******'を要求する」とはどういう意味ですか?
-
[解決済み】C言語で入力が整数型かどうかチェックする
-
[解決済み】スタックスマッシュを検出しました
-
[解決済み】.axfファイルとは何ですか?
-
[解決済み】警告:式の結果が未使用の場合
-
[解決済み] ソケットプログラミングのためのINADDR_ANYの理解
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】単項演算子「*」の型が無効(「int」がある)C言語でのエラー
-
[解決済み】Cygwin - Makefile-error: ターゲット `main.o' のレシピに失敗しました。
-
[解決済み】 switch case: error: case label does not reduce to an integer constant
-
[解決済み] テスト
-
[解決済み】ヒープ割り当てで初期化されていない値が作成された
-
[解決済み】fgetsによるセグメンテーションフォールト(コアダンプ) - と思う。
-
[解決済み】argv[]をint型として取得するには?
-
[解決済み】「複数の定義」「最初に定義されたのはここです」エラーについて
-
[解決済み] char pointers: 'char*' から 'char' への無効な変換?
-
[解決済み】C言語でpow( )への未定義参照、math.hを含むにもかかわらず【重複】。