2010-05-10 2 views
9

C++에는 디스크의 파일에 버퍼를 쓰는 std::fwrite()이 있습니다.fwrite가 출력을 버퍼링합니까?

해당 fwrite 구현 내에 버퍼가 있는지 말해 줄 수 있습니까?

즉 fwrite()를 여러 번 (말하면 10 번) 호출하면 실제로 파일 I/O가 10 번 다른 호출을합니까?

나는 이것을 우분투 10.04 환경에 묻습니다.

답변

10

예, 버퍼링됩니다. 버퍼의 크기는 BUFSIZ으로 정의됩니다. (Thanks @ladenedge.) 충분히 큰 10 개의 연산은 10 개의 시스템 호출을 야기 할 것입니다.

std::setbufstd::setvbuf을 사용하여 자체 버퍼를 설정할 수도 있습니다.

cstdio의 함수는 C에서 상속됩니다. C++의 기본 인터페이스는 fstreamfilebuf입니다.

+2

stdio.h에 정의 된대로 기본 버퍼 크기는 BUFSIZ입니다. 물론 호출자는 해당 정보가 필요하지 않습니다. 일부 시스템에서는'setbuf'를 사용하여 크기를 제어 할 수 있습니다. – ladenedge

+0

Lol, 정확히 말하면 2 초 전 "ladenedge 1 sec ago" – Potatoswatter

6

다릅니다. 대부분의 플랫폼에서 파일 IO는 캐시되므로 캐시 된 데이터를 디스크에 쓰는 데는 fflush() 호출이 있습니다.이 점에서 첫 번째 질문에 대한 대답은 (예 : "예"이고 두 번째는 "아니오"입니다. 즉, 특정 플랫폼에 대한 모든 상상력을 통해 그러한 방식이 보장되는 것은 아닙니다. 일반적으로 표준은 구현이 아닌 그러한 기능을위한 인터페이스 만 지정합니다. 또한 fwrite()을 호출하면 캐시가 "완전"상태가되면 암시 적으로 플러시가 발생할 수 있습니다.이 경우 fwrite()을 호출하면 실제로 파일 IO가 트리거 될 수 있습니다. 특히 많은 양의 데이터로 fwrite()을 호출하는 경우 특히 그렇습니다.

+1

라이브러리 IO 기능이 버퍼링되지만 시스템 IO 기능은 보통 다음과 같습니다. 그뿐만 아니라 디스크 컨트롤러에도 캐시가 있습니다. 사실, 보통 디스크의 문제는 출력물이 캐시에 저장되는 것을 확신하지 못하지만 필요할 때 디스크에 실제로 쓰여지는지 확인하는 것입니다.:) –

+0

@Matteo, 나는 당신이 무슨 뜻인지 안다. 예를 들어 fwrite를 사용하여 에러 로그를 작성하는 것은 프로그램이 충돌하기 전에 * 캐시가 디스크에 쓰여지는 경우에 흥미로울 수있다. 다행히도 거기에 fflush가 있습니다 ... – Mac

+0

"표준은 그러한 기능을위한 인터페이스 만 지정하고 구현은 아닙니다"라고 정확하지 않습니다. 표준은 구현을 지정하지 않지만 동작을 지정합니다. 이 경우 표준에서는 FILE *이 버퍼됨을 지정합니다 (C++은 C 표준을 17.3.1.4/1에 통합하고 C 표준은 FILE *을 7.19.5.6/2에 버퍼로 정의 함). –

0

라이브러리 구현에 따라 다릅니다. dtruss 또는 strace과 같은 것을보고 구현에 의해 실제로 호출 된 시스템 호출을 확인할 수 있습니다.

왜이 점에 대해 신경 쓰시나요?

+0

내 프로그램이 fwrite()를 많이 수행하고 있습니다. 그리고 그것은 우분투 10.04에서 실행됩니다. 성능상의 이유로 fwrite()를 호출하기 전에 직접 IO를 버퍼링해야하는지 알고 싶습니다. – michael

+0

@michael : 예, I/O를 버퍼링합니다. 'fwrite'에 대한 호출 횟수를 줄이면 최소한 코드의 분기 수가 줄어 듭니다. 분기 후에는 많은 프로세서가 명령 캐시를 다시로드하므로 성능이 저하됩니다. 또한 실행할 코드가 적어 프로그램이 빠릅니다. –

+0

병목 현상을 찾기 위해 코드의 프로필을 작성하는 것이 가장 좋은 이유는 무엇입니까? – WhirlWind

0

나는 표준이 이것에 대해 아무 것도 말하지 않는다고 생각하지만, 일반적으로 운영체제는 수행 할 I/O 작업의 수를 결정하지 않습니다. 1 일 수도 있고 10 일 수도 있습니다. 데이터 크기가 클 경우 더 많을 수도 있습니다. 대부분의 운영 체제에서는 I/O가 어떻게 동작해야하는지 제어 할 수 있지만 AFAIK에는 이식 할 수있는 방법이 없습니다. (종종 어쨌든 원하지 않는 경우)

2

FILE* 입출력은 버퍼링 될 수 있지만 반드시 필요하지는 않습니다 (스트림별로 다를 수 있음). 또한 버퍼링을 수행하는 방법은 여러 가지가 있습니다 (버퍼가 가득 찰 때까지 버퍼가 플러시되지 않거나 fflush에 대한 명시 적 호출이 이루어 지거나 버퍼가 플러시되지 않는 곳에서 EOL이 표시 될 때까지 라인 버퍼 됨). 버퍼링을 모두 해제 할 수도 있습니다.

setvbuf 호출을 사용하여 버퍼링 유형을 변경할 수 있습니다.

관련 문제