![`stdio`는 출력이 터미널로 리디렉션되는지 아니면 디스크 파일로 리디렉션되는지 어떻게 식별합니까? [복사]](https://linux55.com/image/213104/%60stdio%60%EB%8A%94%20%EC%B6%9C%EB%A0%A5%EC%9D%B4%20%ED%84%B0%EB%AF%B8%EB%84%90%EB%A1%9C%20%EB%A6%AC%EB%94%94%EB%A0%89%EC%85%98%EB%90%98%EB%8A%94%EC%A7%80%20%EC%95%84%EB%8B%88%EB%A9%B4%20%EB%94%94%EC%8A%A4%ED%81%AC%20%ED%8C%8C%EC%9D%BC%EB%A1%9C%20%EB%A6%AC%EB%94%94%EB%A0%89%EC%85%98%EB%90%98%EB%8A%94%EC%A7%80%20%EC%96%B4%EB%96%BB%EA%B2%8C%20%EC%8B%9D%EB%B3%84%ED%95%A9%EB%8B%88%EA%B9%8C%3F%20%5B%EB%B3%B5%EC%82%AC%5D.png)
#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-buffered
및stdio
사용은 다음과 같습니다.라인 버퍼예를 들어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_IFREG
s_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