read(2)
(で)試してみるunistd.h
と、5文字が出力されるはずです。libc ( fread(3)
、fwrite(3)
など) を使用する場合、通常はページのサイズ (ほとんどの場合 4 kiB) である内部 libc バッファーを使用しています。
初めて 5 バイトを呼び出すと、libc は4096 バイトfread()
の内部処理を実行し、次は、使用する構造に関連付けられたバッファーに libc が既に持っているバイトを返すだけだと思います。4096 に到達するまで。4097 番目のバイトは別の 4096 バイトなどを発行します。read()
fread()
FILE
read
printf()
これは、最初の引数としてを使用する場合など、記述時にも発生しますfprintf()
。stdout()
libc はwrite(2)
直接呼び出しませんが、代わりに内部バッファー (これも 4096 バイト) にデータを入れます。呼び出すとフラッシュされます
fflush(stdout);
自分自身、または送信されたバイト内にバイト 0x0a (ASCII の改行) が見つかったときはいつでも。
試してみてください。
#include <stdio.h> /* for printf() */
#include <unistd.h> /* for sleep() */
int main(void) {
printf("the following message won't show up\n");
printf("hello, world!");
sleep(3);
printf("\nuntil now...\n");
return 0;
}
ただし、これは機能します (libc のバッファリングを使用しません):
#include <stdio.h> /* for printf() */
#include <unistd.h> /* for sleep(), write(), and STDOUT_FILENO */
int main(void) {
printf("the following message WILL show up\n");
write(STDOUT_FILENO, "hello!", 6);
sleep(3);
printf("see?\n");
return 0;
}
STDOUT_FILENO
標準出力 (1) のデフォルトのファイル記述子です。
改行があるたびにフラッシュすることは、端末のユーザーがメッセージを即座に見るために不可欠であり、Unix 環境で多く行われる行ごとの処理にも役立ちます。
そのため、libc がread()
およびwrite()
syscall を直接使用してバッファを埋めたりフラッシュしたりしても (ちなみに、Microsoft の C 標準ライブラリの実装では Windows のものを使用している必要があります (おそらくReadFile
およびWriteFile
))、これらの syscall は libc をまったく認識していません。これにより、両方を使用すると興味深い動作が発生します。
#include <stdio.h> /* for printf() */
#include <unistd.h> /* for write() and STDOUT_FILENO */
int main(void) {
printf("1. first message (flushed now)\n");
printf("2. second message (without flushing)");
write(STDOUT_FILENO, "3. third message (flushed now)", 30);
printf("\n");
return 0;
}
出力:
1. first message (flushed now)
3. third message (flushed now)2. second message (without flushing)
(2 番目の前に 3 番目!)。
また、libc のバッファリングを無効にできることに注意してくださいsetvbuf(3)
。例:
#include <stdio.h> /* for setvbuf() and printf() */
#include <unistd.h> /* for sleep() */
int main(void) {
setvbuf(stdout, NULL, _IONBF, 0);
printf("the following message WILL show up\n");
printf("hello!");
sleep(3);
printf("see?\n");
return 0;
}
私は試したことはありませんが、キャラクターデバイスを ing したFILE*
ときに得られるものと同じことができfopen()
、これの I/O バッファリングを無効にできると思います。
FILE* fh = fopen("/dev/my-char-device", "rb");
setvbuf(fh, NULL, _IONBF, 0);