기본적으로 프로그램의 I / O가 버퍼링된다는 것을 배웠습니다. 즉, 임시 저장소에서 요청하는 프로그램으로 제공됩니다. 버퍼링이 IO 성능을 향상 시킨다는 것을 이해합니다 (시스템 호출을 줄임으로써). setvbuf
C 에서와 같이 버퍼링을 비활성화하는 예를 보았습니다 . 두 모드의 차이점은 무엇이며 언제 다른 모드를 사용해야합니까?
답변
계속하기 전에 출력이 기록되었는지 확인할 때마다 버퍼링되지 않은 출력을 원합니다. 한 가지 예는 C 런타임 라이브러리의 표준 오류입니다. 이는 일반적으로 기본적으로 버퍼링되지 않습니다. 오류는 (희망적으로) 드물기 때문에 즉시 알고 싶을 것입니다. 반면에 표준 출력 은 단순히 더 많은 데이터가 통과 할 것이라고 가정하기 때문에 버퍼링됩니다.
또 다른 예는 로깅 라이브러리입니다. 로그 메시지가 프로세스의 버퍼 내에 보관되고 프로세스가 코어를 덤프하면 출력이 기록되지 않을 가능성이 매우 높습니다.
또한 최소화되는 것은 시스템 호출뿐 아니라 디스크 I / O도 마찬가지입니다. 프로그램이 한 번에 한 바이트 씩 파일을 읽는다고 가정 해 보겠습니다. 버퍼링되지 않은 입력을 사용하면 어쨌든 전체 블록을 읽어야 할지라도 모든 바이트에 대해 (상대적으로 매우 느린) 디스크로 이동합니다 (디스크 하드웨어 자체에 버퍼가있을 수 있지만 여전히 디스크 컨트롤러로 이동합니다). 메모리 내 액세스보다 느릴 것입니다).
버퍼링을 통해 전체 블록을 한 번에 버퍼로 읽어 들인 다음 개별 바이트가 (메모리 내, 믿을 수 없을 정도로 빠른) 버퍼 영역에서 사용자에게 전달됩니다.
버퍼링은 다음 예와 같이 다양한 형태를 취할 수 있습니다.
+-------------------+-------------------+
| Process A | Process B |
+-------------------+-------------------+
| C runtime library | C runtime library | C RTL buffers
+-------------------+-------------------+
| OS caches | Operating system buffers
+---------------------------------------+
| Disk controller hardware cache | Disk hardware buffers
+---------------------------------------+
| Disk |
+---------------------------------------+
답변
디스크에 쓸 준비가 된 큰 바이트 시퀀스가 이미 있고 중간에있는 두 번째 버퍼에 추가 복사 를 하지 않으려는 경우 버퍼링되지 않은 출력을 원합니다 .
버퍼링 된 출력 스트림은 쓰기 결과를 중간 버퍼에 누적하여 충분한 데이터가 누적 (또는 flush()
요청) 될 때만 OS 파일 시스템으로 전송합니다 . 이렇게하면 파일 시스템 호출 수가 줄어 듭니다. 파일 시스템 호출은 대부분의 플랫폼에서 비용이 많이들 수 있으므로 (short에 비해 memcpy
) 많은 수의 작은 쓰기를 수행 할 때 버퍼링 된 출력이 순이익이됩니다. 버퍼링되지 않은 출력은 일반적으로 보낼 큰 버퍼가 이미있을 때 더 좋습니다. 중간 버퍼에 복사해도 OS 호출 수가 더 줄어들지 않고 추가 작업이 발생합니다.
버퍼링되지 않은 출력은 데이터가 디스크에 도달하는지 확인하는 것과 관련 이 없습니다 . 이 기능은에서 제공 flush()
하며 버퍼링 된 스트림과 버퍼링되지 않은 스트림 모두에서 작동합니다. 버퍼링되지 않은 IO 쓰기는 데이터가 물리적 디스크에 도달했음을 보장하지 않습니다. OS 파일 시스템은 데이터 사본을 무기한 보유 할 수 있으며 원하는 경우 디스크에 기록하지 않습니다. 를 호출 할 때만 디스크에 커밋하면됩니다 flush()
. ( 당신을 대신하여 close()
전화 할 것 flush()
입니다.)