#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