파일로 리디렉션될 때 stdout에 명시적 플러시가 필요한 이유는 무엇입니까?
printf()
의 위치에 따라 달라지는 것 같습니다.stdout
.
- 한다면
stdout
콘솔로 전송됩니다.printf()
줄 바꿈으로 표시되며 새 줄이 인쇄된 후 플러시됩니다. - 한다면
stdout
, 는 ""가 아닌 한 않습니다.fflush()
이 호출됩니다. - 만약 게가면, 약에만.
printf()
앞에 됩니다.stdout
는 파일로 리디렉션되고, 후속 쓰기(파일에 대한)는 줄 바꿈 처리되며, 줄 바꿈 후 플러시됩니다.
는 언제입니까?stdout
줄 바꿈 및 , 그고언제리buff▁line언▁does제 그리고-.fflush()
호출해야 합니까?
각 항목의 최소 예:
void RedirectStdout2File(const char* log_path) {
int fd = open(log_path, O_RDWR|O_APPEND|O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO);
dup2(fd,STDOUT_FILENO);
if (fd != STDOUT_FILENO) close(fd);
}
int main_1(int argc, char* argv[]) {
/* Case 1: stdout is line-buffered when run from console */
printf("No redirect; printed immediately\n");
sleep(10);
}
int main_2a(int argc, char* argv[]) {
/* Case 2a: stdout is not line-buffered when redirected to file */
RedirectStdout2File(argv[0]);
printf("Will not go to file!\n");
RedirectStdout2File("/dev/null");
}
int main_2b(int argc, char* argv[]) {
/* Case 2b: flushing stdout does send output to file */
RedirectStdout2File(argv[0]);
printf("Will go to file if flushed\n");
fflush(stdout);
RedirectStdout2File("/dev/null");
}
int main_3(int argc, char* argv[]) {
/* Case 3: printf before redirect; printf is line-buffered after */
printf("Before redirect\n");
RedirectStdout2File(argv[0]);
printf("Does go to file!\n");
RedirectStdout2File("/dev/null");
}
을 위한 stdout
버퍼링 동작에 따라 결정됩니다.은 세 모드로 할 수 ._IOFBF
: waits to (으)까지: (으)ㄹ 때까지 기다립니다.fflush()
가한능경우),우경▁if능),_IOLBF
buffering: 플러시를 ), (라인 버퍼링: (라인 버퍼링: (라인 버퍼링 및_IONBF
(항상 직접 쓰기가 사용됨)."되며, " 러한특성대지한이며정구되, ▁the"를 통해 영향을 수 setbuf()
그리고.setvbuf()
[3] 함수. " [C99:7.19.3.3]
"프로그램 시작 시 세 개의 텍스트 스트림이 사전 정의되며 명시적으로 열 필요가 없습니다. 표준 입력(기존 입력 읽기), 표준 출력(기존 출력 쓰기) 및 표준 오류(진단 출력 쓰기).처음에 열었을 때 표준 오류 스트림은 완전히 버퍼링되지 않습니다. 스트림이 대화형 장치를 참조하지 않는다고 결정될 수 있는 경우에만 표준 입력 및 표준 출력 스트림이 완전히 버퍼링됩니다." [C99:7.19.3.7]
관찰된 행동에 대한 설명
로 결정하는 입니다.stdout
테스트는 될 때 됩니다.대부분의 libc 구현에서 이 테스트는 스트림이 처음 사용될 때 수행됩니다.
- 할 수 있습니다: 때 동 #1은 게 설 명 할 수 있 습 : 니 대 장 일 용 버 되 링 고 퍼 때 인 라 치 형 화 이 스 다 작 쉽 트 림 ▁behaviour , 되 고 ▁is 링 ▁when : ▁is 1 버 퍼 ▁explained
printf()
자동으로 플러시됩니다. - #때이 완전히 도#2제예이를 . 파일로 리디렉션할 때 스트림이 완전히 버퍼링되어 다음을 제외하고는 플러시되지 않습니다.
fflush()
엄청난 양의 데이터를 기록하지 않는 한. - 마지막으로, 기본 fd에 대한 검사를 한 번만 수행하는 구현의 경우 #3도 이해합니다.를 첫 우리가처 stdout 버퍼강에서 입니다.
printf()
stdout이 라인 분할 모드를 획득했습니다.fd를 파일로 전환할 때 여전히 라인 버퍼링 상태이므로 데이터가 자동으로 플러시됩니다.
일부 실제 구현
각 libc는 C99가 "대화형 장치"가 무엇인지 명시하지 않고 POSIX의 stdio 엔트리가 (읽기 위해 stderr을 열 필요가 있는 것을 넘어) 이를 확장하지 않기 때문에 이러한 요구 사항을 해석하는 방법에 대한 관용도를 가집니다.
Glibc. fileoalloc.c:L111 참조.사용하는 방법
stat()
fd가 tatty인지 테스트하고 그에 따라 버퍼링 모드를 설정합니다. (이것은 fileops.c.에서 호출됩니다.)stdout
처음에는 null 버퍼가 있으며 fd 1의 특성에 따라 스트림을 처음 사용할 때 할당됩니다.
버퍼링된 IO 기능과 버퍼링되지 않은 IO 기능을 잘못 결합하고 있습니다.이러한 조합은 특히 코드가 휴대 가능해야 할 때 매우 신중하게 수행되어야 합니다.(그리고 휴대할 수 없는 코드를 쓰는 것은 좋지 않습니다...)
동일한 파일 설명자에서 버퍼링된 IO와 버퍼링되지 않은 IO를 함께 사용하지 않는 것이 가장 좋습니다.
IO 기본 IO: fprintf()
,fopen()
,fclose()
,freopen()
...
않은 IO 퍼링되않 IO: write()
,open()
,close()
,dup()
...
를 할 때dup2()
stdout을 .이 함수는 다음으로 채워진 버퍼를 인식하지 못합니다.fprintf()
그래서 언제dup2()
이전 설명자 1을 닫으면 버퍼가 플러시되지 않으며 내용이 다른 출력으로 플러시될 수 있습니다.당신의 경우 2a는 다음으로 전송되었습니다./dev/null
.
해결책
당신의 경우에는 사용하는 것이 가장 좋습니다.freopen()
에 dup2()
이렇게 하면 모든 문제가 해결됩니다.
- 의 .
FILE
【例울사례 2a) - 새로 연 파일에 따라 버퍼링 모드를 설정합니다.(사례 3)
다음은 올바른 기능 구현입니다.
void RedirectStdout2File(const char* log_path) {
if(freopen(log_path, "a+", stdout) == NULL) err(EXIT_FAILURE, NULL);
}
안타깝게도 버퍼링된 IO에서는 새로 생성된 파일의 권한을 직접 설정할 수 없습니다.권한을 변경하려면 다른 호출을 사용해야 합니다. 그렇지 않으면 이식할 수 없는 glibc 내선 번호를 사용할 수 있습니다.를 참조하십시오.
설명자를 안 설명자를 제거합니다.close(fd)
그리고 가까운 stdout_bak_fd
메시지가 파일에서만 인쇄되도록 하려면 이 옵션을 선택합니다.
언급URL : https://stackoverflow.com/questions/13932932/why-does-stdout-need-explicit-flushing-when-redirected-to-file
'programing' 카테고리의 다른 글
코틀린 및 @유효한 스프링 주석 (0) | 2023.07.30 |
---|---|
jQuery 게시 요청이 중단되었습니다.사후 매개 변수의 절반만 도착 (0) | 2023.07.30 |
Oracle에 C#을 연결하는 중 (0) | 2023.07.30 |
PHP - 각 루프에 대한 변수 앞의 앰퍼샌드 (0) | 2023.07.25 |
외부 키 추가 오류: ORA-02298: 유효성을 검사할 수 없음 - 상위 키를 찾을 수 없음 (0) | 2023.07.25 |