2012-04-25 36 views
8

Tôi đang sử dụng lệnh gọi hàm fwrite() để ghi dữ liệu vào một đường ống trên Linux.Hiểu hành vi đệm của fwrite()

Trước đó, fwrite() đã được gọi cho khối dữ liệu nhỏ (trung bình 20 byte) nhiều lần và bộ đệm được để lại fwrite(). strace trên quá trình cho thấy rằng 4096 byte dữ liệu đã được viết tại một thời điểm.

Hóa ra quy trình viết này là nút cổ chai trong chương trình của tôi. Vì vậy, tôi quyết định để đệm dữ liệu trong mã của tôi vào khối 64KB và sau đó viết toàn bộ khối tại một thời điểm sử dụng fwrite(). Tôi đã sử dụng setvbuf() để đặt con trỏ FILE * thành 'No Buffering'.

Cải thiện hiệu suất không đáng kể như tôi mong đợi.

Quan trọng hơn, đầu ra strace cho thấy dữ liệu vẫn đang được viết 4096 byte tại một thời điểm. Ai đó có thể giải thích hành vi này cho tôi không? Nếu tôi đang gọi fwrite() với 64KB dữ liệu, tại sao nó chỉ viết 4096 byte tại một thời điểm?

Có cách nào thay thế cho fwrite() để ghi dữ liệu vào đường ống bằng cách sử dụng con trỏ FILE * không?

+0

Bạn có thể hiển thị mã cho chúng tôi không? – tuxuday

+1

@Shailesh_Tainwala: Bạn có thể viết mã của bạn bằng C++, nhưng đây là câu hỏi c chứ không phải là C++. 'fwrite()' là một hàm c, không phải là hàm C++. Tôi đã thêm thẻ c vào câu hỏi của bạn để bạn có thể có được đối tượng rộng hơn. –

Trả lời

8

4096 đến từ máy móc Linux làm nền tảng cho đường ống. Có hai nơi nó xảy ra. Một là khả năng của đường ống. Dung lượng là một trang hệ thống trên các phiên bản Linux cũ hơn, là 4096 byte trên máy tính 32 bit i386. (Trên các phiên bản hiện đại của Linux có dung lượng 64K.)

Địa điểm khác bạn sẽ gặp phải là vấn đề 4096 byte nằm trong hằng số được xác định PIPE_BUF, số byte được đảm bảo xử lý nguyên tử. Trên Linux, đây là 4096 byte. Ý nghĩa của giới hạn này phụ thuộc vào việc bạn đã đặt đường dẫn để chặn hoặc không chặn. Làm một man -S7 pipe cho tất cả các chi tiết đẫm máu.

Nếu bạn đang cố gắng trao đổi khối lượng lớn dữ liệu với tốc độ cao, bạn có thể muốn suy nghĩ lại về việc sử dụng đường ống. Bạn đang ở trên một hộp Linux, vì vậy bộ nhớ dùng chung là một tùy chọn. Bạn có thể sử dụng đường ống để gửi lượng dữ liệu tương đối nhỏ như một cơ chế báo hiệu.

+0

Một lựa chọn duy nhất khác của Linux là sử dụng open() và splice() thay vì fwrite(). –

4

Nếu bạn muốn thay đổi hành vi lưu vào bộ đệm, bạn phải thực hiện ngay sau fopen (hoặc trước bất kỳ I/O nào, cho các tập tin tiêu chuẩn stdin, stdout, stderr). Bạn cũng không muốn vô hiệu hóa bộ đệm và tự mình quản lý bộ đệm; thay vào đó, chỉ định bộ đệm 64K của bạn là setvbuf để có thể sử dụng đúng cách.

Nếu bạn thực sự muốn quản lý bộ đệm theo cách thủ công, không sử dụng stdio; sử dụng các mức độ thấp hơn open, writeclose cuộc gọi.

Các vấn đề liên quan