2012-04-25 4 views
8

Linux의 파이프에 데이터를 쓰려면 fwrite() 함수 호출을 사용하고 있습니다.fwrite()의 버퍼링 동작 이해

이전에 작은 덩어리의 데이터 (평균 20 바이트)에 대해 fwrite()이 반복적으로 호출되었으며 버퍼링은 fwrite()으로 남았습니다. strace는 한 번에 4096 바이트의 데이터가 쓰여지고 있음을 보여 주었다.

이 글쓰기 과정이 내 프로그램의 병목이었습니다. 그래서 코드에서 데이터를 64KB 블록으로 버퍼링 한 다음 fwrite()을 사용하여 한 번에 전체 블록을 작성하기로 결정했습니다. setvbuf()을 사용하여 FILE * 포인터를 'No Buffering'으로 설정했습니다.

예상대로 성능이 향상되지 않았습니다.

더 중요한 것은 strace 출력은 데이터가 한 번에 4096 바이트 씩 쓰여지고 있음을 나타냅니다. 누군가 제게이 행동을 설명해 주시겠습니까? 64KB의 데이터로 fwrite()을 호출하는 경우 한 번에 4096 바이트 만 쓰는 이유는 무엇입니까?

FILE * 포인터를 사용하여 파이프에 데이터를 쓰는 대신 fwrite()의 대안이 있습니까?

+0

코드를 표시 할 수 있습니까? – tuxuday

+1

@Shailesh_Tainwala : 당신은 C++로 코드를 작성하고 있을지 모르지만 이것은 C++가 아닌 c 질문입니다. 'fwrite()'는 C++ 함수가 아닌 c 함수입니다. 질문에 태그를 추가하여 더 많은 잠재 고객을 확보 할 수있게되었습니다. –

답변

8

4096은 파이프 라인의 기초가되는 Linux 기계에서 유래했습니다. 두 곳이 있습니다. 하나는 파이프 라인의 용량입니다. 이 용량은 32 비트 i386 시스템에서 4096 바이트 인 Linux의 이전 버전에서 하나의 시스템 페이지입니다. (리눅스의 최신 버전에서는 64K이다.)

그 4096 바이트 문제를 일으키는 또 다른 곳은 정의 된 상수 PIPE_BUF인데, 원자 적으로 처리되는 것으로 보증되는 바이트 수이다. Linux에서는 4096 바이트입니다. 이 제한은 차단 또는 비 차단으로 파이프 라인을 설정했는지 여부에 따라 달라집니다. 피투성이의 모든 세부 사항에 대해서는 man -S7 pipe을하십시오.

많은 양의 데이터를 빠른 속도로 교환하려는 경우 파이프 사용에 대해 다시 생각해 볼 수 있습니다. 리눅스 박스를 사용하기 때문에 공유 메모리가 옵션입니다. 파이프를 사용하여 비교적 작은 양의 데이터를 신호 메커니즘으로 보낼 수 있습니다.

+0

또 다른 가능한 리눅스 옵션은 fwrite() 대신 open()과 splice()를 사용하는 것입니다. –

4

당신은 버퍼링 동작을 변경하려는 경우, 당신이 그렇게 즉시 수행해야합니다 후 fopen (또는 I 전에/O 표준 파일 핸들 stdin, stdout, stderr에 대한). 또한 버퍼링을 비활성화하고 버퍼를 직접 관리하려고하지 마십시오. 오히려 적절하게 사용할 수 있도록 사용자의 64K 버퍼를 setvbuf으로 지정하십시오.

실제로 버퍼링을 수동으로 관리하려면 stdio을 사용하지 마십시오. open, writeclose 호출을 사용하십시오.