標準入力リダイレクトを使用してプログラムを実行しています。
$ prog < f
この場合、標準入力は完全にバッファリングされます。
バッファリングされていないか、ラインバッファリングされるようにする方法はありますか?
編集する。
プログラムのソースコードを変更する必要はありません(つまり、setvbuf()を使用)。
答え1
バッファリングなし通常、出力に適しています。出力バッファリングは、アプリケーションが書き込み前に出力が十分な量に蓄積されるまで、出力を維持してI / O量を最小限に抑えることです。
入力時にアプリケーションができることは、一度に入力から読み取るバイト数を調整するだけです(まあ、多くのバイトを受信すると保証されないため、少なくとも要求するバイト数は調整されます。ファイルバイト数が少なくなる可能性があります)たとえば、パイプまたはttyデバイスの場合は、その時点で利用可能です)。
stdio
入力ストリームのバッファを解放し、バッファサイズを1バイトに設定するために使用されます。
一度に 1 バイトずつ読み込むのは非効率的で、通常は必要ありません。
必要な状況は、検索できない入力(パイプであるため、通常のファイルのf
場合はユーザーのものではありません)から読み取るときであり、他のプロセスが読み取りをprog
再開できるように、ファイル内の特定のポイントで読み取りを停止する必要がある場合です。そこにいつ。
たとえば、
seq 10 | { grep -q 5; cat; }
6〜10行を出力するには、ファイルの読み取りを停止してから行cat
ですgrep
(これはパイプなので検索できません)。
上記のコマンドは、grep
すべての出力を一度に読み取ったため、何も返しません。seq
次の点に注意してください。
{ seq 5; sleep 1; seq 6 10; } | { grep -q 5; cat; }
それでは効果があるでしょう。grep
大きなバッファも要求しますが、当時は最初の5行しか使用できないため、grep
処理されて5行で終了します。つまり、バッファがいっぱいになるか、eofに達して処理を開始するまで入力を蓄積しません(私が知っている唯一のコマンドはこのようなことを行いますmawk
)。
特定のコマンドを使用すると、GNUシステムとFreeBSDシステムで入力バッファリングを調整できますstdbuf -i
。 (unbuffer)の使用はstdbuf -i0
(サイズ1のバッファで読み取る)と同じで、stdbuf -i1
入力が一度に1バイトずつ読み取られます。
GNUでは機能しませんが、grep
GNUでは機能しますsed
。
$ seq 10 | { sed -n /5/q; cat; }
$ seq 10 | { stdbuf -i0 sed -n /5/q; cat; }
6
7
8
9
10
以下を使用して、strace
sのサイズが変更されていることを確認できますread()
。
$ seq 5 | { strace -e read sed -n /2/q; cat; }
[...]
read(0, "1\n2\n3\n4\n5\n", 4096) = 10
+++ exited with 0 +++
$ seq 5 | { strace -e read stdbuf -i0 sed -n /2/q; cat; }
[...]
read(0, "1", 1) = 1
read(0, "\n", 1) = 1
read(0, "2", 1) = 1
read(0, "\n", 1) = 1
+++ exited with 0 +++
3
4
5
$ seq 5 | { strace -e read stdbuf -i1 sed -n /2/q; cat; }
[...]
read(0, "1", 1) = 1
read(0, "\n", 1) = 1
read(0, "2", 1) = 1
read(0, "\n", 1) = 1
+++ exited with 0 +++
3
4
5
答え2
いいえ、そこではありません。
質問への変更そうする方法は明示的に除外されます。。プログラムで目的のタスクを実行するようにプログラムを編集するか、ツールを使用して動的ローダーとCランタイムライブラリの内部に接続して、プログラムの起動時に呼び出されるようにsetvbuf
スケジュールできます。
その機能が許可されていない場合、setvbuf
これを行う方法はありません。電話をかけるsetvbuf
のは人がしなければならないことです。