`stdio`は、出力が端末にリダイレクトされるのかディスクファイルにリダイレクトされるのかをどのように識別しますか? [コピー]

`stdio`は、出力が端末にリダイレクトされるのかディスクファイルにリダイレクトされるのかをどのように識別しますか? [コピー]
#include <stdio.h>
#include <unistd.h>

int main(void)
{
  printf("If I had more time, \n");
  write(STDOUT_FILENO, "I would have written you a shorter letter.\n", 43);

  return 0;
}

私は読んだ

I / O処理関数(stdioライブラリ関数)とシステムコールは、パフォーマンスを向上させるためにバッファリング操作を実行します。この関数はユーザー空間のprintf(3)バッファを使用します。stdioまた、カーネルはI / Oをバッファリングするため、システムコールごとにディスクに書き込む必要はありません。デフォルトでは、出力ファイルが端末の場合、printf(3)この関数の書き込みline-bufferedstdio使用は次のとおりです。ラインバッファたとえば、stdout改行文字が見つかった場合、'\n' バッファは次にフラッシュされます。バッファキャッシュ。ただし、端末でない場合、つまり標準出力がディスクファイルにリダイレクトされると、バッファにスペースがなくなったとき(またはファイルストリームが閉じられたとき)にのみコンテンツがフラッシュされます。上記のプログラムの標準出力が端末の場合、最初の呼び出しはprintfそのバッファを次にフラッシュします。カーネルバッファ(バッファキャッシュ)改行文字が見つかると、'\n'上記の文と同じ順序で出力されます。ただし、出力がディスクファイルにリダイレクトされると、バッファはフラッシュされず、システムコールのstdio内容がwrite(2)カーネルバッファに最初に到達するため、呼び出しの内容の前にディスクにフラッシュされますprintf

ターミナルはいつ頃stdoutですか?

If I had more time,
I would have written you a shorter letter.

stdoutディスクファイルはいつですか?

I would have written you a shorter letter.
If I had more time,

しかし、私の質問は、端末に送信するのかディスクファイルに送信するのかをどうやってstdio library functions知ることができるのかということです。stdout

答え1

printf(私の特定のlibc)は、内部的にnewfstatat()stdoutファイル記述子(たとえば1)からシステムコールを実行します。

入力している通常のファイルまたは文字デバイス(擬似端末など)の場合、カーネルはこれらのst_modeフィールドを入力します。S_IFREGs_IFCHR

私が見つけた方法:

gcc -o foo foo.c # compile your program
strace -o file.strace ./foo > tempfile
strace -o term.strace ./foo
diff *.strace #and look for things towards the end that concern the 1 file descriptor 

関連情報