C++에는 디스크의 파일에 버퍼를 쓰는 std::fwrite()
이 있습니다.fwrite가 출력을 버퍼링합니까?
해당 fwrite 구현 내에 버퍼가 있는지 말해 줄 수 있습니까?
즉 fwrite()를 여러 번 (말하면 10 번) 호출하면 실제로 파일 I/O가 10 번 다른 호출을합니까?
나는 이것을 우분투 10.04 환경에 묻습니다.
C++에는 디스크의 파일에 버퍼를 쓰는 std::fwrite()
이 있습니다.fwrite가 출력을 버퍼링합니까?
해당 fwrite 구현 내에 버퍼가 있는지 말해 줄 수 있습니까?
즉 fwrite()를 여러 번 (말하면 10 번) 호출하면 실제로 파일 I/O가 10 번 다른 호출을합니까?
나는 이것을 우분투 10.04 환경에 묻습니다.
예, 버퍼링됩니다. 버퍼의 크기는 BUFSIZ
으로 정의됩니다. (Thanks @ladenedge.) 충분히 큰 10 개의 연산은 10 개의 시스템 호출을 야기 할 것입니다.
std::setbuf
및 std::setvbuf
을 사용하여 자체 버퍼를 설정할 수도 있습니다.
cstdio
의 함수는 C에서 상속됩니다. C++의 기본 인터페이스는 fstream
및 filebuf
입니다.
다릅니다. 대부분의 플랫폼에서 파일 IO는 캐시되므로 캐시 된 데이터를 디스크에 쓰는 데는 fflush()
호출이 있습니다.이 점에서 첫 번째 질문에 대한 대답은 (예 : "예"이고 두 번째는 "아니오"입니다. 즉, 특정 플랫폼에 대한 모든 상상력을 통해 그러한 방식이 보장되는 것은 아닙니다. 일반적으로 표준은 구현이 아닌 그러한 기능을위한 인터페이스 만 지정합니다. 또한 fwrite()
을 호출하면 캐시가 "완전"상태가되면 암시 적으로 플러시가 발생할 수 있습니다.이 경우 fwrite()
을 호출하면 실제로 파일 IO가 트리거 될 수 있습니다. 특히 많은 양의 데이터로 fwrite()
을 호출하는 경우 특히 그렇습니다.
라이브러리 IO 기능이 버퍼링되지만 시스템 IO 기능은 보통 다음과 같습니다. 그뿐만 아니라 디스크 컨트롤러에도 캐시가 있습니다. 사실, 보통 디스크의 문제는 출력물이 캐시에 저장되는 것을 확신하지 못하지만 필요할 때 디스크에 실제로 쓰여지는지 확인하는 것입니다.:) –
@Matteo, 나는 당신이 무슨 뜻인지 안다. 예를 들어 fwrite를 사용하여 에러 로그를 작성하는 것은 프로그램이 충돌하기 전에 * 캐시가 디스크에 쓰여지는 경우에 흥미로울 수있다. 다행히도 거기에 fflush가 있습니다 ... – Mac
"표준은 그러한 기능을위한 인터페이스 만 지정하고 구현은 아닙니다"라고 정확하지 않습니다. 표준은 구현을 지정하지 않지만 동작을 지정합니다. 이 경우 표준에서는 FILE *이 버퍼됨을 지정합니다 (C++은 C 표준을 17.3.1.4/1에 통합하고 C 표준은 FILE *을 7.19.5.6/2에 버퍼로 정의 함). –
라이브러리 구현에 따라 다릅니다. dtruss 또는 strace과 같은 것을보고 구현에 의해 실제로 호출 된 시스템 호출을 확인할 수 있습니다.
왜이 점에 대해 신경 쓰시나요?
내 프로그램이 fwrite()를 많이 수행하고 있습니다. 그리고 그것은 우분투 10.04에서 실행됩니다. 성능상의 이유로 fwrite()를 호출하기 전에 직접 IO를 버퍼링해야하는지 알고 싶습니다. – michael
@michael : 예, I/O를 버퍼링합니다. 'fwrite'에 대한 호출 횟수를 줄이면 최소한 코드의 분기 수가 줄어 듭니다. 분기 후에는 많은 프로세서가 명령 캐시를 다시로드하므로 성능이 저하됩니다. 또한 실행할 코드가 적어 프로그램이 빠릅니다. –
병목 현상을 찾기 위해 코드의 프로필을 작성하는 것이 가장 좋은 이유는 무엇입니까? – WhirlWind
나는 표준이 이것에 대해 아무 것도 말하지 않는다고 생각하지만, 일반적으로 운영체제는 수행 할 I/O 작업의 수를 결정하지 않습니다. 1 일 수도 있고 10 일 수도 있습니다. 데이터 크기가 클 경우 더 많을 수도 있습니다. 대부분의 운영 체제에서는 I/O가 어떻게 동작해야하는지 제어 할 수 있지만 AFAIK에는 이식 할 수있는 방법이 없습니다. (종종 어쨌든 원하지 않는 경우)
FILE*
입출력은 버퍼링 될 수 있지만 반드시 필요하지는 않습니다 (스트림별로 다를 수 있음). 또한 버퍼링을 수행하는 방법은 여러 가지가 있습니다 (버퍼가 가득 찰 때까지 버퍼가 플러시되지 않거나 fflush
에 대한 명시 적 호출이 이루어 지거나 버퍼가 플러시되지 않는 곳에서 EOL이 표시 될 때까지 라인 버퍼 됨). 버퍼링을 모두 해제 할 수도 있습니다.
setvbuf 호출을 사용하여 버퍼링 유형을 변경할 수 있습니다.
stdio.h에 정의 된대로 기본 버퍼 크기는 BUFSIZ입니다. 물론 호출자는 해당 정보가 필요하지 않습니다. 일부 시스템에서는'setbuf'를 사용하여 크기를 제어 할 수 있습니다. – ladenedge
Lol, 정확히 말하면 2 초 전 "ladenedge 1 sec ago" – Potatoswatter