2010-04-19 4 views
7

따라서 FILE 스트림은 입출력 버퍼를 모두 가질 수 있습니다. setvbuf을 사용하여 출력 스트림을 조정할 수 있습니다 (입력 버퍼 크기 및 동작으로 재생할 수있는 방법을 알지 못합니다).기본 파일 입출력 버퍼링?

또한 기본적으로 버퍼는 BUFSIZ (이것이 POSIX 또는 C 일 경우 확실하지 않음)입니다. stdin/stdout/stderr의 의미가 무엇인지는 분명하지만 새로 열리는 파일의 기본값은 무엇입니까? 입력과 출력 모두를 위해 버퍼링됩니까? 아니면 그냥 하나?

버퍼링되면 출력이 블록 또는 회선 모드로 기본 설정됩니까?

편집 : Jonathan Leffler의 답변이 실제 프로그램에 어떻게 영향을 주 었는지 확인하기 위해 몇 가지 테스트를 수행했습니다. 만약 당신이 다음에 쓰기를 읽는 것 같습니다. write에 의해, 입력 버퍼의 미사용 부분이 완전히 드롭됩니다. 사실, 올바른 파일 오프셋을 유지하기 위해 수행되는 탐색이있을 것입니다.

/* input file contains "ABCDEFGHIJKLMNOPQRSTUVWXYZ" */ 
#include <stdio.h> 
#include <stdlib.h> 

int main() { 

    FILE *f = fopen("test.txt", "r+b"); 
    char ch; 
    fread(&ch, 1, 1, f); 
    fwrite("test", 4, 1, f); 
    fclose(f); 
    return 0; 
} 

는 다음과 같은 시스템의 결과

호출 :

read(3, "ABCDEFGHIJKLMNOPQRSTUVWXYZ\n", 4096) = 27 // attempt to read 4096 chars, got 27 
lseek(3, -26, SEEK_CUR)     = 1  // at this point, I've done my write already, so forget the 26 chars I never asked for and seek to where I should be if we really just read one character... 
write(3, "test", 4)      = 4  // and write my test 
close(3)        = 0 

이 내가 그들에게 표준 라이브러리가 될 수있는 방법으로 지금까지 매우 흥미로운 일이 될 것으로 명확하게 구현 세부 사항은 동안 나는이 간단한 테스트 프로그램을 사용 구현. 귀하의 통찰력있는 답변을 주신 Jonathan에게 감사드립니다.

+0

BUFSIZ는 C 표준에 속하므로 POSIX에도 있습니다. –

+1

정의되지 않은 동작 :'fread()'와'fwrite()'사이에서'fseek()'해야합니다. 그렇지 않으면, 구현이 만족스럽지 않을 수 있습니다. –

답변

6

단일 파일 스트림에는 단일 버퍼가 있습니다. 파일이 입력 및 출력 모두에 사용되는 경우, 읽기 및 쓰기 (또는 쓰기 및 읽기) 조작간에 적절한 조작 (fseek() 또는 동등한 조작)을 수행해야합니다.

표준 채널의 버퍼링 동작은 플랫폼에 따라 다릅니다.

일반적으로 stdout은 출력이 터미널로 전송 될 때 라인 버퍼링됩니다. 그러나 stdout이 터미널이 아닌 파일이나 파이프로 이동하는 경우 가장 일반적으로 전체 버퍼링으로 전환합니다.

일반적으로 stderr는 오류 메시지가 표시되도록하기 위해 (예 : 프로그램이 중단 되더라도) 라인 버퍼링되거나 버퍼되지 않습니다.

일반적으로 stdin은 라인 버퍼링됩니다. 즉, 입력 내용을 편집 할 수있는 기회를 얻게됩니다 (오류에 대한 백 스페이스 등). 드물게 이것을 조정할 것입니다. 입력이 파일 (또는 파이프)에서 오는 경우에도 동작이 다를 수 있습니다.

새로 열린 파일은 일반적으로 완전히 버퍼링됩니다. 특정 구현은 장치가 터미널 인 경우 라인 버퍼링으로 변경할 수 있습니다.

두 개의 버퍼가 있다는 전제가 잘못되었습니다.


제 C99의 7.19.3, 그것은 말한다 :

프로그램 시작시

은, 세 개의 텍스트 스트림이 미리 정의되어 명시 적으로 열 필요가 없다 - 표준 입력 (기존의 입력을 읽기 위해), 표준 출력 (쓰기 용 일반 출력) 및 표준 오류 (진단 출력 작성 용).처음에는 이 열렸으므로 표준 오류 스트림은 완전히 버퍼링되지 않습니다. 기본 입력 및 표준 출력 스트림은 대화 형 장치로 을 참조하지 않도록 스트림을 결정할 수있는 경우에만 완전히 버퍼링됩니다. 원래 명시된 바와 같이

그래서, 표준 에러는 중 버퍼링 또는 라인 (완전히 버퍼링되지 않습니다) 버퍼링.

+0

두 개의 버퍼가 허용되지 않습니까? 모든 표준에서 기본 버퍼가 처음 사용할 때 할당되었다고 말한 후 버퍼가 두 개 뿐이라면 구현하기가 훨씬 쉽다는 것을 알았습니다. 이것은 입력 연산이 출력 문자의 버퍼를 지울 수 있지만 (버퍼가 현재는 명확하고 입력에 사용될 수 있음) 명확한 반면, 역은 처리하기가 더 복잡하기 때문에 이것을 말합니다. –

+0

나는 표준이'stderr'가 기본적으로 버퍼되지 않는다고 말하고 있음을 발견했다. –

+0

두 개의 버퍼가 훨씬 더 복잡합니다 (두 배의 메모리가 필요함). 예를 들어, 입력 버퍼를 읽었을 때 fseek()를 방금 읽은 곳으로 되돌리고 write()를하면 (가상) 출력 버퍼의 데이터를 (가설 적) 입력 버퍼. –