`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 

관련 정보