버퍼링 된 IO와 버퍼링되지 않은 IO


84

기본적으로 프로그램의 I / O가 버퍼링된다는 것을 배웠습니다. 즉, 임시 저장소에서 요청하는 프로그램으로 제공됩니다. 버퍼링이 IO 성능을 향상 시킨다는 것을 이해합니다 (시스템 호출을 줄임으로써). setvbufC 에서와 같이 버퍼링을 비활성화하는 예를 보았습니다 . 두 모드의 차이점은 무엇이며 언제 다른 모드를 사용해야합니까?

답변:


127

계속하기 전에 출력이 기록되었는지 확인할 때마다 버퍼링되지 않은 출력을 원합니다. 한 가지 예는 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                |
+---------------------------------------+

그래프는 훌륭합니다. 언급 할 가치가있는 한 가지는 FILE객체 (스트림)의 내부 버퍼가 fgets필수 버퍼 매개 변수와 완전히 다르다는 것 입니다. 이것은 내가 그것을 알아내는 코드를 작성하기 전에 몇 시간 동안 나를 혼란스럽게 만들었습니다. QAQ
Rick

37

디스크에 쓸 준비가 된 큰 바이트 시퀀스가 ​​이미 있고 중간에있는 두 번째 버퍼에 추가 복사하지 않으려는 경우 버퍼링되지 않은 출력을 원합니다 .

버퍼링 된 출력 스트림은 쓰기 결과를 중간 버퍼에 누적하여 충분한 데이터가 누적 (또는 flush()요청) 될 때만 OS 파일 시스템으로 전송합니다 . 이렇게하면 파일 시스템 호출 수가 줄어 듭니다. 파일 시스템 호출은 대부분의 플랫폼에서 비용이 많이들 수 있으므로 (short에 비해 memcpy) 많은 수의 작은 쓰기를 수행 할 때 버퍼링 된 출력이 순이익이됩니다. 버퍼링되지 않은 출력은 일반적으로 보낼 큰 버퍼가 이미있을 때 더 좋습니다. 중간 버퍼에 복사해도 OS 호출 수가 더 줄어들지 않고 추가 작업이 발생합니다.

버퍼링되지 않은 출력은 데이터가 디스크에 도달하는지 확인하는 것과 관련없습니다 . 이 기능은에서 ​​제공 flush()하며 버퍼링 된 스트림과 버퍼링되지 않은 스트림 모두에서 작동합니다. 버퍼링되지 않은 IO 쓰기는 데이터가 물리적 디스크에 도달했음을 보장하지 않습니다. OS 파일 시스템은 데이터 사본을 무기한 보유 할 수 있으며 원하는 경우 디스크에 기록하지 않습니다. 를 호출 할 때만 디스크에 커밋하면됩니다 flush(). ( 당신을 대신하여 close()전화 할 것 flush()입니다.)


호출 flush()하면 디스크에 기록이 보장됩니까? 나는 그것이 디스크의 버퍼로만 전달되었다고 생각했습니다.
jrdioko

2
O_SYNC쓰기를 보장 해야 합니다.
moshbear 2011

디스크에 기록되는 것에 대한 버퍼링되지 않은 IO ks. 따라서 winapi의 경우 버퍼링되지 않음 (중간 버퍼가 없지만 디스크에 직접 기록됨)이라는 용어는 FILE_FLAG_NO_BUFFERING 및 FILE_FLAG_WRITE_THROUGH를 사용하여 CreateFile을 호출하여 각 쓰기 후 데이터가 직접 지속되도록합니다. 다른 OS에 대해서는 알지 못합니다.
Martin Kosicky
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.